Annotation of previous_trunk/src/ioMem.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - ioMem.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   This is where we intercept read/writes to/from the hardware. 
                      8: */
                      9: const char IoMem_fileid[] = "Hatari ioMem.c : " __DATE__ " " __TIME__;
                     10: 
                     11: #include "main.h"
                     12: #include "configuration.h"
                     13: #include "ioMem.h"
                     14: #include "ioMemTables.h"
                     15: #include "m68000.h"
                     16: #include "sysdeps.h"
                     17: #include "shortcut.h"
                     18: 
                     19: #define IO_SEG_MASK 0x0001FFFF
                     20: #define IO_MASK 0x0001FFFF
                     21: #define IO_SIZE 0x00020000
                     22: 
                     23: static void (*pInterceptReadTable[IO_SIZE])(void);     /* Table with read access handlers */
                     24: static void (*pInterceptWriteTable[IO_SIZE])(void);    /* Table with write access handlers */
                     25: 
                     26: int nIoMemAccessSize;                                 /* Set to 1, 2 or 4 according to byte, word or long word access */
                     27: Uint32 IoAccessBaseAddress;                           /* Stores the base address of the IO mem access */
                     28: Uint32 IoAccessCurrentAddress;                        /* Current byte address while handling WORD and LONG accesses */
                     29: static int nBusErrorAccesses;                         /* Needed to count bus error accesses */
                     30: 
                     31: 
                     32: /*-----------------------------------------------------------------------*/
                     33: /**
                     34:  * Fill a region with bus error handlers.
                     35:  */
                     36: static void IoMem_SetBusErrorRegion(Uint32 startaddr, Uint32 endaddr)
                     37: {
                     38:        Uint32 a;
                     39: 
                     40:        for (a = startaddr; a <= endaddr; a++)
                     41:        {
                     42:                if (a & 1)
                     43:                {
                     44:                        pInterceptReadTable[a & 0x1FFFF] = IoMem_BusErrorOddReadAccess;     /* For 'read' */
                     45:                        pInterceptWriteTable[a & 0x1FFFF] = IoMem_BusErrorOddWriteAccess;   /* and 'write' */
                     46:                }
                     47:                else
                     48:                {
                     49:                        pInterceptReadTable[a & 0x1FFFF] = IoMem_BusErrorEvenReadAccess;    /* For 'read' */
                     50:                        pInterceptWriteTable[a & 0x1FFFF] = IoMem_BusErrorEvenWriteAccess;  /* and 'write' */
                     51:                }
                     52:        }
                     53: }
                     54: 
                     55: 
                     56: /*-----------------------------------------------------------------------*/
                     57: /**
                     58:  * Create 'intercept' tables for hardware address access. Each 'intercept
                     59:  */
                     60: void IoMem_Init(void)
                     61: {
                     62:        Uint32 addr;
                     63:        int i;
                     64:        const INTERCEPT_ACCESS_FUNC *pInterceptAccessFuncs = NULL;
                     65: 
                     66:        /* Set default IO access handler (-> bus error) */
                     67:        IoMem_SetBusErrorRegion(0x02000000, 0x0201FFFF);
                     68: 
                     69:        if (ConfigureParams.System.bTurbo) {
                     70:                pInterceptAccessFuncs = IoMemTable_Turbo;
                     71:        } else {
                     72:                pInterceptAccessFuncs = IoMemTable_NEXT;
                     73:        }
                     74: 
                     75:        /* Now set the correct handlers */
                     76:        for (addr=0x02000000; addr <= 0x0201FFFF; addr++)
                     77:        {
                     78:                /* Does this hardware location/span appear in our list of possible intercepted functions? */
                     79:                for (i=0; pInterceptAccessFuncs[i].Address != 0; i++)
                     80:                {
                     81:                        if (addr >= pInterceptAccessFuncs[i].Address
                     82:                            && addr < pInterceptAccessFuncs[i].Address+pInterceptAccessFuncs[i].SpanInBytes)
                     83:                        {
                     84:                                /* Security checks... */
                     85:                                if (pInterceptReadTable[addr & 0x1FFFF] != IoMem_BusErrorEvenReadAccess && pInterceptReadTable[addr&0x1FFFF] != IoMem_BusErrorOddReadAccess)
                     86:                                        fprintf(stderr, "IoMem_Init: Warning: $%x (R) already defined\n", addr);
                     87:                                if (pInterceptWriteTable[addr& 0x1FFFF] != IoMem_BusErrorEvenWriteAccess && pInterceptWriteTable[addr&0x1FFFF] != IoMem_BusErrorOddWriteAccess)
                     88:                                        fprintf(stderr, "IoMem_Init: Warning: $%x (W) already defined\n", addr);
                     89: 
                     90:                                /* This location needs to be intercepted, so add entry to list */
                     91:                                pInterceptReadTable[addr& 0x1FFFF] = pInterceptAccessFuncs[i].ReadFunc;
                     92:                                pInterceptWriteTable[addr& 0x1FFFF] = pInterceptAccessFuncs[i].WriteFunc;
                     93:                        }
                     94:                }
                     95:        }
                     96: 
                     97: 
                     98: }
                     99: 
                    100: 
                    101: /*-----------------------------------------------------------------------*/
                    102: /**
                    103:  * Uninitialize the IoMem code (currently unused).
                    104:  */
                    105: void IoMem_UnInit(void)
                    106: {
                    107: }
                    108: 
                    109: 
                    110: /*-----------------------------------------------------------------------*/
                    111: /**
                    112:  * Handle byte read access from IO memory.
                    113:  */
                    114: uae_u32 IoMem_bget(uaecptr addr)
                    115: {
                    116:        Uint8 val;
                    117: 
                    118:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    119:        {
                    120:                /* invalid memory addressing --> bus error */
                    121:                M68000_BusError(addr, BUS_ERROR_READ);
                    122:                return -1;
                    123:        }
                    124: 
                    125:        IoAccessBaseAddress = addr;                   /* Store access location */
                    126:        nIoMemAccessSize = SIZE_BYTE;
                    127:        nBusErrorAccesses = 0;
                    128: 
                    129:        IoAccessCurrentAddress = addr;
                    130:        pInterceptReadTable[addr & IO_SEG_MASK]();         /* Call handler */
                    131: 
                    132:        /* Check if we read from a bus-error region */
                    133:        if (nBusErrorAccesses == 1)
                    134:        {
                    135:                M68000_BusError(addr, BUS_ERROR_READ);
                    136:                return -1;
                    137:        }
                    138: 
                    139:        val = IoMem[addr & IO_SEG_MASK];
                    140: 
                    141:        LOG_TRACE(TRACE_IOMEM_RD, "IO read.b $%06x = $%02x\n", addr, val);
                    142: 
                    143:        return val;
                    144: }
                    145: 
                    146: 
                    147: /*-----------------------------------------------------------------------*/
                    148: /**
                    149:  * Handle word read access from IO memory.
                    150:  */
                    151: uae_u32 IoMem_wget(uaecptr addr)
                    152: {
                    153:        Uint32 idx;
                    154:        Uint16 val;
                    155: 
                    156: 
                    157:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    158:        {
                    159:                /* invalid memory addressing --> bus error */
                    160:                M68000_BusError(addr, BUS_ERROR_READ);
                    161:                return -1;
                    162:        }
                    163: 
                    164:        IoAccessBaseAddress = addr;                   /* Store for exception frame */
                    165:        nIoMemAccessSize = SIZE_WORD;
                    166:        nBusErrorAccesses = 0;
                    167:        idx = addr & IO_SEG_MASK;
                    168: 
                    169:        IoAccessCurrentAddress = addr;
                    170:        pInterceptReadTable[idx]();                   /* Call 1st handler */
                    171: 
                    172:        if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx])
                    173:        {
                    174:                IoAccessCurrentAddress = addr + 1;
                    175:                pInterceptReadTable[idx+1]();             /* Call 2nd handler */
                    176:        }
                    177: 
                    178:        /* Check if we completely read from a bus-error region */
                    179:        if (nBusErrorAccesses == 2)
                    180:        {
                    181:                M68000_BusError(addr, BUS_ERROR_READ);
                    182:                return -1;
                    183:        }
                    184: 
                    185:        val = IoMem_ReadWord(addr);
                    186: 
                    187:        LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x\n", addr, val);
                    188: 
                    189:        return val;
                    190: }
                    191: 
                    192: 
                    193: /*-----------------------------------------------------------------------*/
                    194: /**
                    195:  * Handle long-word read access from IO memory.
                    196:  */
                    197: uae_u32 IoMem_lget(uaecptr addr)
                    198: {
                    199:        Uint32 idx;
                    200:        Uint32 val;
                    201: 
                    202: 
                    203:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    204:        {
                    205:                /* invalid memory addressing --> bus error */
                    206:                M68000_BusError(addr, BUS_ERROR_READ);
                    207:                return -1;
                    208:        }
                    209: 
                    210:        IoAccessBaseAddress = addr;                   /* Store for exception frame */
                    211:        nIoMemAccessSize = SIZE_LONG;
                    212:        nBusErrorAccesses = 0;
                    213:        idx = addr & IO_SEG_MASK;
                    214: 
                    215:        IoAccessCurrentAddress = addr;
                    216:        pInterceptReadTable[idx]();                   /* Call 1st handler */
                    217: 
                    218:        if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx])
                    219:        {
                    220:                IoAccessCurrentAddress = addr + 1;
                    221:                pInterceptReadTable[idx+1]();             /* Call 2nd handler */
                    222:        }
                    223: 
                    224:        if (pInterceptReadTable[idx+2] != pInterceptReadTable[idx+1])
                    225:        {
                    226:                IoAccessCurrentAddress = addr + 2;
                    227:                pInterceptReadTable[idx+2]();             /* Call 3rd handler */
                    228:        }
                    229: 
                    230:        if (pInterceptReadTable[idx+3] != pInterceptReadTable[idx+2])
                    231:        {
                    232:                IoAccessCurrentAddress = addr + 3;
                    233:                pInterceptReadTable[idx+3]();             /* Call 4th handler */
                    234:        }
                    235: 
                    236:        /* Check if we completely read from a bus-error region */
                    237:        if (nBusErrorAccesses == 4)
                    238:        {
                    239:                M68000_BusError(addr, BUS_ERROR_READ);
                    240:                return -1;
                    241:        }
                    242: 
                    243:        val = IoMem_ReadLong(addr);
                    244: 
                    245:        LOG_TRACE(TRACE_IOMEM_RD, "IO read.l $%06x = $%08x\n", addr, val);
                    246: 
                    247:        return val;
                    248: }
                    249: 
                    250: 
                    251: /*-----------------------------------------------------------------------*/
                    252: /**
                    253:  * Handle byte write access to IO memory.
                    254:  */
                    255: void IoMem_bput(uaecptr addr, uae_u32 val)
                    256: {
                    257: 
                    258:        LOG_TRACE(TRACE_IOMEM_WR, "IO write.b $%06x = $%02x\n", addr, val&0x0ff);
                    259: 
                    260:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    261:        {
                    262:                /* invalid memory addressing --> bus error */
                    263:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    264:                return;
                    265:        }
                    266: 
                    267:        IoAccessBaseAddress = addr;                   /* Store for exception frame, just in case */
                    268:        nIoMemAccessSize = SIZE_BYTE;
                    269:        nBusErrorAccesses = 0;
                    270: 
                    271:        IoMem[addr & IO_SEG_MASK] = val;
                    272: 
                    273:        IoAccessCurrentAddress = addr;
                    274:        pInterceptWriteTable[addr & IO_SEG_MASK]();        /* Call handler */
                    275: 
                    276:        /* Check if we wrote to a bus-error region */
                    277:        if (nBusErrorAccesses == 1)
                    278:        {
                    279:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    280:        }
                    281: }
                    282: 
                    283: 
                    284: /*-----------------------------------------------------------------------*/
                    285: /**
                    286:  * Handle word write access to IO memory.
                    287:  */
                    288: void IoMem_wput(uaecptr addr, uae_u32 val)
                    289: {
                    290:        Uint32 idx;
                    291: 
                    292: 
                    293:        LOG_TRACE(TRACE_IOMEM_WR, "IO write.w $%06x = $%04x\n", addr, val&0xffff);
                    294: 
                    295:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    296:        {
                    297:                /* invalid memory addressing --> bus error */
                    298:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    299:                return;
                    300:        }
                    301: 
                    302:        IoAccessBaseAddress = addr;                   /* Store for exception frame, just in case */
                    303:        nIoMemAccessSize = SIZE_WORD;
                    304:        nBusErrorAccesses = 0;
                    305: 
                    306:        IoMem_WriteWord(addr, val);
                    307:        idx = addr & IO_SEG_MASK;
                    308: 
                    309:        IoAccessCurrentAddress = addr;
                    310:        pInterceptWriteTable[idx]();                  /* Call 1st handler */
                    311: 
                    312:        if (pInterceptWriteTable[idx+1] != pInterceptWriteTable[idx])
                    313:        {
                    314:                IoAccessCurrentAddress = addr + 1;
                    315:                pInterceptWriteTable[idx+1]();            /* Call 2nd handler */
                    316:        }
                    317: 
                    318:        /* Check if we wrote to a bus-error region */
                    319:        if (nBusErrorAccesses == 2)
                    320:        {
                    321:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    322:        }
                    323: }
                    324: 
                    325: 
                    326: /*-----------------------------------------------------------------------*/
                    327: /**
                    328:  * Handle long-word write access to IO memory.
                    329:  */
                    330: void IoMem_lput(uaecptr addr, uae_u32 val)
                    331: {
                    332:        Uint32 idx;
                    333: 
                    334:        LOG_TRACE(TRACE_IOMEM_WR, "IO write.l $%06x = $%08x\n", addr, val);
                    335: 
                    336:        if ((addr & IO_SEG_MASK) >= IO_SIZE)
                    337:        {
                    338:                /* invalid memory addressing --> bus error */
                    339:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    340:                return;
                    341:        }
                    342: 
                    343:        IoAccessBaseAddress = addr;                   /* Store for exception frame, just in case */
                    344:        nIoMemAccessSize = SIZE_LONG;
                    345:        nBusErrorAccesses = 0;
                    346: 
                    347:        IoMem_WriteLong(addr, val);
                    348:        idx = addr & IO_SEG_MASK;
                    349: 
                    350:        IoAccessCurrentAddress = addr;
                    351:        pInterceptWriteTable[idx]();                  /* Call handler */
                    352: 
                    353:        if (pInterceptWriteTable[idx+1] != pInterceptWriteTable[idx])
                    354:        {
                    355:                IoAccessCurrentAddress = addr + 1;
                    356:                pInterceptWriteTable[idx+1]();            /* Call 2nd handler */
                    357:        }
                    358: 
                    359:        if (pInterceptWriteTable[idx+2] != pInterceptWriteTable[idx+1])
                    360:        {
                    361:                IoAccessCurrentAddress = addr + 2;
                    362:                pInterceptWriteTable[idx+2]();            /* Call 3rd handler */
                    363:        }
                    364: 
                    365:        if (pInterceptWriteTable[idx+3] != pInterceptWriteTable[idx+2])
                    366:        {
                    367:                IoAccessCurrentAddress = addr + 3;
                    368:                pInterceptWriteTable[idx+3]();            /* Call 4th handler */
                    369:        }
                    370: 
                    371:        /* Check if we wrote to a bus-error region */
                    372:        if (nBusErrorAccesses == 4)
                    373:        {
                    374:                M68000_BusError(addr, BUS_ERROR_WRITE);
                    375:        }
                    376: }
                    377: 
                    378: 
                    379: /*-------------------------------------------------------------------------*/
                    380: /**
                    381:  * This handler will be called if a program tries to read from an address
                    382:  * that causes a bus error on a real machine. However, we can't call M68000_BusError()
                    383:  * directly: For example, a "move.b $ff8204,d0" triggers a bus error on a real ST,
                    384:  * while a "move.w $ff8204,d0" works! So we have to count the accesses to bus error
                    385:  * addresses and we only trigger a bus error later if the count matches the complete
                    386:  * access size (e.g. nBusErrorAccesses==4 for a long word access).
                    387:  */
                    388: void IoMem_BusErrorEvenReadAccess(void)
                    389: {
                    390:        nBusErrorAccesses += 1;
                    391:        // IoMem[IoAccessCurrentAddress& IO_SEG_MASK] = 0xff;
                    392:        Log_Printf(LOG_WARN,"Bus error $%08x PC=$%08x %s at %d", IoAccessCurrentAddress,regs.pc,__FILE__,__LINE__);
                    393: }
                    394: 
                    395: /**
                    396:  * We need two handler so that the IoMem_*get functions can distinguish
                    397:  * consecutive addresses.
                    398:  */
                    399: void IoMem_BusErrorOddReadAccess(void)
                    400: {
                    401:        nBusErrorAccesses += 1;
                    402:        // IoMem[IoAccessCurrentAddress& IO_SEG_MASK] = 0xff;
                    403:        Log_Printf(LOG_WARN,"Bus error $%08x PC=$%08x %s at %d", IoAccessCurrentAddress,regs.pc,__FILE__,__LINE__);
                    404: }
                    405: 
                    406: /*-------------------------------------------------------------------------*/
                    407: /**
                    408:  * Same as IoMem_BusErrorReadAccess() but for write access this time.
                    409:  */
                    410: void IoMem_BusErrorEvenWriteAccess(void)
                    411: {
                    412:        nBusErrorAccesses += 1;
                    413:        Log_Printf(LOG_WARN,"Bus error $%08x PC=$%08x %s at %d", IoAccessCurrentAddress,regs.pc,__FILE__,__LINE__);
                    414: }
                    415: 
                    416: /**
                    417:  * We need two handler so that the IoMem_*put functions can distinguish
                    418:  * consecutive addresses.
                    419:  */
                    420: void IoMem_BusErrorOddWriteAccess(void)
                    421: {
                    422:        nBusErrorAccesses += 1;
                    423:        Log_Printf(LOG_WARN,"Bus error $%08x PC=$%08x %s at %d", IoAccessCurrentAddress,regs.pc,__FILE__,__LINE__);
                    424: }
                    425: 
                    426: 
                    427: /*-------------------------------------------------------------------------*/
                    428: /**
                    429:  * This is the read handler for the IO memory locations without an assigned
                    430:  * IO register and which also do not generate a bus error. Reading from such
                    431:  * a register will return the result 0xff.
                    432:  */
                    433: void IoMem_VoidRead(void)
                    434: {
                    435:        Uint32 a;
                    436: 
                    437:        /* handler is probably called only once, so we have to take care of the neighbour "void IO registers" */
                    438:        for (a = IoAccessBaseAddress; a < IoAccessBaseAddress + nIoMemAccessSize; a++)
                    439:        {
                    440:                if (pInterceptReadTable[a & IO_SEG_MASK] == IoMem_VoidRead)
                    441:                {
                    442:                        IoMem[a & IO_SEG_MASK] = 0xff;
                    443:                }
                    444:        }
                    445:        Log_Printf(LOG_WARN,"IO read at $%08x PC=$%08x\n", IoAccessCurrentAddress,regs.pc);
                    446: }
                    447: 
                    448: /*-------------------------------------------------------------------------*/
                    449: /**
                    450:  * This is the write handler for the IO memory locations without an assigned
                    451:  * IO register and which also do not generate a bus error. We simply ignore
                    452:  * a write access to these registers.
                    453:  */
                    454: void IoMem_VoidWrite(void)
                    455: {
                    456:        /* Nothing... */
                    457:        Log_Printf(LOG_WARN,"IO write at $%08x PC=$%08x\n", IoAccessCurrentAddress,regs.pc);
                    458: }
                    459: 
                    460: 
                    461: /*-------------------------------------------------------------------------*/
                    462: /**
                    463:  * A dummy function that does nothing at all - for memory regions that don't
                    464:  * need a special handler for read access.
                    465:  */
                    466: void IoMem_ReadWithoutInterception(void)
                    467: {
                    468:        /* Nothing... */
                    469: }
                    470: 
                    471: /*-------------------------------------------------------------------------*/
                    472: /**
                    473:  * A dummy function that does nothing at all - for memory regions that don't
                    474:  * need a special handler for write access.
                    475:  */
                    476: void IoMem_WriteWithoutInterception(void)
                    477: {
                    478:        /* Nothing... */
                    479: }
                    480: 
                    481: /*-------------------------------------------------------------------------*/
                    482: /**
                    483:  * A dummy function that does nothing at all - for memory regions that don't
                    484:  * need a special handler for read access.
                    485:  */
                    486: void IoMem_ReadWithoutInterceptionButTrace(void)
                    487: {
                    488:        Log_Printf(LOG_WARN,"IO read at $%08x PC=$%08x\n", IoAccessCurrentAddress,regs.pc);
                    489: }
                    490: 
                    491: /*-------------------------------------------------------------------------*/
                    492: /**
                    493:  * A dummy function that does nothing at all - for memory regions that don't
                    494:  * need a special handler for write access.
                    495:  */
                    496: void IoMem_WriteWithoutInterceptionButTrace(void)
                    497: {
                    498:        Log_Printf(LOG_WARN,"IO write at $%08x val=%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],regs.pc);
                    499: }
                    500: 
                    501: /*-------------------------------------------------------------------------*/
                    502: /* Jump into debugger upon access
                    503:  */
                    504: void IoMem_Debug(void) {
                    505:     ShortCut_Debug_M68K();
                    506: }

unix.superglobalmegacorp.com

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