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

unix.superglobalmegacorp.com

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