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

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.2   root       22: 
1.1.1.7   root       23: /* STRam points to our ST Ram. Unless the user enabled SMALL_MEM where we have
                     24:  * to save memory, this includes all TOS ROM and IO hardware areas for ease
                     25:  * and emulation speed - so we create a 16 MiB array directly here.
                     26:  * But when the user turned on ENABLE_SMALL_MEM, this only points to a malloc'ed
                     27:  * buffer with the ST RAM; the ROM and IO memory will be handled separately. */
                     28: #if ENABLE_SMALL_MEM
                     29: Uint8 *STRam;
                     30: #else
                     31: Uint8 STRam[16*1024*1024];
                     32: #endif
1.1.1.4   root       33: 
1.1.1.7   root       34: Uint32 STRamEnd;            /* End of ST Ram, above this address is no-mans-land and ROM/IO memory */
1.1       root       35: 
1.1.1.2   root       36: 
1.1.1.7   root       37: /**
                     38:  * Clear section of ST's memory space.
                     39:  */
1.1.1.15  root       40: static void STMemory_Clear(Uint32 StartAddress, Uint32 EndAddress)
1.1       root       41: {
1.1.1.5   root       42:        memset(&STRam[StartAddress], 0, EndAddress-StartAddress);
1.1       root       43: }
                     44: 
1.1.1.13  root       45: /**
                     46:  * Copy given memory area safely to Atari RAM.
                     47:  * If the memory area isn't fully within RAM, only the valid parts are written.
                     48:  * Useful for all kinds of IO operations.
                     49:  * 
                     50:  * addr - destination Atari RAM address
                     51:  * src - source Hatari memory address
                     52:  * len - number of bytes to copy
                     53:  * name - name / description if this memory copy for error messages
                     54:  * 
                     55:  * Return true if whole copy was safe / valid.
                     56:  */
                     57: bool STMemory_SafeCopy(Uint32 addr, Uint8 *src, unsigned int len, const char *name)
                     58: {
                     59:        Uint32 end;
                     60: 
1.1.1.17! root       61:        if ( STMemory_CheckAreaType ( addr, len, ABFLAG_RAM ) )
1.1.1.13  root       62:        {
                     63:                memcpy(&STRam[addr], src, len);
                     64:                return true;
                     65:        }
                     66:        Log_Printf(LOG_WARN, "Invalid '%s' RAM range 0x%x+%i!\n", name, addr, len);
                     67: 
                     68:        for (end = addr + len; addr < end; addr++, src++)
                     69:        {
1.1.1.17! root       70:                if ( STMemory_CheckAreaType ( addr, 1, ABFLAG_RAM ) )
1.1.1.13  root       71:                        STRam[addr] = *src;
                     72:        }
                     73:        return false;
                     74: }
1.1.1.6   root       75: 
1.1.1.12  root       76: /**
                     77:  * Save/Restore snapshot of RAM / ROM variables
                     78:  * ('MemorySnapShot_Store' handles type)
                     79:  */
                     80: void STMemory_MemorySnapShot_Capture(bool bSave)
                     81: {
                     82:        MemorySnapShot_Store(&STRamEnd, sizeof(STRamEnd));
                     83: 
                     84:        /* Only save/restore area of memory machine is set to, eg 1Mb */
                     85:        MemorySnapShot_Store(STRam, STRamEnd);
                     86: 
                     87:        /* And Cart/TOS/Hardware area */
                     88:        MemorySnapShot_Store(&RomMem[0xE00000], 0x200000);
                     89: }
                     90: 
                     91: 
1.1.1.7   root       92: /**
                     93:  * Set default memory configuration, connected floppies, memory size and
                     94:  * clear the ST-RAM area.
                     95:  * As TOS checks hardware for memory size + connected devices on boot-up
                     96:  * we set these values ourselves and fill in the magic numbers so TOS
                     97:  * skips these tests.
                     98:  */
1.1.1.6   root       99: void STMemory_SetDefaultConfig(void)
                    100: {
                    101:        int i;
1.1.1.17! root      102:        int screensize, limit;
        !           103:        int memtop, phystop;
1.1.1.6   root      104:        Uint8 nMemControllerByte;
1.1.1.13  root      105:        Uint8 nFalcSysCntrl;
                    106: 
1.1.1.6   root      107:        static const int MemControllerTable[] =
                    108:        {
                    109:                0x01,   /* 512 KiB */
                    110:                0x05,   /* 1 MiB */
                    111:                0x02,   /* 2 MiB */
                    112:                0x06,   /* 2.5 MiB */
                    113:                0x0A    /* 4 MiB */
                    114:        };
                    115: 
1.1.1.7   root      116:        if (bRamTosImage)
                    117:        {
                    118:                /* Clear ST-RAM, excluding the RAM TOS image */
                    119:                STMemory_Clear(0x00000000, TosAddress);
                    120:                STMemory_Clear(TosAddress+TosSize, STRamEnd);
                    121:        }
1.1.1.6   root      122:        else
1.1.1.7   root      123:        {
                    124:                /* Clear whole ST-RAM */
                    125:                STMemory_Clear(0x00000000, STRamEnd);
                    126:        }
1.1.1.6   root      127: 
                    128:        /* Mirror ROM boot vectors */
                    129:        STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress));
                    130:        STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4));
                    131: 
1.1.1.14  root      132:        /* Fill in magic numbers to bypass TOS' memory tests for faster boot or
1.1.1.17! root      133:         * if VDI resolution is enabled or if more than 4 MB of ram are used
        !           134:         * or if TT RAM added in Falcon mode.
1.1.1.14  root      135:         * (for highest compatibility, those tests should not be bypassed in
                    136:         *  the common STF/STE cases as some programs like "Yolanda" rely on
                    137:         *  the RAM content after those tests) */
1.1.1.17! root      138:        if ( ConfigureParams.System.bFastBoot
        !           139:          || bUseVDIRes
        !           140:          || ( ConfigureParams.Memory.nMemorySize > 4 && !bIsEmuTOS )
        !           141:          || ( ( ConfigureParams.System.nMachineType == MACHINE_FALCON ) && TTmemory ) )
1.1.1.14  root      142:        {
                    143:                /* Write magic values to sysvars to signal valid config */
                    144:                STMemory_WriteLong(0x420, 0x752019f3);    /* memvalid */
                    145:                STMemory_WriteLong(0x43a, 0x237698aa);    /* memval2 */
                    146:                STMemory_WriteLong(0x51a, 0x5555aaaa);    /* memval3 */
1.1.1.17! root      147: 
        !           148:                /* If ST RAM detection is bypassed, we must also force TT RAM config if enabled */
        !           149:                if ( TTmemory )
        !           150:                        STMemory_WriteLong ( 0x5a4 , 0x01000000 + TTmem_size );         /* ramtop */
        !           151:                else
        !           152:                        STMemory_WriteLong ( 0x5a4 , 0 );               /* ramtop */
        !           153:                STMemory_WriteLong ( 0x5a8 , 0x1357bd13 );              /* ramvalid */
        !           154: 
        !           155:                /* On Falcon, set bit6=1 at $ff8007 to simulate a warm start */
        !           156:                /* (else memory detection is not skipped after a cold start/reset) */
        !           157:                if ( ConfigureParams.System.nMachineType == MACHINE_FALCON )
        !           158:                        STMemory_WriteByte ( 0xff8007, IoMem_ReadByte(0xff8007) | 0x40 );
        !           159: 
        !           160:                /* On TT, set bit0=1 at $ff8e09 to simulate a warm start */
        !           161:                /* (else memory detection is not skipped after a cold start/reset) */
        !           162:                if ( ConfigureParams.System.nMachineType == MACHINE_TT )
        !           163:                        STMemory_WriteByte ( 0xff8e09, IoMem_ReadByte(0xff8e09) | 0x01 );
1.1.1.14  root      164:        }
1.1.1.6   root      165: 
1.1.1.17! root      166:        /* Set memory size, adjust for extra VDI screens if needed. */
1.1.1.7   root      167:        screensize = VDIWidth * VDIHeight / 8 * VDIPlanes;
1.1.1.14  root      168:        /* Use 32 kiB in normal screen mode or when the screen size is smaller than 32 kiB */
1.1.1.7   root      169:        if (!bUseVDIRes || screensize < 0x8000)
                    170:                screensize = 0x8000;
1.1.1.17! root      171:        /* mem top - upper end of user memory (right before the screen memory)
        !           172:         * memtop / phystop must be dividable by 512 or TOS crashes */
1.1.1.7   root      173:        memtop = (STRamEnd - screensize) & 0xfffffe00;
1.1.1.17! root      174:        /* phys top - 32k gap causes least issues with apps & TOS
        !           175:         * as that's the largest _common_ screen size. EmuTOS behavior
        !           176:         * depends on machine type.
        !           177:         *
        !           178:         * TODO: what to do about _native_ TT & Videl resolutions
        !           179:         * which size is >32k?  Should memtop be adapted also for
        !           180:         * those?
        !           181:         */
        !           182:        switch (ConfigureParams.System.nMachineType)
        !           183:        {
        !           184:        case MACHINE_FALCON:
        !           185:                /* TOS v4 doesn't work with VDI mode (yet), and
        !           186:                 * EmuTOS works with correct gap, so use that */
        !           187:                phystop = STRamEnd;
        !           188:                break;
        !           189:        case MACHINE_TT:
        !           190:                /* For correct TOS v3 memory detection, phystop should be
        !           191:                 * at the end of memory, not at memtop + 32k.
        !           192:                 *
        !           193:                 * However:
        !           194:                 * - TOS v3 crashes/hangs if phystop-memtop gap is larger
        !           195:                 *   than largest real HW screen size (150k)
        !           196:                 * - NVDI hangs if gap is larger than 32k in any other than
        !           197:                 *   monochrome mode
        !           198:                 */
        !           199:                if (VDIPlanes == 1)
        !           200:                        limit = 1280*960/8;
        !           201:                else
        !           202:                        limit = 0x8000;
        !           203:                if (screensize > limit)
        !           204:                {
        !           205:                        phystop = memtop + limit;
        !           206:                        fprintf(stderr, "WARNING: too large VDI mode for TOS v3 memory detection to work correctly!\n");
        !           207:                }
        !           208:                else
        !           209:                        phystop = STRamEnd;
        !           210:                break;
        !           211:        default:
        !           212:                phystop = memtop + 0x8000;
        !           213:        }
1.1.1.7   root      214:        STMemory_WriteLong(0x436, memtop);
1.1.1.17! root      215:        STMemory_WriteLong(0x42e, phystop);
        !           216:        if (bUseVDIRes)
        !           217:                fprintf(stderr, "VDI mode memtop: 0x%x, phystop: 0x%x (screensize: %d kB, memtop->phystop: %d kB)\n",
        !           218:                        memtop, phystop, (screensize+511) / 1024, (phystop-memtop+511) / 1024);
1.1.1.6   root      219: 
                    220:        /* Set memory controller byte according to different memory sizes */
                    221:        /* Setting per bank: %00=128k %01=512k %10=2Mb %11=reserved. - e.g. %1010 means 4Mb */
                    222:        if (ConfigureParams.Memory.nMemorySize <= 4)
                    223:                nMemControllerByte = MemControllerTable[ConfigureParams.Memory.nMemorySize];
                    224:        else
                    225:                nMemControllerByte = 0x0f;
                    226:        STMemory_WriteByte(0x424, nMemControllerByte);
                    227:        IoMem_WriteByte(0xff8001, nMemControllerByte);
                    228: 
1.1.1.7   root      229:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
                    230:        {
1.1.1.13  root      231:                /* Set the Falcon memory and monitor configuration register:
                    232: 
1.1.1.15  root      233:                         $ffff8006.b [R]  76543210  Monitor-memory
                    234:                                          ||||||||
                    235:                                          |||||||+- RAM Wait Status
                    236:                                          |||||||   0 =  1 Wait (default)
                    237:                                          |||||||   1 =  0 Wait
                    238:                                          ||||||+-- Video Bus size ???
                    239:                                          ||||||    0 = 16 Bit
                    240:                                          ||||||    1 = 32 Bit (default)
                    241:                                          ||||++--- ROM Wait Status
                    242:                                          ||||      00 = Reserved
                    243:                                          ||||      01 =  2 Wait (default)
                    244:                                          ||||      10 =  1 Wait
                    245:                                          ||||      11 =  0 Wait
                    246:                                          ||++----- Falcon Memory
                    247:                                          ||        00 =  1 MB
                    248:                                          ||        01 =  4 MB
                    249:                                          ||        10 = 14 MB
                    250:                                          ||        11 = no boot !
                    251:                                          ++------- Monitor-Typ
                    252:                                                    00 - Monochrome (SM124)
                    253:                                                    01 - Color (SC1224)
                    254:                                                    10 - VGA Color
                    255:                                                    11 - Television
1.1.1.13  root      256: 
                    257:                Bit 1 seems not to be well documented. It's used by TOS at bootup to compute the memory size.
                    258:                After some tests, I get the following RAM values (Bits 5, 4, 1 are involved) :
                    259: 
                    260:                00 =  512 Ko    20 = 8192 Ko
                    261:                02 = 1024 Ko    22 = 14366 Ko
                    262:                10 = 2048 Ko    30 = Illegal
                    263:                12 = 4096 Ko    32 = Illegal
                    264: 
                    265:                I use these values for Hatari's emulation.
                    266:                I also set the bit 3 and 2 at value 01 are mentioned in the register description.
                    267:                */
                    268: 
                    269:                if (ConfigureParams.Memory.nMemorySize == 14)     /* 14 Meg */
                    270:                        nFalcSysCntrl = 0x26;
                    271:                else if (ConfigureParams.Memory.nMemorySize == 8) /* 8 Meg */
                    272:                        nFalcSysCntrl = 0x24;
                    273:                else if (ConfigureParams.Memory.nMemorySize == 4) /* 4 Meg */
1.1.1.7   root      274:                        nFalcSysCntrl = 0x16;
1.1.1.13  root      275:                else if (ConfigureParams.Memory.nMemorySize == 2) /* 2 Meg */
1.1.1.7   root      276:                        nFalcSysCntrl = 0x14;
1.1.1.13  root      277:                else if (ConfigureParams.Memory.nMemorySize == 1) /* 1 Meg */
1.1.1.7   root      278:                        nFalcSysCntrl = 0x06;
                    279:                else
1.1.1.13  root      280:                        nFalcSysCntrl = 0x04;                     /* 512 Ko */
                    281: 
1.1.1.8   root      282:                switch(ConfigureParams.Screen.nMonitorType) {
1.1.1.13  root      283:                        case MONITOR_TYPE_TV:
                    284:                                nFalcSysCntrl |= FALCON_MONITOR_TV;
                    285:                                break;
                    286:                        case MONITOR_TYPE_VGA:
                    287:                                nFalcSysCntrl |= FALCON_MONITOR_VGA;
                    288:                                break;
                    289:                        case MONITOR_TYPE_RGB:
                    290:                                nFalcSysCntrl |= FALCON_MONITOR_RGB;
                    291:                                break;
                    292:                        case MONITOR_TYPE_MONO:
                    293:                                nFalcSysCntrl |= FALCON_MONITOR_MONO;
                    294:                                break;
1.1.1.7   root      295:                }
                    296:                STMemory_WriteByte(0xff8006, nFalcSysCntrl);
                    297:        }
                    298: 
1.1.1.6   root      299:        /* Set TOS floppies */
                    300:        STMemory_WriteWord(0x446, nBootDrive);          /* Boot up on A(0) or C(2) */
                    301: 
1.1.1.16  root      302:        /* Create connected drives mask (only for harddrives, don't change floppy drive detected by TOS) */
1.1.1.10  root      303:        ConnectedDriveMask = STMemory_ReadLong(0x4c2);  // Get initial drive mask (see what TOS thinks)
                    304:        if (GEMDOS_EMU_ON)
1.1.1.6   root      305:        {
1.1.1.10  root      306:                for (i = 0; i < MAX_HARDDRIVES; i++)
                    307:                {
                    308:                        if (emudrives[i] != NULL)     // Is this GEMDOS drive enabled?
1.1.1.12  root      309:                                ConnectedDriveMask |= (1 << emudrives[i]->drive_number);
1.1.1.10  root      310:                }
1.1.1.6   root      311:        }
                    312:        /* Set connected drives system variable.
                    313:         * NOTE: some TOS images overwrite this value, see 'OpCode_SysInit', too */
                    314:        STMemory_WriteLong(0x4c2, ConnectedDriveMask);
                    315: }
1.1.1.17! root      316: 
        !           317: 
        !           318: /**
        !           319:  * Check that the region of 'size' starting at 'addr' is entirely inside
        !           320:  * a memory bank of the same memory type
        !           321:  */
        !           322: bool   STMemory_CheckAreaType ( Uint32 addr , int size , int mem_type )
        !           323: {
        !           324:        addrbank        *pBank;
        !           325: 
        !           326:        pBank = &get_mem_bank ( addr );
        !           327: 
        !           328:        if ( ( pBank->flags & mem_type ) == 0 )
        !           329:        {
        !           330:                fprintf(stderr, "pBank flags mismatch: 0x%x & 0x%x (RAM = 0x%x)\n", pBank->flags, mem_type, ABFLAG_RAM);
        !           331:                return false;
        !           332:        }
        !           333: 
        !           334:        return pBank->check ( addr , size );
        !           335: }
        !           336: 
        !           337: 
        !           338: /**
        !           339:  * Check if an address points to a memory region that causes bus error
        !           340:  * This is used for blitter and other DMA chips that should not cause
        !           341:  * a bus error when accessing such regions (on the contrary of the CPU)
        !           342:  * Returns true if region gives bus error
        !           343:  */
        !           344: bool   STMemory_CheckRegionBusError ( Uint32 addr )
        !           345: {
        !           346:        return memory_region_bus_error ( addr );
        !           347: }
        !           348: 
        !           349: 
        !           350: /**
        !           351:  * Convert an address in the ST memory space to a direct pointer
        !           352:  * in the host memory.
        !           353:  *
        !           354:  * NOTE : Using this function to get a direct pointer to the memory should
        !           355:  * only be used after doing a call to valid_address or STMemory_CheckAreaType
        !           356:  * to ensure we don't try to access a non existing memory region.
        !           357:  * Basically, this function should be used only for addr in RAM or in ROM
        !           358:  */
        !           359: void   *STMemory_STAddrToPointer ( Uint32 addr )
        !           360: {
        !           361:        Uint8   *p;
        !           362: 
        !           363:        if ( ConfigureParams.System.bAddressSpace24 == true )
        !           364:                addr &= 0x00ffffff;                     /* Only keep the 24 lowest bits */
        !           365: 
        !           366:        p = get_real_address ( addr );
        !           367:        return (void *)p;
        !           368: }
        !           369: 
        !           370: 
        !           371: 
        !           372: /**
        !           373:  * Those functions are directly accessing the memory of the corresponding
        !           374:  * bank, without calling its dedicated access handlers (they won't generate
        !           375:  * bus errors or address errors or update IO values)
        !           376:  * They are only used for internal work of the emulation, such as debugger,
        !           377:  * log to print the content of memory, intercepting gemdos/bios calls, ...
        !           378:  *
        !           379:  * These functions are not used by the CPU emulation itself, see memory.c
        !           380:  * for the functions that emulate real memory accesses.
        !           381:  */
        !           382: 
        !           383: /**
        !           384:  * Write long/word/byte into memory.
        !           385:  * NOTE - value will be converted to 68000 endian
        !           386:  */
        !           387: void   STMemory_Write ( Uint32 addr , Uint32 val , int size )
        !           388: {
        !           389:        addrbank        *pBank;
        !           390:        Uint8           *p;
        !           391: 
        !           392: //printf ( "mem direct write %x %x %d\n" , addr , val , size );
        !           393:        pBank = &get_mem_bank ( addr );
        !           394: 
        !           395:        if ( pBank->baseaddr == NULL )
        !           396:                return;                                 /* No real memory, do nothing */
        !           397: 
        !           398:        addr -= pBank->start & pBank->mask;
        !           399:        addr &= pBank->mask;
        !           400:        p = pBank->baseaddr + addr;
        !           401: 
        !           402:        /* We modify the memory, so we flush the instr/data caches if needed */
        !           403:        M68000_Flush_All_Caches ( addr , size );
        !           404:        
        !           405:        if ( size == 4 )
        !           406:                do_put_mem_long ( p , val );
        !           407:        else if ( size == 2 )
        !           408:                do_put_mem_word ( p , (Uint16)val );
        !           409:        else
        !           410:                *p = (Uint8)val;
        !           411: }
        !           412: 
        !           413: void   STMemory_WriteLong ( Uint32 addr , Uint32 val )
        !           414: {
        !           415:        STMemory_Write ( addr , val , 4 );
        !           416: }
        !           417: 
        !           418: void   STMemory_WriteWord ( Uint32 addr , Uint16 val )
        !           419: {
        !           420:        STMemory_Write ( addr , (Uint32)val , 2 );
        !           421: }
        !           422: 
        !           423: void   STMemory_WriteByte ( Uint32 addr , Uint8 val )
        !           424: {
        !           425:        STMemory_Write ( addr , (Uint32)val , 1 );
        !           426: }
        !           427: 
        !           428: 
        !           429: /**
        !           430:  * Read long/word/byte from memory.
        !           431:  * NOTE - value will be converted to 68000 endian
        !           432:  */
        !           433: Uint32 STMemory_Read ( Uint32 addr , int size )
        !           434: {
        !           435:        addrbank        *pBank;
        !           436:        Uint8           *p;
        !           437: 
        !           438: //printf ( "mem direct read %x %d\n" , addr , size );
        !           439:        pBank = &get_mem_bank ( addr );
        !           440: 
        !           441:        if ( pBank->baseaddr == NULL )
        !           442:                return 0;                               /* No real memory, return 0 */
        !           443: 
        !           444:        addr -= pBank->start & pBank->mask;
        !           445:        addr &= pBank->mask;
        !           446:        p = pBank->baseaddr + addr;
        !           447:        
        !           448:        if ( size == 4 )
        !           449:                return do_get_mem_long ( p );
        !           450:        else if ( size == 2 )
        !           451:                return (Uint32)do_get_mem_word ( p );
        !           452:        else
        !           453:                return (Uint32)*p;
        !           454: }
        !           455: 
        !           456: Uint32 STMemory_ReadLong ( Uint32 addr )
        !           457: {
        !           458:        return (Uint32) STMemory_Read ( addr , 4 );
        !           459: }
        !           460: 
        !           461: Uint16 STMemory_ReadWord ( Uint32 addr )
        !           462: {
        !           463:        return (Uint16)STMemory_Read ( addr , 2 );
        !           464: }
        !           465: 
        !           466: Uint8  STMemory_ReadByte ( Uint32 addr )
        !           467: {
        !           468:        return (Uint8)STMemory_Read ( addr , 1 );
        !           469: }
        !           470: 

unix.superglobalmegacorp.com

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