|
|
1.1 ! root 1: /* NeXT system registers emulation */ ! 2: ! 3: #include <stdlib.h> ! 4: #include "main.h" ! 5: #include "ioMem.h" ! 6: #include "ioMemTables.h" ! 7: #include "video.h" ! 8: #include "configuration.h" ! 9: #include "sysdeps.h" ! 10: #include "m68000.h" ! 11: #include "dsp.h" ! 12: #include "sysReg.h" ! 13: #include "rtcnvram.h" ! 14: #include "statusbar.h" ! 15: #include "host.h" ! 16: ! 17: #define LOG_HARDCLOCK_LEVEL LOG_DEBUG ! 18: #define LOG_SOFTINT_LEVEL LOG_DEBUG ! 19: #define LOG_DSP_LEVEL LOG_DEBUG ! 20: ! 21: #define IO_SEG_MASK 0x1FFFF ! 22: ! 23: int SCR_ROM_overlay=0; ! 24: ! 25: static Uint32 scr1=0x00000000; ! 26: ! 27: static Uint8 scr2_0=0x00; ! 28: static Uint8 scr2_1=0x00; ! 29: static Uint8 scr2_2=0x00; ! 30: static Uint8 scr2_3=0x00; ! 31: ! 32: static Uint32 intStat=0x00000000; ! 33: static Uint32 intMask=0x00000000; ! 34: ! 35: ! 36: ! 37: void SID_Read(void) { ! 38: Log_Printf(LOG_WARN,"SID read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 39: IoMem[IoAccessCurrentAddress & 0x1FFFF]=0x00; // slot ID 0 ! 40: } ! 41: ! 42: /* System Control Register 1 ! 43: * ! 44: * These values are valid for all non-Turbo systems: ! 45: * -------- -------- -------- ------xx bits 0:1 --> cpu speed ! 46: * -------- -------- -------- ----xx-- bits 2:3 --> reserved ! 47: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed ! 48: * -------- -------- -------- xx------ bits 6:7 --> video memory speed ! 49: * -------- -------- ----xxxx -------- bits 8:11 --> board revision ! 50: * -------- -------- xxxx---- -------- bits 12:15 --> cpu type ! 51: * -------- xxxxxxxx -------- -------- bits 16:23 --> dma revision ! 52: * ----xxxx -------- -------- -------- bits 24:27 --> reserved ! 53: * xxxx---- -------- -------- -------- bits 28:31 --> slot id ! 54: * ! 55: * cpu speed: 0 = 40MHz, 1 = 20MHz, 2 = 25MHz, 3 = 33MHz ! 56: * main mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns ! 57: * video mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns ! 58: * board revision: for 030 Cube: ! 59: * 0 = DCD input inverted ! 60: * 1 = DCD polarity fixed ! 61: * 2 = must disable DSP mem before reset ! 62: * cpu type: 0 = NeXT Computer (68030) ! 63: * 1 = NeXTstation monochrome ! 64: * 2 = NeXTcube ! 65: * 3 = NeXTstation color ! 66: * 4 = all Turbo systems ! 67: * dma revision: 1 on all systems ? ! 68: * slot id: f on Turbo systems (cube too?), 0 on other systems ! 69: * ! 70: * ! 71: * These bits are always 0 on all Turbo systems: ! 72: * ----xxxx xxxxxxxx ----xxxx xxxxxxxx ! 73: */ ! 74: ! 75: /* for Slab 040: ! 76: * 0000 0000 0000 0001 0001 0000 0101 0010 ! 77: * 00 01 10 52 ! 78: * ! 79: * for Cube 030: ! 80: * 0000 0000 0000 0001 0000 0001 0101 0010 ! 81: * 00 01 01 52 ! 82: */ ! 83: #define SCR1_NEXT_COMPUTER 0x00010152 ! 84: #define SCR1_SLAB_MONO 0x00011052 ! 85: #define SCR1_SLAB_COLOR 0x00013052 ! 86: #define SCR1_CUBE 0x00012052 ! 87: #define SCR1_TURBO 0x00004000 ! 88: ! 89: #define SCR1_CONST_MASK 0xFFFFFF00 ! 90: ! 91: void SCR_Reset(void) { ! 92: SCR_ROM_overlay = 0; ! 93: ! 94: scr2_0=0x00; ! 95: scr2_1=0x00; ! 96: if (ConfigureParams.System.bTurbo) { ! 97: scr2_2=0x10; ! 98: scr2_3=0x80; ! 99: } else { ! 100: scr2_2=0x00; ! 101: scr2_3=0x00; ! 102: } ! 103: ! 104: intStat=0x00000000; ! 105: intMask=0x00000000; ! 106: ! 107: if (ConfigureParams.System.bTurbo) { ! 108: scr1 = SCR1_TURBO; ! 109: scr1 |= (ConfigureParams.System.nMachineType==NEXT_CUBE040)?0:0xF0000000; ! 110: return; ! 111: } else { ! 112: switch (ConfigureParams.System.nMachineType) { ! 113: case NEXT_CUBE030: ! 114: scr1 = SCR1_NEXT_COMPUTER & SCR1_CONST_MASK; ! 115: break; ! 116: case NEXT_CUBE040: ! 117: scr1 = SCR1_CUBE & SCR1_CONST_MASK; ! 118: break; ! 119: case NEXT_STATION: ! 120: if (ConfigureParams.System.bColor) ! 121: scr1 = SCR1_SLAB_COLOR & SCR1_CONST_MASK; ! 122: else ! 123: scr1 = SCR1_SLAB_MONO & SCR1_CONST_MASK; ! 124: break; ! 125: default: ! 126: break; ! 127: } ! 128: } ! 129: ! 130: Uint8 cpu_speed; ! 131: Uint8 memory_speed = 0; ! 132: ! 133: if (ConfigureParams.System.nCpuFreq<20) { ! 134: cpu_speed = 0; ! 135: } else if (ConfigureParams.System.nCpuFreq<25) { ! 136: cpu_speed = 1; ! 137: } else if (ConfigureParams.System.nCpuFreq<33) { ! 138: cpu_speed = 2; ! 139: } else { ! 140: cpu_speed = 3; ! 141: } ! 142: ! 143: switch (ConfigureParams.Memory.nMemorySpeed) { ! 144: case MEMORY_120NS: memory_speed = 0x00; break; ! 145: case MEMORY_100NS: memory_speed = 0x50; break; ! 146: case MEMORY_80NS: memory_speed = 0xA0; break; ! 147: case MEMORY_60NS: memory_speed = 0xF0; break; ! 148: default: Log_Printf(LOG_WARN, "SCR1 error: unknown memory speed\n"); break; ! 149: } ! 150: scr1 |= ((memory_speed&0xF0)|(cpu_speed&0x03)); ! 151: } ! 152: ! 153: void SCR1_Read0(void) ! 154: { ! 155: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 156: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0xFF000000)>>24; ! 157: } ! 158: void SCR1_Read1(void) ! 159: { ! 160: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 161: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x00FF0000)>>16; ! 162: } ! 163: void SCR1_Read2(void) ! 164: { ! 165: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 166: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x0000FF00)>>8; ! 167: } ! 168: void SCR1_Read3(void) ! 169: { ! 170: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 171: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = scr1&0x000000FF; ! 172: } ! 173: ! 174: ! 175: /* System Control Register 2 ! 176: ! 177: s_dsp_reset : 1, ! 178: s_dsp_block_end : 1, ! 179: s_dsp_unpacked : 1, ! 180: s_dsp_mode_B : 1, ! 181: s_dsp_mode_A : 1, ! 182: s_remote_int : 1, ! 183: s_local_int : 2, ! 184: s_dram_256K : 4, ! 185: s_dram_1M : 4, ! 186: s_timer_on_ipl7 : 1, ! 187: s_rom_wait_states : 3, ! 188: s_rom_1M : 1, ! 189: s_rtdata : 1, ! 190: s_rtclk : 1, ! 191: s_rtce : 1, ! 192: s_rom_overlay : 1, ! 193: s_dsp_int_en : 1, ! 194: s_dsp_mem_en : 1, ! 195: s_reserved : 4, ! 196: s_led : 1; ! 197: ! 198: */ ! 199: ! 200: /* byte 0 */ ! 201: #define SCR2_DSP_RESET 0x80 ! 202: #define SCR2_DSP_BLK_END 0x40 ! 203: #define SCR2_DSP_UNPKD 0x20 ! 204: #define SCR2_DSP_MODE_B 0x10 ! 205: #define SCR2_DSP_MODE_A 0x08 ! 206: #define SCR2_SOFTINT2 0x02 ! 207: #define SCR2_SOFTINT1 0x01 ! 208: ! 209: /* byte 2 */ ! 210: #define SCR2_TIMERIPL7 0x80 ! 211: #define SCR2_RTDATA 0x04 ! 212: #define SCR2_RTCLK 0x02 ! 213: #define SCR2_RTCE 0x01 ! 214: ! 215: /* byte 3 */ ! 216: #define SCR2_ROM 0x80 ! 217: #define SCR2_DSP_INT_EN 0x40 ! 218: #define SCR2_DSP_MEM_EN 0x20 ! 219: #define SCR2_LED 0x01 ! 220: ! 221: ! 222: void SCR2_Write0(void) ! 223: { ! 224: Uint8 old_scr2_0=scr2_0; ! 225: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc()); ! 226: scr2_0=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 227: ! 228: if ((old_scr2_0&SCR2_SOFTINT1)!=(scr2_0&SCR2_SOFTINT1)) { ! 229: Log_Printf(LOG_SOFTINT_LEVEL,"SCR2 SCR2_SOFTINT1 change at $%08x val=%x PC=$%08x\n", ! 230: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT1,m68k_getpc()); ! 231: if (scr2_0&SCR2_SOFTINT1) ! 232: set_interrupt(INT_SOFT1,SET_INT); ! 233: else ! 234: set_interrupt(INT_SOFT1,RELEASE_INT); ! 235: } ! 236: ! 237: if ((old_scr2_0&SCR2_SOFTINT2)!=(scr2_0&SCR2_SOFTINT2)) { ! 238: Log_Printf(LOG_SOFTINT_LEVEL,"SCR2 SCR2_SOFTINT2 change at $%08x val=%x PC=$%08x\n", ! 239: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT2,m68k_getpc()); ! 240: if (scr2_0&SCR2_SOFTINT2) ! 241: set_interrupt(INT_SOFT2,SET_INT); ! 242: else ! 243: set_interrupt(INT_SOFT2,RELEASE_INT); ! 244: } ! 245: ! 246: /* DSP bits */ ! 247: if (scr2_0&SCR2_DSP_MODE_A) { ! 248: Log_Printf(LOG_DSP_LEVEL,"[SCR2] DSP Mode A"); ! 249: } ! 250: if (scr2_0&SCR2_DSP_MODE_B) { ! 251: Log_Printf(LOG_DSP_LEVEL,"[SCR2] DSP Mode B"); ! 252: } ! 253: if (!(scr2_0&SCR2_DSP_RESET) && (old_scr2_0&SCR2_DSP_RESET)) { ! 254: Log_Printf(LOG_DSP_LEVEL,"[SCR2] DSP Reset"); ! 255: DSP_Reset(); ! 256: } else if ((scr2_0&SCR2_DSP_RESET) && !(old_scr2_0&SCR2_DSP_RESET)) { ! 257: Log_Printf(LOG_DSP_LEVEL,"[SCR2] DSP Start (mode %i)",(~(scr2_0>>3))&3); ! 258: DSP_Start((~(scr2_0>>3))&3); ! 259: } ! 260: dsp_intr_at_block_end = scr2_0&SCR2_DSP_BLK_END; ! 261: if ((old_scr2_0&SCR2_DSP_BLK_END) != (scr2_0&SCR2_DSP_BLK_END)) { ! 262: Log_Printf(LOG_DSP_LEVEL,"[SCR2] %s DSP interrupt from DMA at block end",dsp_intr_at_block_end?"Enable":"Disable"); ! 263: } ! 264: dsp_dma_unpacked = scr2_0&SCR2_DSP_UNPKD; ! 265: if ((old_scr2_0&SCR2_DSP_UNPKD) != (scr2_0&SCR2_DSP_UNPKD)) { ! 266: Log_Printf(LOG_DSP_LEVEL,"[SCR2] %s DSP DMA unpacked mode",dsp_dma_unpacked?"Enable":"Disable"); ! 267: } ! 268: } ! 269: ! 270: void SCR2_Read0(void) ! 271: { ! 272: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 273: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_0; ! 274: } ! 275: ! 276: void SCR2_Write1(void) ! 277: { ! 278: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc()); ! 279: scr2_1=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 280: } ! 281: ! 282: void SCR2_Read1(void) ! 283: { ! 284: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 285: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_1; ! 286: } ! 287: ! 288: void SCR2_Write2(void) ! 289: { ! 290: Uint8 old_scr2_2=scr2_2; ! 291: ! 292: scr2_2=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 293: ! 294: if ((old_scr2_2&SCR2_TIMERIPL7)!=(scr2_2&SCR2_TIMERIPL7)) { ! 295: Log_Printf(LOG_WARN,"SCR2 TIMER IPL7 change at $%08x val=%x PC=$%08x\n", ! 296: IoAccessCurrentAddress,scr2_2&SCR2_TIMERIPL7,m68k_getpc()); ! 297: } ! 298: ! 299: /* RTC enabled */ ! 300: if (scr2_2&SCR2_RTCE) { ! 301: if (((old_scr2_2&SCR2_RTCLK)!=(scr2_2&SCR2_RTCLK)) && ((scr2_2&SCR2_RTCLK)==0) ) { ! 302: Uint8 rtdata = scr2_2&SCR2_RTDATA; ! 303: scr2_2 &= ~SCR2_RTDATA; ! 304: scr2_2 |= rtc_interface_io(rtdata)?SCR2_RTDATA:0; ! 305: } ! 306: } else { ! 307: rtc_interface_reset(); ! 308: } ! 309: } ! 310: ! 311: void SCR2_Read2(void) ! 312: { ! 313: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 314: // IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2 & (SCR2_RTDATA|SCR2_RTCLK|SCR2_RTCE)); // + data ! 315: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2; ! 316: } ! 317: ! 318: void SCR2_Write3(void) ! 319: { ! 320: Uint8 old_scr2_3=scr2_3; ! 321: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc()); ! 322: scr2_3=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 323: if ((old_scr2_3&SCR2_ROM)!=(scr2_3&SCR2_ROM)) { ! 324: Log_Printf(LOG_WARN,"SCR2 ROM change at $%08x val=%x PC=$%08x\n", ! 325: IoAccessCurrentAddress,scr2_3&SCR2_ROM,m68k_getpc()); ! 326: SCR_ROM_overlay=scr2_3&SCR2_ROM; ! 327: } ! 328: if ((old_scr2_3&SCR2_LED)!=(scr2_3&SCR2_LED)) { ! 329: Log_Printf(LOG_DEBUG,"SCR2 LED change at $%08x val=%x PC=$%08x\n", ! 330: IoAccessCurrentAddress,scr2_3&SCR2_LED,m68k_getpc()); ! 331: Statusbar_SetSystemLed(scr2_3&SCR2_LED); ! 332: } ! 333: ! 334: if ((old_scr2_3&SCR2_DSP_INT_EN) != (scr2_3&SCR2_DSP_INT_EN)) { ! 335: Log_Printf(LOG_DSP_LEVEL,"[SCR2] DSP interrupt at level %i",(scr2_3&SCR2_DSP_INT_EN)?4:3); ! 336: if (intStat&(INT_DSP_L3|INT_DSP_L4)) { ! 337: Log_Printf(LOG_DSP_LEVEL,"[SCR2] Switching DSP interrupt to level %i",(scr2_3&SCR2_DSP_INT_EN)?4:3); ! 338: set_interrupt(INT_DSP_L3|INT_DSP_L4, RELEASE_INT); ! 339: set_dsp_interrupt(SET_INT); ! 340: } ! 341: } ! 342: if ((old_scr2_3&SCR2_DSP_MEM_EN) != (scr2_3&SCR2_DSP_MEM_EN)) { ! 343: Log_Printf(LOG_DSP_LEVEL,"[SCR2] %s DSP memory",(scr2_3&SCR2_DSP_MEM_EN)?"Enable":"Disable"); ! 344: } ! 345: } ! 346: ! 347: ! 348: void SCR2_Read3(void) ! 349: { ! 350: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc()); ! 351: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_3; ! 352: } ! 353: ! 354: ! 355: ! 356: /* Interrupt Status Register */ ! 357: ! 358: void IntRegStatRead(void) { ! 359: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, intStat); ! 360: } ! 361: ! 362: void IntRegStatWrite(void) { ! 363: intStat = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK); ! 364: } ! 365: ! 366: void set_dsp_interrupt(Uint8 state) { ! 367: if (scr2_3&SCR2_DSP_INT_EN || ConfigureParams.System.bTurbo) { ! 368: set_interrupt(INT_DSP_L4, state); ! 369: } else { ! 370: set_interrupt(INT_DSP_L3, state); ! 371: } ! 372: } ! 373: ! 374: void set_interrupt(Uint32 intr, Uint8 state) { ! 375: /* The interrupt gets polled by the cpu via intlev() ! 376: * --> see previous-glue.c ! 377: */ ! 378: if (state==SET_INT) { ! 379: intStat |= intr; ! 380: } else { ! 381: intStat &= ~intr; ! 382: } ! 383: } ! 384: ! 385: int get_interrupt_level(void) { ! 386: Uint32 interrupt = intStat&intMask; ! 387: ! 388: if (!interrupt) { ! 389: return 0; ! 390: } else if (interrupt&INT_L7_MASK) { ! 391: return 7; ! 392: } else if ((interrupt&INT_TIMER) && (scr2_2&SCR2_TIMERIPL7)) { ! 393: return 7; ! 394: } else if (interrupt&INT_L6_MASK) { ! 395: return 6; ! 396: } else if (interrupt&INT_L5_MASK) { ! 397: return 5; ! 398: } else if (interrupt&INT_L4_MASK) { ! 399: return 4; ! 400: } else if (interrupt&INT_L3_MASK) { ! 401: return 3; ! 402: } else if (interrupt&INT_L2_MASK) { ! 403: return 2; ! 404: } else if (interrupt&INT_L1_MASK) { ! 405: return 1; ! 406: } else { ! 407: abort(); ! 408: } ! 409: } ! 410: ! 411: /* Interrupt Mask Register */ ! 412: ! 413: void IntRegMaskRead(void) { ! 414: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK,intMask); ! 415: } ! 416: ! 417: void IntRegMaskWrite(void) { ! 418: intMask = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK); ! 419: Log_Printf(LOG_DEBUG,"Interrupt mask: %08x", intMask); ! 420: } ! 421: ! 422: ! 423: /* Hardclock internal interrupt */ ! 424: ! 425: #define HARDCLOCK_ENABLE 0x80 ! 426: #define HARDCLOCK_LATCH 0x40 ! 427: #define HARDCLOCK_ZERO 0x3F ! 428: ! 429: static Uint8 hardclock_csr=0; ! 430: static Uint8 hardclock1=0; ! 431: static Uint8 hardclock0=0; ! 432: static int latch_hardclock=0; ! 433: ! 434: static Uint64 hardClockLastLatch; ! 435: ! 436: void Hardclock_InterruptHandler ( void ) ! 437: { ! 438: CycInt_AcknowledgeInterrupt(); ! 439: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) { ! 440: // Log_Printf(LOG_WARN,"[INT] throwing hardclock %lld", host_time_us()); ! 441: set_interrupt(INT_TIMER,SET_INT); ! 442: Uint64 now = host_time_us(); ! 443: host_hardclock(latch_hardclock, now - hardClockLastLatch); ! 444: hardClockLastLatch = now; ! 445: CycInt_AddRelativeInterruptUs(latch_hardclock, 0, INTERRUPT_HARDCLOCK); ! 446: } ! 447: } ! 448: ! 449: ! 450: void HardclockRead0(void){ ! 451: IoMem[IoAccessCurrentAddress & 0x1FFFF]=(latch_hardclock>>8); ! 452: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 453: } ! 454: void HardclockRead1(void){ ! 455: IoMem[IoAccessCurrentAddress & 0x1FFFF]=latch_hardclock&0xff; ! 456: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 457: } ! 458: ! 459: void HardclockWrite0(void){ ! 460: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 461: hardclock0=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 462: } ! 463: void HardclockWrite1(void){ ! 464: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x",IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 465: hardclock1=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 466: } ! 467: ! 468: void HardclockWriteCSR(void) { ! 469: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 470: hardclock_csr=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 471: if (hardclock_csr&HARDCLOCK_LATCH) { ! 472: hardclock_csr&= ~HARDCLOCK_LATCH; ! 473: latch_hardclock=(hardclock0<<8)|hardclock1; ! 474: hardClockLastLatch = host_time_us(); ! 475: } ! 476: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) { ! 477: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] enable periodic interrupt (%i microseconds).", latch_hardclock); ! 478: CycInt_AddRelativeInterruptUs(latch_hardclock, 0, INTERRUPT_HARDCLOCK); ! 479: } else { ! 480: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] disable periodic interrupt."); ! 481: } ! 482: set_interrupt(INT_TIMER,RELEASE_INT); ! 483: } ! 484: void HardclockReadCSR(void) { ! 485: IoMem[IoAccessCurrentAddress & 0x1FFFF]=hardclock_csr; ! 486: // Log_Printf(LOG_WARN,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc()); ! 487: set_interrupt(INT_TIMER,RELEASE_INT); ! 488: } ! 489: ! 490: ! 491: /* Event counter register */ ! 492: ! 493: static Uint64 sysTimerOffset = 0; ! 494: static bool resetTimer; ! 495: ! 496: void System_Timer_Read(void) { ! 497: Uint64 now = host_time_us(); ! 498: if(resetTimer) { ! 499: sysTimerOffset = now; ! 500: resetTimer = false; ! 501: } ! 502: now -= sysTimerOffset; ! 503: IoMem_WriteLong(IoAccessCurrentAddress&IO_SEG_MASK, now & 0xFFFFF); ! 504: } ! 505: ! 506: void System_Timer_Write(void) { ! 507: resetTimer = true; ! 508: } ! 509: ! 510: /* Color Video Interrupt Register */ ! 511: ! 512: #define VID_CMD_CLEAR_INT 0x01 ! 513: #define VID_CMD_ENABLE_INT 0x02 ! 514: #define VID_CMD_UNBLANK 0x04 ! 515: ! 516: Uint8 col_vid_intr = 0; ! 517: ! 518: void ColorVideo_CMD_Write(void) { ! 519: col_vid_intr=IoMem[IoAccessCurrentAddress & 0x1FFFF]; ! 520: Log_Printf(LOG_DEBUG,"[Color Video] Command write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 521: ! 522: if (col_vid_intr&VID_CMD_CLEAR_INT) { ! 523: set_interrupt(INT_DISK, RELEASE_INT); ! 524: } ! 525: } ! 526: ! 527: void color_video_interrupt(void) { ! 528: if (col_vid_intr&VID_CMD_ENABLE_INT) { ! 529: set_interrupt(INT_DISK, SET_INT); ! 530: col_vid_intr &= ~VID_CMD_ENABLE_INT; ! 531: } ! 532: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.