|
|
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. The ST's memory
8: is nicely split into four main parts - the bottom area of RAM is for user
9: programs. This is followed by a large area which causes a Bus Error. After
10: this is the ROM addresses for TOS and finally an area for hardware mapping.
11: To gain speed any address in the user area can simply read/write, but anything
12: above this range needs to be checked for validity and sent to the various
13: handlers.
14: A big problem for ST emulation is the use of the hardware registers. These
15: often consist of an 'odd' byte in memory and is usually addressed as a single
16: byte. A number of applications, however, write to the address using a word or
17: even long word. So we have a list of handlers that take care of each address
18: that has to be intercepted. Eg, a long write to a PSG register (which access
19: two registers) will write the long into IO memory space and then call the two
20: handlers which read off the bytes for each register.
21: This means that any access to any hardware register in such a way will work
22: correctly - it certainly fixes a lot of bugs and means writing just one
23: routine for each hardware register we mean to intercept! Phew!
24: You have also to take into consideration that some hardware registers are
25: bigger than 1 byte (there are also word and longword registers) and that
26: a lot of addresses in between can cause a bus error - so it's not so easy
27: to cope with all type of handlers in a straight forward way.
28: Also note the 'mirror' (or shadow) registers of the PSG - this is used by most
29: games.
30: */
1.1.1.6 root 31: const char IoMem_fileid[] = "Hatari ioMem.c : " __DATE__ " " __TIME__;
1.1 root 32:
33: #include "main.h"
34: #include "configuration.h"
35: #include "ioMem.h"
36: #include "ioMemTables.h"
1.1.1.8 ! root 37: #include "memorySnapShot.h"
1.1 root 38: #include "m68000.h"
1.1.1.3 root 39: #include "sysdeps.h"
1.1 root 40:
41:
42: static void (*pInterceptReadTable[0x8000])(void); /* Table with read access handlers */
43: static void (*pInterceptWriteTable[0x8000])(void); /* Table with write access handlers */
44:
45: int nIoMemAccessSize; /* Set to 1, 2 or 4 according to byte, word or long word access */
46: Uint32 IoAccessBaseAddress; /* Stores the base address of the IO mem access */
1.1.1.3 root 47: Uint32 IoAccessCurrentAddress; /* Current byte address while handling WORD and LONG accesses */
1.1 root 48: static int nBusErrorAccesses; /* Needed to count bus error accesses */
49:
1.1.1.8 ! root 50: /* Falcon bus mode (Falcon STe compatible bus or Falcon only bus) */
! 51: static enum {
! 52: STE_BUS_COMPATIBLE,
! 53: FALCON_ONLY_BUS
! 54: } falconBusMode;
! 55:
! 56: /*-----------------------------------------------------------------------*/
! 57: /**
! 58: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
! 59: */
! 60: void IoMem_MemorySnapShot_Capture(bool bSave)
! 61: {
! 62: /* Save/Restore details */
! 63: MemorySnapShot_Store(&falconBusMode, sizeof(falconBusMode));
! 64: }
1.1 root 65:
66: /*-----------------------------------------------------------------------*/
1.1.1.3 root 67: /**
68: * Fill a region with bus error handlers.
69: */
1.1 root 70: static void IoMem_SetBusErrorRegion(Uint32 startaddr, Uint32 endaddr)
71: {
72: Uint32 a;
73:
74: for (a = startaddr; a <= endaddr; a++)
75: {
76: if (a & 1)
77: {
78: pInterceptReadTable[a - 0xff8000] = IoMem_BusErrorOddReadAccess; /* For 'read' */
79: pInterceptWriteTable[a - 0xff8000] = IoMem_BusErrorOddWriteAccess; /* and 'write' */
80: }
81: else
82: {
83: pInterceptReadTable[a - 0xff8000] = IoMem_BusErrorEvenReadAccess; /* For 'read' */
84: pInterceptWriteTable[a - 0xff8000] = IoMem_BusErrorEvenWriteAccess; /* and 'write' */
85: }
86: }
87: }
88:
89:
90: /*-----------------------------------------------------------------------*/
1.1.1.3 root 91: /**
92: * Create 'intercept' tables for hardware address access. Each 'intercept
93: * table is a list of 0x8000 pointers to a list of functions to call when
94: * that location in the ST's memory is accessed.
95: */
1.1 root 96: void IoMem_Init(void)
97: {
98: Uint32 addr;
99: int i;
1.1.1.2 root 100: const INTERCEPT_ACCESS_FUNC *pInterceptAccessFuncs = NULL;
1.1 root 101:
102: /* Set default IO access handler (-> bus error) */
103: IoMem_SetBusErrorRegion(0xff8000, 0xffffff);
104:
1.1.1.8 ! root 105:
! 106: /* Initialize STe bus specific registers for Falcon in FALCON STe compatible bus mode */
! 107: if ((ConfigureParams.System.nMachineType == MACHINE_FALCON) && (falconBusMode == STE_BUS_COMPATIBLE)) {
! 108: for (addr = 0xff8000; addr < 0xffd426; addr++)
! 109: {
! 110: if ( ((addr >= 0xff8002) && (addr < 0xff8006)) ||
! 111: ((addr >= 0xff8008) && (addr < 0xff800c)) ||
! 112: ((addr >= 0xff800e) && (addr < 0xff8060)) ||
! 113: ((addr >= 0xff8064) && (addr < 0xff8200)) ||
! 114: ((addr >= 0xff82c4) && (addr < 0xff8400)) ||
! 115: (addr == 0xff8560) ||
! 116: (addr == 0xff8564) ||
! 117: ((addr >= 0xff8804) && (addr < 0xff8900)) ||
! 118: ((addr >= 0xff8964) && (addr < 0xff8970)) ||
! 119: ((addr >= 0xff8c00) && (addr < 0xff8c80)) ||
! 120: ((addr >= 0xff8c88) && (addr < 0xff8d00)) ||
! 121: ((addr >= 0xff9000) && (addr < 0xff9200)) ||
! 122: ((addr >= 0xff9204) && (addr < 0xff9206)) ||
! 123: ((addr >= 0xff9207) && (addr < 0xff9210)) ||
! 124: ((addr >= 0xff9218) && (addr < 0xff9220)) ||
! 125: ((addr >= 0xff9224) && (addr < 0xff9800)) ||
! 126: ((addr >= 0xff9c00) && (addr < 0xffa000)) ||
! 127: ((addr >= 0xffa200) && (addr < 0xffa208)) ||
! 128: (addr == 0xffc020) ||
! 129: (addr == 0xffc021) ||
! 130: (addr == 0xffd020) ||
! 131: (addr == 0xffd021) ||
! 132: (addr == 0xffd420) ||
! 133: (addr == 0xffd421) ||
! 134: (addr == 0xffd425)
! 135: ) {
! 136: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
! 137: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
! 138: }
! 139: }
! 140: }
! 141:
1.1 root 142: switch (ConfigureParams.System.nMachineType)
143: {
144: case MACHINE_ST: pInterceptAccessFuncs = IoMemTable_ST; break;
145: case MACHINE_STE: pInterceptAccessFuncs = IoMemTable_STE; break;
1.1.1.2 root 146: case MACHINE_TT: pInterceptAccessFuncs = IoMemTable_TT; break;
1.1.1.3 root 147: case MACHINE_FALCON: pInterceptAccessFuncs = IoMemTable_Falcon; break;
1.1.1.8 ! root 148: default: abort(); /* bug */
1.1 root 149: }
150:
151: /* Now set the correct handlers */
152: for (addr=0xff8000; addr <= 0xffffff; addr++)
153: {
154: /* Does this hardware location/span appear in our list of possible intercepted functions? */
155: for (i=0; pInterceptAccessFuncs[i].Address != 0; i++)
156: {
157: if (addr >= pInterceptAccessFuncs[i].Address
158: && addr < pInterceptAccessFuncs[i].Address+pInterceptAccessFuncs[i].SpanInBytes)
159: {
160: /* Security checks... */
161: if (pInterceptReadTable[addr-0xff8000] != IoMem_BusErrorEvenReadAccess && pInterceptReadTable[addr-0xff8000] != IoMem_BusErrorOddReadAccess)
162: fprintf(stderr, "IoMem_Init: Warning: $%x (R) already defined\n", addr);
163: if (pInterceptWriteTable[addr-0xff8000] != IoMem_BusErrorEvenWriteAccess && pInterceptWriteTable[addr-0xff8000] != IoMem_BusErrorOddWriteAccess)
164: fprintf(stderr, "IoMem_Init: Warning: $%x (W) already defined\n", addr);
165:
166: /* This location needs to be intercepted, so add entry to list */
167: pInterceptReadTable[addr-0xff8000] = pInterceptAccessFuncs[i].ReadFunc;
168: pInterceptWriteTable[addr-0xff8000] = pInterceptAccessFuncs[i].WriteFunc;
169: }
170: }
171: }
172:
1.1.1.4 root 173: /* Set registers for Falcon DSP emulation */
1.1.1.3 root 174: if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
175: {
1.1.1.4 root 176: switch (ConfigureParams.System.nDSPType)
177: {
1.1.1.3 root 178: #if ENABLE_DSP_EMU
179: case DSP_TYPE_EMU:
180: IoMemTabFalcon_DSPemulation(pInterceptReadTable,
181: pInterceptWriteTable);
182: break;
183: #endif
184: case DSP_TYPE_DUMMY:
185: IoMemTabFalcon_DSPdummy(pInterceptReadTable,
186: pInterceptWriteTable);
187: break;
188: default:
189: /* none */
190: IoMemTabFalcon_DSPnone(pInterceptReadTable,
191: pInterceptWriteTable);
192: }
193: }
194:
1.1 root 195: /* Disable blitter? */
1.1.1.3 root 196: if (!ConfigureParams.System.bBlitter && ConfigureParams.System.nMachineType == MACHINE_ST)
1.1 root 197: {
198: IoMem_SetBusErrorRegion(0xff8a00, 0xff8a3f);
199: }
200:
201: /* Disable real time clock? */
202: if (!ConfigureParams.System.bRealTimeClock)
203: {
1.1.1.4 root 204: for (addr = 0xfffc21; addr <= 0xfffc3f; addr++)
1.1 root 205: {
206: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
207: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
208: }
1.1.1.4 root 209: }
210:
1.1.1.8 ! root 211: /* Initialize PSG shadow registers for ST, STe, TT machines */
1.1.1.4 root 212: if (ConfigureParams.System.nMachineType != MACHINE_FALCON)
213: {
214: for (addr = 0xff8804; addr < 0xff8900; addr++)
215: {
216: pInterceptReadTable[addr - 0xff8000] = pInterceptReadTable[(addr & 0xfff803) - 0xff8000];
217: pInterceptWriteTable[addr - 0xff8000] = pInterceptWriteTable[(addr & 0xfff803) - 0xff8000];
218: }
1.1.1.8 ! root 219: }
! 220: else {
! 221: /* Initialize PSG shadow registers for Falcon machine when in STe bus compatibility mode */
! 222: if (falconBusMode == STE_BUS_COMPATIBLE) {
! 223: for (addr = 0xff8804; addr < 0xff8900; addr++)
! 224: {
! 225: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
! 226: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
! 227: }
! 228:
! 229: }
1.1 root 230: }
231: }
232:
1.1.1.8 ! root 233: /*-----------------------------------------------------------------------*/
! 234: /**
! 235: * This function is called to fix falconBusMode (0 = Falcon STe bus compatibility, other value = Falcon only bus compatibility)
! 236: * This value comes from register $ff8007.b (Bit 5) and is called by ioMemTabFalcon
! 237: */
! 238: void IoMem_Init_FalconInSTeBuscompatibilityMode(Uint8 value)
! 239: {
! 240: if (value == 0)
! 241: falconBusMode = STE_BUS_COMPATIBLE;
! 242: else
! 243: falconBusMode = FALCON_ONLY_BUS;
! 244:
! 245: IoMem_Init();
! 246: }
1.1 root 247:
248: /*-----------------------------------------------------------------------*/
1.1.1.3 root 249: /**
250: * Uninitialize the IoMem code (currently unused).
251: */
1.1 root 252: void IoMem_UnInit(void)
253: {
254: }
255:
256:
257: /*-----------------------------------------------------------------------*/
1.1.1.3 root 258: /**
259: * Handle byte read access from IO memory.
260: */
1.1 root 261: uae_u32 IoMem_bget(uaecptr addr)
262: {
1.1.1.6 root 263: Uint8 val;
1.1 root 264:
265: addr &= 0x00ffffff; /* Use a 24 bit address */
266:
267: if (addr < 0xff8000)
268: {
269: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 270: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 271: return -1;
272: }
273:
274: IoAccessBaseAddress = addr; /* Store access location */
275: nIoMemAccessSize = SIZE_BYTE;
276: nBusErrorAccesses = 0;
277:
278: IoAccessCurrentAddress = addr;
279: pInterceptReadTable[addr-0xff8000](); /* Call handler */
280:
281: /* Check if we read from a bus-error region */
282: if (nBusErrorAccesses == 1)
283: {
1.1.1.8 ! root 284: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 285: return -1;
286: }
287:
1.1.1.6 root 288: val = IoMem[addr];
289:
1.1.1.7 root 290: LOG_TRACE(TRACE_IOMEM_RD, "IO read.b $%06x = $%02x\n", addr, val);
1.1.1.6 root 291:
292: return val;
1.1 root 293: }
294:
295:
296: /*-----------------------------------------------------------------------*/
1.1.1.3 root 297: /**
298: * Handle word read access from IO memory.
299: */
1.1 root 300: uae_u32 IoMem_wget(uaecptr addr)
301: {
302: Uint32 idx;
1.1.1.6 root 303: Uint16 val;
1.1 root 304:
305: addr &= 0x00ffffff; /* Use a 24 bit address */
306:
307: if (addr < 0xff8000)
308: {
309: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 310: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 311: return -1;
312: }
313: if (addr > 0xfffffe)
314: {
315: fprintf(stderr, "Illegal IO memory access: IoMem_wget($%x)\n", addr);
316: return -1;
317: }
318:
319: IoAccessBaseAddress = addr; /* Store for exception frame */
320: nIoMemAccessSize = SIZE_WORD;
321: nBusErrorAccesses = 0;
322: idx = addr - 0xff8000;
323:
324: IoAccessCurrentAddress = addr;
325: pInterceptReadTable[idx](); /* Call 1st handler */
326:
327: if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx])
328: {
329: IoAccessCurrentAddress = addr + 1;
330: pInterceptReadTable[idx+1](); /* Call 2nd handler */
331: }
332:
333: /* Check if we completely read from a bus-error region */
334: if (nBusErrorAccesses == 2)
335: {
1.1.1.8 ! root 336: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 337: return -1;
338: }
339:
1.1.1.6 root 340: val = IoMem_ReadWord(addr);
341:
1.1.1.7 root 342: LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x\n", addr, val);
1.1.1.6 root 343:
344: return val;
1.1 root 345: }
346:
347:
348: /*-----------------------------------------------------------------------*/
1.1.1.3 root 349: /**
350: * Handle long-word read access from IO memory.
351: */
1.1 root 352: uae_u32 IoMem_lget(uaecptr addr)
353: {
354: Uint32 idx;
1.1.1.6 root 355: Uint32 val;
1.1 root 356:
357: addr &= 0x00ffffff; /* Use a 24 bit address */
358:
359: if (addr < 0xff8000)
360: {
361: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 362: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 363: return -1;
364: }
365: if (addr > 0xfffffc)
366: {
367: fprintf(stderr, "Illegal IO memory access: IoMem_lget($%x)\n", addr);
368: return -1;
369: }
370:
371: IoAccessBaseAddress = addr; /* Store for exception frame */
372: nIoMemAccessSize = SIZE_LONG;
373: nBusErrorAccesses = 0;
374: idx = addr - 0xff8000;
375:
376: IoAccessCurrentAddress = addr;
377: pInterceptReadTable[idx](); /* Call 1st handler */
378:
379: if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx])
380: {
381: IoAccessCurrentAddress = addr + 1;
382: pInterceptReadTable[idx+1](); /* Call 2nd handler */
383: }
384:
385: if (pInterceptReadTable[idx+2] != pInterceptReadTable[idx+1])
386: {
387: IoAccessCurrentAddress = addr + 2;
388: pInterceptReadTable[idx+2](); /* Call 3rd handler */
389: }
390:
391: if (pInterceptReadTable[idx+3] != pInterceptReadTable[idx+2])
392: {
393: IoAccessCurrentAddress = addr + 3;
394: pInterceptReadTable[idx+3](); /* Call 4th handler */
395: }
396:
397: /* Check if we completely read from a bus-error region */
398: if (nBusErrorAccesses == 4)
399: {
1.1.1.8 ! root 400: M68000_BusError(addr, BUS_ERROR_READ);
1.1 root 401: return -1;
402: }
403:
1.1.1.6 root 404: val = IoMem_ReadLong(addr);
405:
1.1.1.7 root 406: LOG_TRACE(TRACE_IOMEM_RD, "IO read.l $%06x = $%08x\n", addr, val);
1.1.1.6 root 407:
408: return val;
1.1 root 409: }
410:
411:
412: /*-----------------------------------------------------------------------*/
1.1.1.3 root 413: /**
414: * Handle byte write access to IO memory.
415: */
1.1 root 416: void IoMem_bput(uaecptr addr, uae_u32 val)
417: {
418: addr &= 0x00ffffff; /* Use a 24 bit address */
419:
1.1.1.7 root 420: LOG_TRACE(TRACE_IOMEM_WR, "IO write.b $%06x = $%02x\n", addr, val&0x0ff);
1.1.1.6 root 421:
1.1.1.5 root 422: if (addr < 0xff8000 || !regs.s)
1.1 root 423: {
424: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 425: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 426: return;
427: }
428:
429: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
430: nIoMemAccessSize = SIZE_BYTE;
431: nBusErrorAccesses = 0;
432:
433: IoMem[addr] = val;
434:
435: IoAccessCurrentAddress = addr;
436: pInterceptWriteTable[addr-0xff8000](); /* Call handler */
437:
438: /* Check if we wrote to a bus-error region */
439: if (nBusErrorAccesses == 1)
440: {
1.1.1.8 ! root 441: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 442: }
443: }
444:
445:
446: /*-----------------------------------------------------------------------*/
1.1.1.3 root 447: /**
448: * Handle word write access to IO memory.
449: */
1.1 root 450: void IoMem_wput(uaecptr addr, uae_u32 val)
451: {
452: Uint32 idx;
453:
454: addr &= 0x00ffffff; /* Use a 24 bit address */
455:
1.1.1.7 root 456: LOG_TRACE(TRACE_IOMEM_WR, "IO write.w $%06x = $%04x\n", addr, val&0x0ffff);
1.1.1.6 root 457:
1.1.1.5 root 458: if (addr < 0x00ff8000 || !regs.s)
1.1 root 459: {
460: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 461: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 462: return;
463: }
464: if (addr > 0xfffffe)
465: {
466: fprintf(stderr, "Illegal IO memory access: IoMem_wput($%x)\n", addr);
467: return;
468: }
469:
470: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
471: nIoMemAccessSize = SIZE_WORD;
472: nBusErrorAccesses = 0;
473:
474: IoMem_WriteWord(addr, val);
475: idx = addr - 0xff8000;
476:
477: IoAccessCurrentAddress = addr;
478: pInterceptWriteTable[idx](); /* Call 1st handler */
479:
480: if (pInterceptWriteTable[idx+1] != pInterceptWriteTable[idx])
481: {
482: IoAccessCurrentAddress = addr + 1;
483: pInterceptWriteTable[idx+1](); /* Call 2nd handler */
484: }
485:
486: /* Check if we wrote to a bus-error region */
487: if (nBusErrorAccesses == 2)
488: {
1.1.1.8 ! root 489: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 490: }
491: }
492:
493:
494: /*-----------------------------------------------------------------------*/
1.1.1.3 root 495: /**
496: * Handle long-word write access to IO memory.
497: */
1.1 root 498: void IoMem_lput(uaecptr addr, uae_u32 val)
499: {
500: Uint32 idx;
501:
502: addr &= 0x00ffffff; /* Use a 24 bit address */
503:
1.1.1.7 root 504: LOG_TRACE(TRACE_IOMEM_WR, "IO write.l $%06x = $%08x\n", addr, val);
1.1.1.6 root 505:
1.1.1.5 root 506: if (addr < 0xff8000 || !regs.s)
1.1 root 507: {
508: /* invalid memory addressing --> bus error */
1.1.1.8 ! root 509: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 510: return;
511: }
512: if (addr > 0xfffffc)
513: {
514: fprintf(stderr, "Illegal IO memory access: IoMem_lput($%x)\n", addr);
515: return;
516: }
517:
518: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
519: nIoMemAccessSize = SIZE_LONG;
520: nBusErrorAccesses = 0;
521:
522: IoMem_WriteLong(addr, val);
523: idx = addr - 0xff8000;
524:
525: IoAccessCurrentAddress = addr;
526: pInterceptWriteTable[idx](); /* Call handler */
527:
528: if (pInterceptWriteTable[idx+1] != pInterceptWriteTable[idx])
529: {
530: IoAccessCurrentAddress = addr + 1;
531: pInterceptWriteTable[idx+1](); /* Call 2nd handler */
532: }
533:
534: if (pInterceptWriteTable[idx+2] != pInterceptWriteTable[idx+1])
535: {
536: IoAccessCurrentAddress = addr + 2;
537: pInterceptWriteTable[idx+2](); /* Call 3rd handler */
538: }
539:
540: if (pInterceptWriteTable[idx+3] != pInterceptWriteTable[idx+2])
541: {
542: IoAccessCurrentAddress = addr + 3;
543: pInterceptWriteTable[idx+3](); /* Call 4th handler */
544: }
545:
546: /* Check if we wrote to a bus-error region */
547: if (nBusErrorAccesses == 4)
548: {
1.1.1.8 ! root 549: M68000_BusError(addr, BUS_ERROR_WRITE);
1.1 root 550: }
551: }
552:
553:
554: /*-------------------------------------------------------------------------*/
1.1.1.3 root 555: /**
556: * This handler will be called if a ST program tries to read from an address
557: * that causes a bus error on a real ST. However, we can't call M68000_BusError()
558: * directly: For example, a "move.b $ff8204,d0" triggers a bus error on a real ST,
559: * while a "move.w $ff8204,d0" works! So we have to count the accesses to bus error
560: * addresses and we only trigger a bus error later if the count matches the complete
561: * access size (e.g. nBusErrorAccesses==4 for a long word access).
562: */
1.1 root 563: void IoMem_BusErrorEvenReadAccess(void)
564: {
565: nBusErrorAccesses += 1;
566: IoMem[IoAccessCurrentAddress] = 0xff;
567: }
568:
1.1.1.3 root 569: /**
570: * We need two handler so that the IoMem_*get functions can distinguish
571: * consecutive addresses.
572: */
1.1 root 573: void IoMem_BusErrorOddReadAccess(void)
574: {
575: nBusErrorAccesses += 1;
576: IoMem[IoAccessCurrentAddress] = 0xff;
577: }
578:
579: /*-------------------------------------------------------------------------*/
1.1.1.3 root 580: /**
581: * Same as IoMem_BusErrorReadAccess() but for write access this time.
582: */
1.1 root 583: void IoMem_BusErrorEvenWriteAccess(void)
584: {
585: nBusErrorAccesses += 1;
586: }
587:
1.1.1.3 root 588: /**
589: * We need two handler so that the IoMem_*put functions can distinguish
590: * consecutive addresses.
591: */
1.1 root 592: void IoMem_BusErrorOddWriteAccess(void)
593: {
594: nBusErrorAccesses += 1;
595: }
596:
597:
598: /*-------------------------------------------------------------------------*/
1.1.1.3 root 599: /**
600: * This is the read handler for the IO memory locations without an assigned
601: * IO register and which also do not generate a bus error. Reading from such
602: * a register will return the result 0xff.
603: */
1.1 root 604: void IoMem_VoidRead(void)
605: {
606: Uint32 a;
607:
608: /* handler is probably called only once, so we have to take care of the neighbour "void IO registers" */
609: for (a = IoAccessBaseAddress; a < IoAccessBaseAddress + nIoMemAccessSize; a++)
610: {
611: if (pInterceptReadTable[a - 0xff8000] == IoMem_VoidRead)
612: {
613: IoMem[a] = 0xff;
614: }
615: }
616: }
617:
618: /*-------------------------------------------------------------------------*/
1.1.1.3 root 619: /**
1.1.1.8 ! root 620: * This is the same function as IoMem_VoidRead, but for IO registers that
! 621: * return 0x00 instead of 0xff when read (this is the case for some video
! 622: * registers on STE, Falcon, ...)
! 623: */
! 624: void IoMem_VoidRead_00(void)
! 625: {
! 626: Uint32 a;
! 627:
! 628: /* handler is probably called only once, so we have to take care of the neighbour "void IO registers" */
! 629: for (a = IoAccessBaseAddress; a < IoAccessBaseAddress + nIoMemAccessSize; a++)
! 630: {
! 631: if (pInterceptReadTable[a - 0xff8000] == IoMem_VoidRead_00)
! 632: {
! 633: IoMem[a] = 0x00;
! 634: }
! 635: }
! 636: }
! 637:
! 638: /*-------------------------------------------------------------------------*/
! 639: /**
1.1.1.3 root 640: * This is the write handler for the IO memory locations without an assigned
641: * IO register and which also do not generate a bus error. We simply ignore
642: * a write access to these registers.
643: */
1.1 root 644: void IoMem_VoidWrite(void)
645: {
646: /* Nothing... */
647: }
648:
649:
650: /*-------------------------------------------------------------------------*/
1.1.1.3 root 651: /**
652: * A dummy function that does nothing at all - for memory regions that don't
653: * need a special handler for read access.
654: */
1.1 root 655: void IoMem_ReadWithoutInterception(void)
656: {
657: /* Nothing... */
658: }
659:
660: /*-------------------------------------------------------------------------*/
1.1.1.3 root 661: /**
662: * A dummy function that does nothing at all - for memory regions that don't
663: * need a special handler for write access.
664: */
1.1 root 665: void IoMem_WriteWithoutInterception(void)
666: {
667: /* Nothing... */
668: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.