|
|
1.1 root 1: /*
1.1.1.3 root 2: Hatari - stMemory.c
1.1 root 3:
1.1.1.15 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1.1.3 root 6:
1.1.1.4 root 7: ST Memory access functions.
1.1 root 8: */
1.1.1.10 root 9: const char STMemory_fileid[] = "Hatari stMemory.c : " __DATE__ " " __TIME__;
1.1 root 10:
1.1.1.4 root 11: #include "stMemory.h"
1.1.1.6 root 12: #include "configuration.h"
13: #include "floppy.h"
1.1.1.10 root 14: #include "gemdos.h"
1.1.1.12 root 15: #include "ioMem.h"
1.1.1.10 root 16: #include "log.h"
1.1.1.7 root 17: #include "memory.h"
1.1.1.12 root 18: #include "memorySnapShot.h"
19: #include "tos.h"
20: #include "vdi.h"
1.1.1.17 root 21: #include "m68000.h"
1.1.1.19 root 22: #include "screen.h"
23: #include "video.h"
1.1.1.2 root 24:
1.1.1.7 root 25: /* STRam points to our ST Ram. Unless the user enabled SMALL_MEM where we have
26: * to save memory, this includes all TOS ROM and IO hardware areas for ease
27: * and emulation speed - so we create a 16 MiB array directly here.
28: * But when the user turned on ENABLE_SMALL_MEM, this only points to a malloc'ed
29: * buffer with the ST RAM; the ROM and IO memory will be handled separately. */
30: #if ENABLE_SMALL_MEM
31: Uint8 *STRam;
32: #else
33: Uint8 STRam[16*1024*1024];
34: #endif
1.1.1.4 root 35:
1.1.1.19 root 36: Uint32 STRamEnd; /* End of ST Ram, above this address is no-mans-land and ROM/IO memory */
37:
38:
39:
40: Uint32 RAM_Bank0_Size; /* Physical RAM on board in bank0 (in bytes) : 128, 512 or 2048 KB */
41: Uint32 RAM_Bank1_Size; /* Physical RAM on board in bank1 (in bytes) : 128, 512 or 2048 KB */
42:
43: Uint32 MMU_Bank0_Size; /* Logical MMU RAM size for bank0 (in bytes) : 128, 512 or 2048 KB */
44: Uint32 MMU_Bank1_Size; /* Logical MMU RAM size for bank1 (in bytes) : 128, 512 or 2048 KB */
45:
46: Uint8 MMU_Conf_Expected; /* Expected value for $FF8001 corresponding to ST RAM size if <= 4MB */
47:
48:
49: static void STMemory_MMU_ConfToBank ( Uint8 MMU_conf , Uint32 *pBank0 , Uint32 *pBank1 );
50: static int STMemory_MMU_Size ( Uint8 MMU_conf );
51: static int STMemory_MMU_Size_TT ( Uint8 MMU_conf );
52:
53: static Uint32 STMemory_MMU_Translate_Addr_STF ( Uint32 addr_logical , int RAM_Bank_Size , int MMU_Bank_Size );
54: static Uint32 STMemory_MMU_Translate_Addr_STE ( Uint32 addr_logical , int RAM_Bank_Size , int MMU_Bank_Size );
55:
56:
57:
58: /**
59: * Set default value for MMU bank size and RAM bank size
1.1.1.20! root 60: * NOTE : when using SMALL_MEM, IoMem will not be allocated yet on the first call
! 61: * so we default to 0x0.
! 62: * TODO [NP] : don't call STMemory_MMU_ConfToBank from here ? Better ensure STMemory_Reset()
! 63: * is called early enough.
1.1.1.19 root 64: */
65: void STMemory_Init ( int RAM_Size_Byte )
66: {
1.1.1.20! root 67: Uint8 val;
! 68:
1.1.1.19 root 69: /* Set default MMU bank size values */
1.1.1.20! root 70: #if ENABLE_SMALL_MEM
! 71: if ( IOmemory == NULL )
! 72: val = 0x0;
! 73: else
! 74: val = IoMem[ 0xff8001 ];
! 75: #else
! 76: val = IoMem[ 0xff8001 ];
! 77: #endif
! 78: //fprintf ( stderr , "STMemory_Init %d %x\n" , RAM_Size_Byte , val );
! 79: STMemory_MMU_ConfToBank ( val, &MMU_Bank0_Size, &MMU_Bank1_Size );
1.1.1.19 root 80:
81: if ( RAM_Size_Byte <= 0x400000 )
82: {
83: if ( STMemory_RAM_SetBankSize ( RAM_Size_Byte , &RAM_Bank0_Size , &RAM_Bank1_Size , &MMU_Conf_Expected ) == false )
84: {
1.1.1.20! root 85: Log_Printf(LOG_ERROR, "invalid RAM size %d KB for MMU banks\n", RAM_Size_Byte );
1.1.1.19 root 86: }
87: }
88: }
89:
90:
91: /*
92: * Reset the internal MMU/MCU used to configure address decoding for the RAM banks
93: * 0xFF8001 is set to 0 on cold reset but keep its value on warm reset
94: */
95: void STMemory_Reset ( bool bCold )
96: {
97: if ( bCold )
98: {
1.1.1.20! root 99: //fprintf ( stderr , "STMemory_Reset\n" );
1.1.1.19 root 100: IoMem[ 0xff8001 ] = 0x0;
101: STMemory_MMU_ConfToBank ( IoMem[ 0xff8001 ] , &MMU_Bank0_Size , &MMU_Bank1_Size );
102: }
103: }
1.1 root 104:
1.1.1.2 root 105:
1.1.1.7 root 106: /**
107: * Clear section of ST's memory space.
1.1.1.20! root 108: * @addr Destination Atari RAM address
! 109: * @len Number of bytes to clear
! 110: *
! 111: * Return true if whole clear was safe / valid.
1.1.1.7 root 112: */
1.1.1.20! root 113: bool STMemory_SafeClear(Uint32 addr, unsigned int len)
1.1 root 114: {
1.1.1.20! root 115: Uint32 end;
! 116:
! 117: if (STMemory_CheckAreaType(addr, len, ABFLAG_RAM))
! 118: {
! 119: memset(&STRam[addr], 0, len);
! 120: return true;
! 121: }
! 122: Log_Printf(LOG_WARN, "Invalid RAM clear range 0x%x+%i!\n", addr, len);
! 123:
! 124: for (end = addr + len; addr < end; addr++)
! 125: {
! 126: if (STMemory_CheckAreaType(addr, 1, ABFLAG_RAM))
! 127: STRam[addr] = 0;
! 128: }
! 129: return false;
1.1 root 130: }
131:
1.1.1.13 root 132: /**
133: * Copy given memory area safely to Atari RAM.
134: * If the memory area isn't fully within RAM, only the valid parts are written.
135: * Useful for all kinds of IO operations.
136: *
137: * addr - destination Atari RAM address
138: * src - source Hatari memory address
139: * len - number of bytes to copy
140: * name - name / description if this memory copy for error messages
141: *
142: * Return true if whole copy was safe / valid.
143: */
144: bool STMemory_SafeCopy(Uint32 addr, Uint8 *src, unsigned int len, const char *name)
145: {
146: Uint32 end;
147:
1.1.1.17 root 148: if ( STMemory_CheckAreaType ( addr, len, ABFLAG_RAM ) )
1.1.1.13 root 149: {
150: memcpy(&STRam[addr], src, len);
151: return true;
152: }
153: Log_Printf(LOG_WARN, "Invalid '%s' RAM range 0x%x+%i!\n", name, addr, len);
154:
155: for (end = addr + len; addr < end; addr++, src++)
156: {
1.1.1.17 root 157: if ( STMemory_CheckAreaType ( addr, 1, ABFLAG_RAM ) )
1.1.1.13 root 158: STRam[addr] = *src;
159: }
160: return false;
161: }
1.1.1.6 root 162:
1.1.1.19 root 163:
1.1.1.12 root 164: /**
165: * Save/Restore snapshot of RAM / ROM variables
166: * ('MemorySnapShot_Store' handles type)
167: */
168: void STMemory_MemorySnapShot_Capture(bool bSave)
169: {
170: MemorySnapShot_Store(&STRamEnd, sizeof(STRamEnd));
171:
1.1.1.19 root 172: /* After restoring RAM/MMU bank sizes we must call memory_map_Standard_RAM() */
173: MemorySnapShot_Store(&RAM_Bank0_Size, sizeof(RAM_Bank0_Size));
174: MemorySnapShot_Store(&RAM_Bank1_Size, sizeof(RAM_Bank1_Size));
175: MemorySnapShot_Store(&MMU_Bank0_Size, sizeof(MMU_Bank0_Size));
176: MemorySnapShot_Store(&MMU_Bank1_Size, sizeof(MMU_Bank1_Size));
177: MemorySnapShot_Store(&MMU_Conf_Expected, sizeof(MMU_Conf_Expected));
1.1.1.20! root 178:
1.1.1.12 root 179: /* Only save/restore area of memory machine is set to, eg 1Mb */
180: MemorySnapShot_Store(STRam, STRamEnd);
181:
182: /* And Cart/TOS/Hardware area */
183: MemorySnapShot_Store(&RomMem[0xE00000], 0x200000);
1.1.1.19 root 184:
1.1.1.20! root 185: /* Save/restore content of TT RAM if TTRamSize_KB != 0 */
! 186: if ( ConfigureParams.Memory.TTRamSize_KB > 0 )
! 187: MemorySnapShot_Store ( TTmemory , ConfigureParams.Memory.TTRamSize_KB*1024 );
! 188:
1.1.1.19 root 189: if ( !bSave )
190: memory_map_Standard_RAM ( MMU_Bank0_Size , MMU_Bank1_Size );
1.1.1.12 root 191: }
192:
193:
1.1.1.7 root 194: /**
195: * Set default memory configuration, connected floppies, memory size and
196: * clear the ST-RAM area.
197: * As TOS checks hardware for memory size + connected devices on boot-up
198: * we set these values ourselves and fill in the magic numbers so TOS
199: * skips these tests.
200: */
1.1.1.6 root 201: void STMemory_SetDefaultConfig(void)
202: {
203: int i;
1.1.1.17 root 204: int screensize, limit;
205: int memtop, phystop;
1.1.1.19 root 206: Uint8 MMU_Conf_Force;
1.1.1.13 root 207: Uint8 nFalcSysCntrl;
208:
1.1.1.7 root 209: if (bRamTosImage)
210: {
211: /* Clear ST-RAM, excluding the RAM TOS image */
1.1.1.20! root 212: STMemory_SafeClear(0x00000000, TosAddress);
! 213: STMemory_SafeClear(TosAddress + TosSize, STRamEnd - TosAddress - TosSize);
1.1.1.7 root 214: }
1.1.1.6 root 215: else
1.1.1.7 root 216: {
217: /* Clear whole ST-RAM */
1.1.1.20! root 218: STMemory_SafeClear(0x00000000, STRamEnd);
1.1.1.7 root 219: }
1.1.1.6 root 220:
221: /* Mirror ROM boot vectors */
222: STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress));
223: STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4));
224:
1.1.1.14 root 225: /* Fill in magic numbers to bypass TOS' memory tests for faster boot or
1.1.1.17 root 226: * if VDI resolution is enabled or if more than 4 MB of ram are used
227: * or if TT RAM added in Falcon mode.
1.1.1.14 root 228: * (for highest compatibility, those tests should not be bypassed in
229: * the common STF/STE cases as some programs like "Yolanda" rely on
230: * the RAM content after those tests) */
1.1.1.17 root 231: if ( ConfigureParams.System.bFastBoot
232: || bUseVDIRes
1.1.1.19 root 233: || ( ConfigureParams.Memory.STRamSize_KB > (4*1024) && !bIsEmuTOS )
1.1.1.18 root 234: || ( Config_IsMachineTT() && ConfigureParams.System.bAddressSpace24 && !bIsEmuTOS )
235: || ( Config_IsMachineFalcon() && TTmemory && !bIsEmuTOS) )
1.1.1.14 root 236: {
237: /* Write magic values to sysvars to signal valid config */
238: STMemory_WriteLong(0x420, 0x752019f3); /* memvalid */
239: STMemory_WriteLong(0x43a, 0x237698aa); /* memval2 */
240: STMemory_WriteLong(0x51a, 0x5555aaaa); /* memval3 */
1.1.1.17 root 241:
242: /* If ST RAM detection is bypassed, we must also force TT RAM config if enabled */
243: if ( TTmemory )
244: STMemory_WriteLong ( 0x5a4 , 0x01000000 + TTmem_size ); /* ramtop */
245: else
246: STMemory_WriteLong ( 0x5a4 , 0 ); /* ramtop */
247: STMemory_WriteLong ( 0x5a8 , 0x1357bd13 ); /* ramvalid */
248:
249: /* On Falcon, set bit6=1 at $ff8007 to simulate a warm start */
250: /* (else memory detection is not skipped after a cold start/reset) */
1.1.1.18 root 251: if (Config_IsMachineFalcon())
1.1.1.17 root 252: STMemory_WriteByte ( 0xff8007, IoMem_ReadByte(0xff8007) | 0x40 );
253:
254: /* On TT, set bit0=1 at $ff8e09 to simulate a warm start */
255: /* (else memory detection is not skipped after a cold start/reset) */
1.1.1.18 root 256: if (Config_IsMachineTT())
1.1.1.17 root 257: STMemory_WriteByte ( 0xff8e09, IoMem_ReadByte(0xff8e09) | 0x01 );
1.1.1.19 root 258:
259: /* TOS 3.0x and 4.0x check _hz200 and always do a memory test
260: * if the machine runs less than 80 seconds */
261: if (!bIsEmuTOS && TosVersion >= 0x300)
262: STMemory_WriteLong(0x4ba, 80 * 200);
1.1.1.14 root 263: }
1.1.1.6 root 264:
1.1.1.20! root 265: /* VDI screen size. Needs to leave extra space for 16x16 area
! 266: * between end of screen & RAM end, or <= v2.x TOS versions
! 267: * crash when mouse moves to bottom right corner of screen.
! 268: */
! 269: screensize = VDIWidth * VDIHeight / 8 * VDIPlanes + 16*16*VDIPlanes/8;
! 270: /* Use 32 kiB in normal screen mode or when the screen size
! 271: * is smaller than 32 kiB
! 272: */
1.1.1.7 root 273: if (!bUseVDIRes || screensize < 0x8000)
274: screensize = 0x8000;
1.1.1.17 root 275: /* mem top - upper end of user memory (right before the screen memory)
1.1.1.20! root 276: * memtop / phystop must be divisible by 512 or TOS crashes
! 277: */
1.1.1.7 root 278: memtop = (STRamEnd - screensize) & 0xfffffe00;
1.1.1.17 root 279: /* phys top - 32k gap causes least issues with apps & TOS
280: * as that's the largest _common_ screen size. EmuTOS behavior
281: * depends on machine type.
282: *
283: * TODO: what to do about _native_ TT & Videl resolutions
284: * which size is >32k? Should memtop be adapted also for
285: * those?
286: */
287: switch (ConfigureParams.System.nMachineType)
288: {
289: case MACHINE_FALCON:
290: /* TOS v4 doesn't work with VDI mode (yet), and
291: * EmuTOS works with correct gap, so use that */
292: phystop = STRamEnd;
293: break;
294: case MACHINE_TT:
295: /* For correct TOS v3 memory detection, phystop should be
296: * at the end of memory, not at memtop + 32k.
297: *
298: * However:
299: * - TOS v3 crashes/hangs if phystop-memtop gap is larger
300: * than largest real HW screen size (150k)
301: * - NVDI hangs if gap is larger than 32k in any other than
302: * monochrome mode
303: */
304: if (VDIPlanes == 1)
305: limit = 1280*960/8;
306: else
307: limit = 0x8000;
308: if (screensize > limit)
309: {
310: phystop = memtop + limit;
1.1.1.20! root 311: Log_Printf(LOG_WARN, "too large VDI mode for TOS v3 memory detection to work correctly!\n");
1.1.1.17 root 312: }
313: else
314: phystop = STRamEnd;
315: break;
316: default:
317: phystop = memtop + 0x8000;
318: }
1.1.1.7 root 319: STMemory_WriteLong(0x436, memtop);
1.1.1.17 root 320: STMemory_WriteLong(0x42e, phystop);
321: if (bUseVDIRes)
1.1.1.19 root 322: {
323: Log_Printf(LOG_DEBUG, "VDI mode memtop: 0x%x, phystop: 0x%x (screensize: %d kB, memtop->phystop: %d kB)\n",
324: memtop, phystop, (screensize+511) / 1024, (phystop-memtop+511) / 1024);
325: }
1.1.1.6 root 326:
1.1.1.19 root 327: /* If possible we don't override memory detection, TOS will do it
328: * (in that case MMU/MCU can be correctly emulated, and we do nothing
329: * and let TOS do its own memory tests using $FF8001) */
330: if (!(Config_IsMachineST() || Config_IsMachineSTE())
331: || ConfigureParams.System.bFastBoot || bUseVDIRes
332: || ConfigureParams.Memory.STRamSize_KB > 4*1024)
333: {
334: /* Set memory controller byte according to different memory sizes */
335: /* Setting per bank : %00=128k %01=512k %10=2Mb %11=reserved. - e.g. %1010 means 4Mb */
336: if (ConfigureParams.Memory.STRamSize_KB <= 4*1024)
337: MMU_Conf_Force = MMU_Conf_Expected;
338: else
339: MMU_Conf_Force = 0x0f;
340: STMemory_WriteByte(0x424, MMU_Conf_Force);
341: IoMem_WriteByte(0xff8001, MMU_Conf_Force);
342: }
1.1.1.6 root 343:
1.1.1.18 root 344: if (Config_IsMachineFalcon())
1.1.1.7 root 345: {
1.1.1.13 root 346: /* Set the Falcon memory and monitor configuration register:
347:
1.1.1.15 root 348: $ffff8006.b [R] 76543210 Monitor-memory
349: ||||||||
350: |||||||+- RAM Wait Status
351: ||||||| 0 = 1 Wait (default)
352: ||||||| 1 = 0 Wait
353: ||||||+-- Video Bus size ???
354: |||||| 0 = 16 Bit
355: |||||| 1 = 32 Bit (default)
356: ||||++--- ROM Wait Status
357: |||| 00 = Reserved
358: |||| 01 = 2 Wait (default)
359: |||| 10 = 1 Wait
360: |||| 11 = 0 Wait
361: ||++----- Falcon Memory
362: || 00 = 1 MB
363: || 01 = 4 MB
364: || 10 = 14 MB
365: || 11 = no boot !
366: ++------- Monitor-Typ
367: 00 - Monochrome (SM124)
368: 01 - Color (SC1224)
369: 10 - VGA Color
370: 11 - Television
1.1.1.13 root 371:
372: Bit 1 seems not to be well documented. It's used by TOS at bootup to compute the memory size.
373: After some tests, I get the following RAM values (Bits 5, 4, 1 are involved) :
374:
375: 00 = 512 Ko 20 = 8192 Ko
376: 02 = 1024 Ko 22 = 14366 Ko
377: 10 = 2048 Ko 30 = Illegal
378: 12 = 4096 Ko 32 = Illegal
379:
380: I use these values for Hatari's emulation.
381: I also set the bit 3 and 2 at value 01 are mentioned in the register description.
382: */
383:
1.1.1.19 root 384: if (ConfigureParams.Memory.STRamSize_KB == 14*1024) /* 14 Meg */
1.1.1.13 root 385: nFalcSysCntrl = 0x26;
1.1.1.19 root 386: else if (ConfigureParams.Memory.STRamSize_KB == 8*1024) /* 8 Meg */
1.1.1.13 root 387: nFalcSysCntrl = 0x24;
1.1.1.19 root 388: else if (ConfigureParams.Memory.STRamSize_KB == 4*1024) /* 4 Meg */
1.1.1.7 root 389: nFalcSysCntrl = 0x16;
1.1.1.19 root 390: else if (ConfigureParams.Memory.STRamSize_KB == 2*1024) /* 2 Meg */
1.1.1.7 root 391: nFalcSysCntrl = 0x14;
1.1.1.19 root 392: else if (ConfigureParams.Memory.STRamSize_KB == 1024) /* 1 Meg */
1.1.1.7 root 393: nFalcSysCntrl = 0x06;
394: else
1.1.1.19 root 395: nFalcSysCntrl = 0x04; /* 512 Ko */
1.1.1.13 root 396:
1.1.1.8 root 397: switch(ConfigureParams.Screen.nMonitorType) {
1.1.1.13 root 398: case MONITOR_TYPE_TV:
399: nFalcSysCntrl |= FALCON_MONITOR_TV;
400: break;
401: case MONITOR_TYPE_VGA:
402: nFalcSysCntrl |= FALCON_MONITOR_VGA;
403: break;
404: case MONITOR_TYPE_RGB:
405: nFalcSysCntrl |= FALCON_MONITOR_RGB;
406: break;
407: case MONITOR_TYPE_MONO:
408: nFalcSysCntrl |= FALCON_MONITOR_MONO;
409: break;
1.1.1.7 root 410: }
411: STMemory_WriteByte(0xff8006, nFalcSysCntrl);
412: }
413:
1.1.1.6 root 414: /* Set TOS floppies */
415: STMemory_WriteWord(0x446, nBootDrive); /* Boot up on A(0) or C(2) */
416:
1.1.1.16 root 417: /* Create connected drives mask (only for harddrives, don't change floppy drive detected by TOS) */
1.1.1.10 root 418: ConnectedDriveMask = STMemory_ReadLong(0x4c2); // Get initial drive mask (see what TOS thinks)
419: if (GEMDOS_EMU_ON)
1.1.1.6 root 420: {
1.1.1.10 root 421: for (i = 0; i < MAX_HARDDRIVES; i++)
422: {
423: if (emudrives[i] != NULL) // Is this GEMDOS drive enabled?
1.1.1.12 root 424: ConnectedDriveMask |= (1 << emudrives[i]->drive_number);
1.1.1.10 root 425: }
1.1.1.6 root 426: }
427: /* Set connected drives system variable.
428: * NOTE: some TOS images overwrite this value, see 'OpCode_SysInit', too */
429: STMemory_WriteLong(0x4c2, ConnectedDriveMask);
430: }
1.1.1.17 root 431:
432:
433: /**
434: * Check that the region of 'size' starting at 'addr' is entirely inside
435: * a memory bank of the same memory type
436: */
437: bool STMemory_CheckAreaType ( Uint32 addr , int size , int mem_type )
438: {
439: addrbank *pBank;
440:
441: pBank = &get_mem_bank ( addr );
442:
443: if ( ( pBank->flags & mem_type ) == 0 )
444: {
1.1.1.19 root 445: Log_Printf(LOG_ERROR, "pBank flags mismatch: 0x%x & 0x%x (RAM = 0x%x)\n",
446: pBank->flags, mem_type, ABFLAG_RAM);
1.1.1.17 root 447: return false;
448: }
449:
450: return pBank->check ( addr , size );
451: }
452:
453:
454: /**
455: * Check if an address points to a memory region that causes bus error
456: * This is used for blitter and other DMA chips that should not cause
457: * a bus error when accessing such regions (on the contrary of the CPU)
458: * Returns true if region gives bus error
459: */
460: bool STMemory_CheckRegionBusError ( Uint32 addr )
461: {
462: return memory_region_bus_error ( addr );
463: }
464:
465:
466: /**
467: * Convert an address in the ST memory space to a direct pointer
468: * in the host memory.
469: *
470: * NOTE : Using this function to get a direct pointer to the memory should
471: * only be used after doing a call to valid_address or STMemory_CheckAreaType
472: * to ensure we don't try to access a non existing memory region.
473: * Basically, this function should be used only for addr in RAM or in ROM
474: */
475: void *STMemory_STAddrToPointer ( Uint32 addr )
476: {
477: Uint8 *p;
478:
479: if ( ConfigureParams.System.bAddressSpace24 == true )
480: addr &= 0x00ffffff; /* Only keep the 24 lowest bits */
481:
482: p = get_real_address ( addr );
483: return (void *)p;
484: }
485:
486:
487:
488: /**
489: * Those functions are directly accessing the memory of the corresponding
490: * bank, without calling its dedicated access handlers (they won't generate
491: * bus errors or address errors or update IO values)
492: * They are only used for internal work of the emulation, such as debugger,
493: * log to print the content of memory, intercepting gemdos/bios calls, ...
494: *
495: * These functions are not used by the CPU emulation itself, see memory.c
496: * for the functions that emulate real memory accesses.
497: */
498:
499: /**
500: * Write long/word/byte into memory.
501: * NOTE - value will be converted to 68000 endian
502: */
503: void STMemory_Write ( Uint32 addr , Uint32 val , int size )
504: {
505: addrbank *pBank;
506: Uint8 *p;
507:
508: //printf ( "mem direct write %x %x %d\n" , addr , val , size );
509: pBank = &get_mem_bank ( addr );
510:
511: if ( pBank->baseaddr == NULL )
512: return; /* No real memory, do nothing */
513:
514: addr -= pBank->start & pBank->mask;
515: addr &= pBank->mask;
516: p = pBank->baseaddr + addr;
517:
518: /* We modify the memory, so we flush the instr/data caches if needed */
519: M68000_Flush_All_Caches ( addr , size );
520:
521: if ( size == 4 )
522: do_put_mem_long ( p , val );
523: else if ( size == 2 )
524: do_put_mem_word ( p , (Uint16)val );
525: else
526: *p = (Uint8)val;
527: }
528:
529: void STMemory_WriteLong ( Uint32 addr , Uint32 val )
530: {
531: STMemory_Write ( addr , val , 4 );
532: }
533:
534: void STMemory_WriteWord ( Uint32 addr , Uint16 val )
535: {
536: STMemory_Write ( addr , (Uint32)val , 2 );
537: }
538:
539: void STMemory_WriteByte ( Uint32 addr , Uint8 val )
540: {
541: STMemory_Write ( addr , (Uint32)val , 1 );
542: }
543:
544:
545: /**
546: * Read long/word/byte from memory.
547: * NOTE - value will be converted to 68000 endian
548: */
549: Uint32 STMemory_Read ( Uint32 addr , int size )
550: {
551: addrbank *pBank;
552: Uint8 *p;
553:
554: //printf ( "mem direct read %x %d\n" , addr , size );
555: pBank = &get_mem_bank ( addr );
556:
557: if ( pBank->baseaddr == NULL )
558: return 0; /* No real memory, return 0 */
559:
560: addr -= pBank->start & pBank->mask;
561: addr &= pBank->mask;
562: p = pBank->baseaddr + addr;
563:
564: if ( size == 4 )
565: return do_get_mem_long ( p );
566: else if ( size == 2 )
567: return (Uint32)do_get_mem_word ( p );
568: else
569: return (Uint32)*p;
570: }
571:
572: Uint32 STMemory_ReadLong ( Uint32 addr )
573: {
574: return (Uint32) STMemory_Read ( addr , 4 );
575: }
576:
577: Uint16 STMemory_ReadWord ( Uint32 addr )
578: {
579: return (Uint16)STMemory_Read ( addr , 2 );
580: }
581:
582: Uint8 STMemory_ReadByte ( Uint32 addr )
583: {
584: return (Uint8)STMemory_Read ( addr , 1 );
585: }
586:
1.1.1.19 root 587:
588:
589:
590: /*
591:
592: Description of the MMU used in STF/STE to address RAM :
593: -------------------------------------------------------
594:
595: Atari's computer used their own custom MMU to map logical addresses to physical RAM or to hardware registers.
596:
597: The CAS/RAS mappings are based on Christian Zietz research to reverse the MMU's inner work, as well as by using
598: some custom programs on ST to change MMU configs and see how RAM content is modified when the shifter
599: displays it on screen.
600:
601:
602: When addressing RAM, the MMU will convert a logical address into the corresponding RAS0/CAS0L/CAS0H or
603: RAS1/CAS1L/CAS1H (using the MAD0-MAD9 signals), which will select the RAM chips needed to store the data.
604: Data are handled as 16 bits.
605:
606: The mapping between a logical address and a physical bank/memory chips depends on the ST model.
607:
608:
609: STF :
610: A bank is made of 16 chips of 1 bit memory. The MMU can use chips of 64 kbits, 256 kbits or 1024 kbits, which
611: gives a bank size of 128 KB, 512 KB or 2048 KB (for example 16 chips of 41256 RAM will give 512 KB)
612:
613: Over the years, several revisions of the MMU were made :
614: - C025912-20 : maker unknown, found in very first STs, banks 0 and 1 can be different
615: - C025912-38 : made by Ricoh, found in most STFs, banks 0 and 1 can be different
616: - C100109-001 : made by IMP, found in more recent STFs ; although different values can be set
617: for banks 0 and 1, bank 0 setting will always apply to the 2 banks (so, 2.5 MB config is not possible)
618:
619:
620: STE :
621: Each bank is made of 2 chips of SIMM RAM using 8 bit memory (instead of 1 bit on STF).
622:
623: The MMU was integrated into a bigger chip, the GST/MCU.
624: As for the STF's IMP MMU, the MCU will only use bank 0 setting for both banks
625: - C300589-001 : STE
626: - C302183-001 : Mega STE
627:
628:
629: Regarding physical RAM on STF/STE, bank 1 can be empty or not, but bank 0 must always be filled (due to the way TOS
630: checks for available RAM and size, memory detection would give wrong results if bank 0 was empty and bank 1 was filled,
631: as bank 0 would be considered as 128 KB in such cases)
632:
633:
634: TT :
635: The TT had several possibilities for memory extensions :
636: - on board "slow" dual purpose (system/shifter) memory : 16 chips of 4 bit memory using 256 kbits or 1024 kbits modules
637: Most (all ?) TT were shipped with 2 MB of on board RAM (ie 256 kbits chips).
638: Using 1024 kbits chips, it's possible to get 8 MB of RAM
639: - daughterboard "slow" dual purpose memory : similar to on board RAM, you get 2 MB or 8 MB
640: - CA400313-xxx : 2 MB board by Atari
641: - CA401059-xxx : 2 or 8 MB board by Atari
642: - extension board using the VME BUS ; such RAM can't be used for shifter and it's slower than fast RAM
1.1.1.20! root 643: - fast RAM : up to 512 MB of "fast" single purpose RAM could be added. It can't be used for shifter,
1.1.1.19 root 644: but it can be used with TT DMA specific chips. As this RAM is not shared with the shifter, it's much faster
645: (there's no bus cycle penalty every 250 ns as with dual purpose memory)
646:
647: As tested by some people, if the TT has 8 MB on board and 8 MB on the daughterboard of "slow" dual purpose RAM,
648: then the resulting memory will be limited to 10 MB (addr 0x000000 to 0xA00000) and not to 14 or 16 MB,
649: the rest is reserved for cartridge, VME, ROM, IO regs
650:
651:
652: MMU configuration at $FF8001 :
653: This register is used to specify the memory bank sizes used by the MMU to translate logical addresses
654: into physical ones. Under normal operations, it should match the size of the physical RAM.
655:
656: STF/STE : bits 2-3 = size of bank 0 bits 0-1 = size of bank 1
657: bank size : 00 = 128 KB 01=512 KB 10=2048 KB 11=reserved
658:
659: TT : only bit 1 is used (there's only 1 bank)
660: bank size : 0 = 2 MB (uses 256 kbits chips) 1 = 8 MB (uses 1024 kits chips)
661:
662: */
663:
664:
665:
666:
667: static void STMemory_MMU_ConfToBank ( Uint8 MMU_conf , Uint32 *pBank0 , Uint32 *pBank1 )
668: {
669: if ( Config_IsMachineTT() )
670: {
671: *pBank0 = STMemory_MMU_Size_TT ( ( MMU_conf >> 1 ) & 1 );
672: *pBank1 = 0;
673: }
674:
675: else
676: {
677: *pBank0 = STMemory_MMU_Size ( ( MMU_conf >> 2 ) & 3 );
678:
679: /* - STF with non-IMP MMU can have 2 different size of banks */
680: /* - STF with IMP MMU and STE use bank0 value for the 2 banks (ie bank1=bank0 in all cases) */
681: if ( Config_IsMachineST() )
682: *pBank1 = STMemory_MMU_Size ( MMU_conf & 3 );
683: else
684: *pBank1 = MMU_Bank0_Size;
685: }
686: }
687:
688:
689:
690:
691: /**
692: * Return the number of bytes for a given MMU bank configuration on STF/STE
693: * Possible values are 00, 01 or 10
694: */
695: static int STMemory_MMU_Size ( Uint8 MMU_conf )
696: {
697: if ( MMU_conf == 0 ) return MEM_BANK_SIZE_128;
698: else if ( MMU_conf == 1 ) return MEM_BANK_SIZE_512;
699: else if ( MMU_conf == 2 ) return MEM_BANK_SIZE_2048;
700: else return 0; /* invalid */
701: }
702:
703:
704:
705:
706: /**
707: * Return the number of bytes for a given MMU bank configuration on TT
708: * Possible values are 0 or 1
709: */
710: static int STMemory_MMU_Size_TT ( Uint8 MMU_conf )
711: {
712: if ( MMU_conf == 0 ) return MEM_BANK_SIZE_2048;
713: else return MEM_BANK_SIZE_8192;
714: }
715:
716:
717:
718:
719: /**
720: * Read the MMU banks configuration at $FF80001
721: */
722: void STMemory_MMU_Config_ReadByte ( void )
723: {
724: int FrameCycles, HblCounterVideo, LineCycles;
725:
726: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
727:
728: LOG_TRACE(TRACE_MEM, "mmu read memory config ff8001 val=0x%02x mmu_bank0=%d KB mmu_bank1=%d KB VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
729: IoMem[ 0xff8001 ] , MMU_Bank0_Size/1024 , MMU_Bank1_Size/1024 ,
730: nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
731: }
732:
733:
734:
735:
736: /**
737: * Write to the MMU banks configuration at $FF80001
738: * When value is changed, we remap the RAM bank into our STRam[] buffer
739: * and enable addresses translation if necessary
740: */
741: void STMemory_MMU_Config_WriteByte ( void )
742: {
743: int FrameCycles, HblCounterVideo, LineCycles;
744:
745: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
746:
747: STMemory_MMU_ConfToBank ( IoMem[ 0xff8001 ] , &MMU_Bank0_Size , &MMU_Bank1_Size );
748:
749: memory_map_Standard_RAM ( MMU_Bank0_Size , MMU_Bank1_Size );
750:
751: LOG_TRACE(TRACE_MEM, "mmu write memory config ff8001 val=0x%02x mmu_bank0=%d KB mmu_bank1=%d KB VBL=%d video_cyc=%d %d@%d pc=%x\n" ,
752: IoMem[ 0xff8001 ] , MMU_Bank0_Size/1024 , MMU_Bank1_Size/1024 ,
753: nVBLs , FrameCycles, LineCycles, HblCounterVideo , M68000_GetPC() );
754: }
755:
756:
757:
758:
759: /**
760: * Check if "TotalMem" bytes is a valid value for the ST RAM size
761: * and return the corresponding number of KB.
762: * TotalMem can be expressed in MB if <= 14, else in KB
763: * We list the most usual sizes, some more could be added if needed
764: * Some values are not standard for all machines and will also require
765: * to patch TOS to bypass RAM detection.
766: *
767: * If TotalMem is not a valid ST RAM size, return -1
768: */
769: int STMemory_RAM_Validate_Size_KB ( int TotalMem )
770: {
771: /* Old format where ST RAM size was in MB between 0 and 14 */
772: if ( TotalMem == 0 )
1.1.1.20! root 773: return 512;
1.1.1.19 root 774: else if ( TotalMem <= 14 )
775: return TotalMem * 1024;
776:
777: /* New format where ST RAM size is in KB */
778: else if ( ( TotalMem == 128 ) || ( TotalMem == 256 ) || ( TotalMem == 512 ) || ( TotalMem == 640 )
779: || ( TotalMem == 1024 ) || ( TotalMem == 2048 ) || ( TotalMem == 2176 ) || ( TotalMem == 2560 )
780: || ( TotalMem == 4096 ) || ( TotalMem == 8*1024 ) || ( TotalMem == 14*1024 ) )
781: return TotalMem;
782:
783: return -1;
784: }
785:
786:
787:
788:
789: /**
790: * For TotalMem <= 4MB, set the corresponding size in bytes for RAM bank 0 and RAM bank 1.
791: * Also set the corresponding MMU value to expect at $FF8001
792: * Return true if TotalMem is a valid ST RAM size for the MMU, else false
793: */
794: bool STMemory_RAM_SetBankSize ( int TotalMem , Uint32 *pBank0_Size , Uint32 *pBank1_Size , Uint8 *pMMU_Conf )
795: {
796: int TotalMem_KB = TotalMem / 1024;
797:
798: /* Check some possible RAM size configurations in KB */
799: if ( TotalMem_KB == 128 ) { *pBank0_Size = 128; *pBank1_Size = 0; *pMMU_Conf = (0<<2) + 0; } /* 0x0 : 128 + 0 */
800: else if ( TotalMem_KB == 256 ) { *pBank0_Size = 128; *pBank1_Size = 128; *pMMU_Conf = (0<<2) + 0; } /* 0x0 : 128 + 128 */
801: else if ( TotalMem_KB == 512 ) { *pBank0_Size = 512; *pBank1_Size = 0; *pMMU_Conf = (1<<2) + 0; } /* 0x4 : 512 + 0 */
802: else if ( TotalMem_KB == 640 ) { *pBank0_Size = 512; *pBank1_Size = 128; *pMMU_Conf = (1<<2) + 0; } /* 0x4 : 512 + 128 */
803: else if ( TotalMem_KB == 1024 ) { *pBank0_Size = 512; *pBank1_Size = 512; *pMMU_Conf = (1<<2) + 1; } /* 0x5 : 512 + 512 */
804: else if ( TotalMem_KB == 2048 ) { *pBank0_Size = 2048; *pBank1_Size = 0; *pMMU_Conf = (2<<2) + 0; } /* 0x8 : 2048 + 0 */
805: else if ( TotalMem_KB == 2176 ) { *pBank0_Size = 2048; *pBank1_Size = 128; *pMMU_Conf = (2<<2) + 0; } /* 0x8 : 2048 + 128 */
806: else if ( TotalMem_KB == 2560 ) { *pBank0_Size = 2048; *pBank1_Size = 512; *pMMU_Conf = (2<<2) + 1; } /* 0x9 : 2048 + 512 */
807: else if ( TotalMem_KB == 4096 ) { *pBank0_Size = 2048; *pBank1_Size = 2048; *pMMU_Conf = (2<<2) + 2; } /* 0xA : 2048 + 2048 */
808:
809: else
810: {
811: Log_Printf(LOG_ERROR, "Invalid RAM size %d KB for MMU banks\n", TotalMem_KB);
812: return false;
813: }
814:
815: Log_Printf(LOG_DEBUG, "STMemory_RAM_SetBankSize total=%d KB bank0=%d KB bank1=%d KB MMU=%x\n",
816: TotalMem_KB, *pBank0_Size, *pBank1_Size, *pMMU_Conf);
817: *pBank0_Size *= 1024;
818: *pBank1_Size *= 1024;
819: return true;
820: }
821:
822:
823:
824:
825: /**
826: * STF : translate a logical address (as used by the CPU, DMA or the shifter) into a physical inside
827: * the corresponding RAM bank using the RAS/CAS signal.
828: * The STF MMU maps a 21 bit address (bits A20 .. A0) as follow :
829: * - A0 : used to select low/high byte of a 16 bit word
830: * - A1 ... A10 -> RAS0 ... RAS9
831: * - CASx :
832: * - if MMU set to 2 MB, then A11 ... A20 -> CAS0 ... CAS9
833: * - if MMU set to 512 KB, then A10 ... A18 -> CAS0 ... CAS8
834: * - if MMU set to 128 KB, then A9 ... A16 -> CAS0 ... CAS7
835: *
836: * [NP] As seen on a real STF (and confirmed by analyzing the STF's MMU), there's a special case
837: * when bank0 is set to 128 KB and bank 1 is set to 2048 KB : the region between $40000 and $80000 will
838: * not be mapped to any RAM at all, but will point to a "void" region ; this looks like a bug in the MMU's logic,
839: * maybe not handled by Atari because this bank combination is unlikely to be used in real machines.
840: */
841: static Uint32 STMemory_MMU_Translate_Addr_STF ( Uint32 addr_logical , int RAM_Bank_Size , int MMU_Bank_Size )
842: {
843: Uint32 addr;
844:
845:
846: if ( RAM_Bank_Size == MEM_BANK_SIZE_2048 )
847: {
848: /* RAM modules use lines MAD0-MAD9, C9/C8/R9/R8 exist : 21 bits per address in bank */
849: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
850: {
851: /* 21 bit address is mapped to 21 bits : */
852: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
853: /* C C C C C C C C C C R R R R R R R R R R X */
854: /* 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X */
855: addr = addr_logical;
856: }
857: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
858: {
859: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
860: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
861: /* . . C C C C C C C C C R R R R R R R R R X */
862: /* . . 8 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 X */
863: addr = ( ( addr_logical & 0xffc00 ) << 1 )
864: | ( addr_logical & 0x7ff ); /* add C9=A19 and R9=A10 */
865: }
866: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
867: {
868: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
869: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
870: /* . . . . C C C C C C C C R R R R R R R R X */
871: /* . . . . 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 X */
872: addr = ( ( addr_logical & 0x7fe00 ) << 2 )
873: | ( addr_logical & 0x7ff ); /* add C9=A18 C8=A17 and R9=A10 R8=A9 */
874: }
875: }
876:
877: else if ( RAM_Bank_Size == MEM_BANK_SIZE_512 )
878: {
879: /* RAM modules use lines MAD0-MAD8, C9/R9 don't exist, C8/R8 exist : 19 bits per address in bank */
880: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
881: {
882: /* 21 bit address is mapped to 21 bits : */
883: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
884: /* C C C C C C C C C C R R R R R R R R R R X */
885: /* 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X */
886: addr = ( ( addr_logical & 0xff800 ) >> 1 ) | ( addr_logical & 0x3ff ); /* remove C9/R9 */
887: }
888: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
889: {
890: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
891: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
892: /* . . C C C C C C C C C R R R R R R R R R X */
893: /* . . 8 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 X */
894: addr = addr_logical;
895: }
896: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
897: {
898: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
899: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
900: /* . . . . C C C C C C C C R R R R R R R R X */
901: /* . . . . 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 X */
902: addr = ( ( addr_logical & 0x3fe00 ) << 1 )
903: | ( addr_logical & 0x3ff ); /* add C8=A17 and R8=A9 */
904: }
905: }
906:
907: else /* ( RAM_Bank_Size == MEM_BANK_SIZE_128 ) */
908: {
909: /* RAM modules use lines MAD0-MAD7, C9/C8/R9/R8 don't exist : 17 bits per address in bank */
910: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
911: {
912: /* 21 bit address is mapped to 21 bits : */
913: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
914: /* C C C C C C C C C C R R R R R R R R R R X */
915: /* 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 X */
916: addr = ( ( addr_logical & 0x7f800 ) >> 2 ) | ( addr_logical & 0x1ff ); /* remove C9/C8/R9/R8 */
917: }
918: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
919: {
920: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
921: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
922: /* . . C C C C C C C C C R R R R R R R R R X */
923: /* . . 8 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 X */
924: addr = ( ( addr_logical & 0x3fc00 ) >> 1 ) | ( addr_logical & 0x1ff ); /* remove C8/R8 */
925: }
926: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
927: {
928: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
929: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
930: /* . . . . C C C C C C C C R R R R R R R R X */
931: /* . . . . 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 X */
932: addr = addr_logical;
933: }
934: }
935:
936:
937: addr &= ( RAM_Bank_Size - 1 ); /* Keep address inside RAM bank size */
938: return addr;
939: }
940:
941:
942:
943:
944: /**
945: * STE : translate a logical address (as used by the CPU, DMA or the shifter) into a physical inside
946: * the corresponding RAM bank using the RAS/CAS signal.
947: * The STE MMU maps a 21 bit address (bits A20 .. A0) as follow :
948: * - A0 : used to select low/high byte of a 16 bit word
949: * - A1 ... A20 -> RAS0 CAS0 RAS1 CAS1 ... RAS9 CAS9
950: *
951: * Note : the following code uses 9 cases for readability and to compare with STF, but it could be
952: * largely reduced as many cases are common.
953: */
954: static Uint32 STMemory_MMU_Translate_Addr_STE ( Uint32 addr_logical , int RAM_Bank_Size , int MMU_Bank_Size )
955: {
956: Uint32 addr;
957:
958:
959: if ( RAM_Bank_Size == MEM_BANK_SIZE_2048 )
960: {
961: /* RAM modules use lines MAD0-MAD9, C9/C8/R9/R8 exist : 21 bits per address in bank */
962: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
963: {
964: /* 21 bit address is mapped to 21 bits : */
965: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
966: /* C R C R C R C R C R C R C R C R C R C R X */
967: /* 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
968: addr = addr_logical;
969: }
970: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
971: {
972: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
973: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
974: /* . . C R C R C R C R C R C R C R C R C R X */
975: /* . . 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
976: addr = ( addr_logical & 0x1fffff ); /* add C9=A20 and R9=A19 */
977: }
978: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
979: {
980: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
981: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
982: /* . . . . C R C R C R C R C R C R C R C R X */
983: /* . . . . 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
984: addr = ( addr_logical & 0x1fffff ); /* add C9=A20 C8=A18 and R9=A19 R8=A17 */
985: }
986: }
987:
988: else if ( RAM_Bank_Size == MEM_BANK_SIZE_512 )
989: {
990: /* RAM modules use lines MAD0-MAD8, C9/R9 don't exist, C8/R8 exist : 19 bits per address in bank */
991: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
992: {
993: /* 21 bit address is mapped to 21 bits : */
994: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
995: /* C R C R C R C R C R C R C R C R C R C R X */
996: /* 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
997: addr = ( addr_logical & 0x7ffff ); /* remove C9/R9 */
998: }
999: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
1000: {
1001: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
1002: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
1003: /* . . C R C R C R C R C R C R C R C R C R X */
1004: /* . . 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
1005: addr = addr_logical;
1006: }
1007: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
1008: {
1009: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
1010: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
1011: /* . . . . C R C R C R C R C R C R C R C R X */
1012: /* . . . . 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
1013: addr = ( addr_logical & 0x7ffff ); /* add C8=A18 and R8=A17 */
1014: }
1015: }
1016:
1017: else /* ( RAM_Bank_Size == MEM_BANK_SIZE_128 ) */
1018: {
1019: /* RAM modules use lines MAD0-MAD7, C9/C8/R9/R8 don't exist : 17 bits per address in bank */
1020: if ( MMU_Bank_Size == MEM_BANK_SIZE_2048 )
1021: {
1022: /* 21 bit address is mapped to 21 bits : */
1023: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
1024: /* C R C R C R C R C R C R C R C R C R C R X */
1025: /* 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
1026: addr = ( addr_logical & 0x1ffff ); /* remove C9/C8/R9/R8 */
1027: }
1028: else if ( MMU_Bank_Size == MEM_BANK_SIZE_512 )
1029: {
1030: /* 21 bit address is mapped to 19 bits (C9/R9 are not used) : */
1031: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
1032: /* . . C R C R C R C R C R C R C R C R C R X */
1033: /* . . 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
1034: addr = ( addr_logical & 0x1ffff ); /* remove C8/R8 */
1035: }
1036: else /* if ( MMU_Bank_Size == MEM_BANK_SIZE_128 ) */
1037: {
1038: /* 21 bit address is mapped to 17 bits (C9/C8/R9/R8 are not used) : */
1039: /* a20 a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 */
1040: /* . . . . C R C R C R C R C R C R C R C R X */
1041: /* . . . . 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 X */
1042: addr = addr_logical;
1043: }
1044: }
1045:
1046:
1047: addr &= ( RAM_Bank_Size - 1 ); /* Keep address inside RAM bank size */
1048: return addr;
1049: }
1050:
1051:
1052:
1053:
1054: /**
1055: * Translate a logical address into a physical address inside the STRam[] buffer
1056: * by taking into account the size of the 2 MMU banks and the machine type (STF or STE)
1057: */
1058: Uint32 STMemory_MMU_Translate_Addr ( Uint32 addr_logical )
1059: {
1060: Uint32 addr;
1061: Uint32 addr_physical;
1062: Uint32 Bank_Start_physical;
1063: int RAM_Bank_Size , MMU_Bank_Size;
1064:
1065:
1066: /* MMU only translates RAM addr < 4 MB */
1067: /* If logical address is beyond total MMU size and < 4MB, then we don't translate either */
1068: /* Useless check below : memory_map_Standard_RAM() ensures addr_logical is always < MMU_Bank0_Size + MMU_Bank1_Size when MMU is enabled */
1069: // if ( addr_logical >= MMU_Bank0_Size + MMU_Bank1_Size )
1070: // return addr_logical;
1071:
1072: addr = addr_logical;
1073:
1074: if ( addr < MMU_Bank0_Size ) /* Accessing bank0 */
1075: {
1076: Bank_Start_physical = 0; /* Bank0's start relative to STRam[] */
1077: RAM_Bank_Size = RAM_Bank0_Size; /* Physical size for bank0 */
1078: MMU_Bank_Size = MMU_Bank0_Size; /* Logical size for bank0 */
1079: }
1080: else /* Accessing bank1 */
1081: {
1082: Bank_Start_physical = RAM_Bank0_Size; /* Bank1's start relative to STRam[] */
1083: RAM_Bank_Size = RAM_Bank1_Size; /* Physical size for bank1 */
1084: MMU_Bank_Size = MMU_Bank1_Size; /* Logical size for bank1 */
1085: }
1086:
1087:
1088: if ( Config_IsMachineST() ) /* For STF / Mega STF */
1089: addr_physical = STMemory_MMU_Translate_Addr_STF ( addr , RAM_Bank_Size , MMU_Bank_Size );
1090: else /* For STE / Mega STE */
1091: addr_physical = STMemory_MMU_Translate_Addr_STE ( addr , RAM_Bank_Size , MMU_Bank_Size );
1092:
1093: addr_physical += Bank_Start_physical;
1094:
1095: //fprintf ( stderr , "mmu translate %x -> %x pc=%x\n" , addr_logical , addr_physical , M68000_GetPC() );
1096: return addr_physical;
1097: }
1098:
1099:
1100:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.