Annotation of previous/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: 
        !            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.