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

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: 

unix.superglobalmegacorp.com

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