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