Annotation of previous_trunk/src/ioMem.c, revision 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.