Annotation of hatari/src/stMemory.c, revision 1.1.1.20

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.