|
|
1.1 ! root 1: #include "main.h" ! 2: #include "configuration.h" ! 3: #include "m68000.h" ! 4: #include "sysdeps.h" ! 5: #include "sysReg.h" ! 6: #include "adb.h" ! 7: #include "tmc.h" ! 8: ! 9: #define LOG_TMC_LEVEL LOG_DEBUG ! 10: ! 11: /* NeXT TMC emulation */ ! 12: ! 13: #define TMC_ADB_ADDR_MASK 0x02208000 ! 14: ! 15: #define TMC_REGS_MASK 0x0000FFFF ! 16: ! 17: /* TMC registers */ ! 18: ! 19: struct { ! 20: Uint32 scr1; ! 21: Uint32 control; ! 22: Uint32 horizontal; ! 23: Uint32 vertical; ! 24: Uint8 video_intr; ! 25: Uint32 nitro; ! 26: } tmc; ! 27: ! 28: /* Additional System Control Register for Turbo systems: ! 29: * -------- -------- -------- -----xxx bits 0:2 --> cpu speed ! 30: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed ! 31: * -------- -------- -------- xx------ bits 6:7 --> video memory speed ! 32: * -------- -------- ----xxxx -------- bits 8:11 --> cpu revision ! 33: * -------- -------- xxxx---- -------- bits 12:15 --> cpu type ! 34: * xxxx---- -------- -------- -------- bits 28:31 --> slot id ! 35: * ----xxxx xxxxxxxx -------- ----x--- all other bits: 1 ! 36: * ! 37: * cpu speed: 7 = 33MHz? ! 38: * main mem speed: 0 = 60ns, 1 = 70ns, 2 = 80ns, 3 = 100ns ! 39: * video mem speed: 3 on all Turbo systems (100ns)? ! 40: * cpu revision: 0xF = rev 0 ! 41: * 0xE = rev 1 ! 42: * 0xD = rev 2 ! 43: * 0xC - 0x0: rev 3 - 15 ! 44: * cpu type: 4 = NeXTstation turbo monochrome ! 45: * 5 = NeXTstation turbo color ! 46: * 8 = NeXTcube turbo ! 47: */ ! 48: ! 49: #define TURBOSCR_FMASK 0x0FFF0F08 ! 50: ! 51: void TurboSCR1_Reset(void) { ! 52: Uint8 memory_speed; ! 53: Uint8 cpu_speed = 0x07; // 33 MHz ! 54: ! 55: if (ConfigureParams.System.nCpuFreq<20) { ! 56: cpu_speed = 4; ! 57: } else if (ConfigureParams.System.nCpuFreq<25) { ! 58: cpu_speed = 5; ! 59: } else if (ConfigureParams.System.nCpuFreq<33) { ! 60: cpu_speed = 6; ! 61: } else { ! 62: cpu_speed = 7; ! 63: } ! 64: ! 65: switch (ConfigureParams.Memory.nMemorySpeed) { ! 66: case MEMORY_120NS: memory_speed = 0x00; break; ! 67: case MEMORY_100NS: memory_speed = 0x50; break; ! 68: case MEMORY_80NS: memory_speed = 0xA0; break; ! 69: case MEMORY_60NS: memory_speed = 0xF0; break; ! 70: default: Log_Printf(LOG_WARN, "Turbo SCR1 error: unknown memory speed\n"); break; ! 71: } ! 72: tmc.scr1 = ((memory_speed&0xF0)|(cpu_speed&0x07)); ! 73: if (ConfigureParams.System.nMachineType == NEXT_CUBE040) ! 74: tmc.scr1 |= 0x8000; ! 75: else if (ConfigureParams.System.bColor) { ! 76: tmc.scr1 |= 0x5000; ! 77: } else { ! 78: tmc.scr1 |= 0x4000; ! 79: } ! 80: tmc.scr1 |= TURBOSCR_FMASK; ! 81: } ! 82: ! 83: ! 84: ! 85: /* Register read/write functions */ ! 86: ! 87: Uint8 tmc_ill_read(void) { ! 88: Log_Printf(LOG_WARN, "[TMC] Illegal read!\n"); ! 89: return 0; ! 90: } ! 91: ! 92: void tmc_ill_write(Uint8 val) { ! 93: Log_Printf(LOG_WARN, "[TMC] Illegal write!\n"); ! 94: } ! 95: ! 96: Uint8 tmc_unimpl_read(void) { ! 97: Log_Printf(LOG_WARN, "[TMC] Unimplemented read!\n"); ! 98: return 0; ! 99: } ! 100: ! 101: void tmc_unimpl_write(Uint8 val) { ! 102: Log_Printf(LOG_WARN, "[TMC] Unimplemented write!\n"); ! 103: } ! 104: ! 105: Uint8 tmc_void_read(void) { ! 106: return 0; ! 107: } ! 108: ! 109: void tmc_void_write(Uint8 val) { ! 110: } ! 111: ! 112: /* SCR1 */ ! 113: Uint8 tmc_scr1_read0(void) { ! 114: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200000 PC=$%08x\n",m68k_getpc()); ! 115: return (tmc.scr1>>24); ! 116: } ! 117: Uint8 tmc_scr1_read1(void) { ! 118: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200001 PC=$%08x\n",m68k_getpc()); ! 119: return (tmc.scr1>>16); ! 120: } ! 121: Uint8 tmc_scr1_read2(void) { ! 122: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200002 PC=$%08x\n",m68k_getpc()); ! 123: return (tmc.scr1>>8); ! 124: } ! 125: Uint8 tmc_scr1_read3(void) { ! 126: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200003 PC=$%08x\n",m68k_getpc()); ! 127: return tmc.scr1; ! 128: } ! 129: ! 130: /* TMC Control Register */ ! 131: ! 132: Uint8 tmc_ctrl_read0(void) { ! 133: return (tmc.control>>24); ! 134: } ! 135: Uint8 tmc_ctrl_read1(void) { ! 136: return (tmc.control>>16); ! 137: } ! 138: Uint8 tmc_ctrl_read2(void) { ! 139: return (tmc.control>>8); ! 140: } ! 141: Uint8 tmc_ctrl_read3(void) { ! 142: return tmc.control; ! 143: } ! 144: ! 145: void tmc_ctrl_write0(Uint8 val) { ! 146: tmc.control &= 0x00FFFFFF; ! 147: tmc.control |= (val&0xFF)<<24; ! 148: } ! 149: void tmc_ctrl_write1(Uint8 val) { ! 150: tmc.control &= 0xFF00FFFF; ! 151: tmc.control |= (val&0xFF)<<16; ! 152: } ! 153: void tmc_ctrl_write2(Uint8 val) { ! 154: val &= ~0x04; /* no parity memory */ ! 155: ! 156: tmc.control &= 0xFFFF00FF; ! 157: tmc.control |= (val&0xFF)<<8; ! 158: } ! 159: void tmc_ctrl_write3(Uint8 val) { ! 160: tmc.control &= 0xFFFFFF00; ! 161: tmc.control |= val&0xFF; ! 162: } ! 163: ! 164: ! 165: /* Video Interrupt Register */ ! 166: #define TMC_VI_INTERRUPT 0x01 ! 167: #define TMC_VI_INT_MASK 0x02 ! 168: ! 169: /* Horizontal and Vertical Configruation Registers */ ! 170: #define HFPORCH 0x18 ! 171: #define HSYNC 0x20 ! 172: #define HBPORCH 0x48 ! 173: #define HDISCNT 0x118 ! 174: ! 175: #define VFPORCH 0x08 ! 176: #define VSYNC 0x08 ! 177: #define VBPORCH 0x30 ! 178: #define VDISCNT 0x340 ! 179: ! 180: void tmc_video_reg_reset(void) { ! 181: tmc.video_intr = 0x00; ! 182: tmc.horizontal = (HFPORCH<<25)|(HSYNC<<19)|(HBPORCH<<12)|HDISCNT; ! 183: tmc.vertical = (VFPORCH<<25)|(VSYNC<<19)|(VBPORCH<<12)|VDISCNT; ! 184: } ! 185: ! 186: void tmc_video_interrupt(void) { ! 187: if (tmc.video_intr&TMC_VI_INT_MASK) { ! 188: set_interrupt(INT_DISK, SET_INT); ! 189: tmc.video_intr |= TMC_VI_INTERRUPT; ! 190: } ! 191: } ! 192: ! 193: Uint8 tmc_vir_read0(void) { ! 194: return tmc.video_intr; ! 195: } ! 196: ! 197: void tmc_vir_write0(Uint8 val) { ! 198: tmc.video_intr = val; ! 199: if (tmc.video_intr&TMC_VI_INTERRUPT) { ! 200: tmc.video_intr &= ~TMC_VI_INTERRUPT; ! 201: set_interrupt(INT_DISK, RELEASE_INT); ! 202: } ! 203: } ! 204: ! 205: Uint8 tmc_hcr_read0(void) { ! 206: return (tmc.horizontal>>24); ! 207: } ! 208: Uint8 tmc_hcr_read1(void) { ! 209: return (tmc.horizontal>>16); ! 210: } ! 211: Uint8 tmc_hcr_read2(void) { ! 212: return (tmc.horizontal>>8); ! 213: } ! 214: Uint8 tmc_hcr_read3(void) { ! 215: return tmc.horizontal; ! 216: } ! 217: ! 218: void tmc_hcr_write0(Uint8 val) { ! 219: tmc.horizontal &= 0x00FFFFFF; ! 220: tmc.horizontal |= (val&0xFF)<<24; ! 221: } ! 222: void tmc_hcr_write1(Uint8 val) { ! 223: tmc.horizontal &= 0xFF00FFFF; ! 224: tmc.horizontal |= (val&0xFF)<<16; ! 225: } ! 226: void tmc_hcr_write2(Uint8 val) { ! 227: tmc.horizontal &= 0xFFFF00FF; ! 228: tmc.horizontal |= (val&0xFF)<<8; ! 229: } ! 230: void tmc_hcr_write3(Uint8 val) { ! 231: tmc.horizontal &= 0xFFFFFF00; ! 232: tmc.horizontal |= val&0xFF; ! 233: } ! 234: ! 235: Uint8 tmc_vcr_read0(void) { ! 236: return (tmc.vertical>>24); ! 237: } ! 238: Uint8 tmc_vcr_read1(void) { ! 239: return (tmc.vertical>>16); ! 240: } ! 241: Uint8 tmc_vcr_read2(void) { ! 242: return (tmc.vertical>>8); ! 243: } ! 244: Uint8 tmc_vcr_read3(void) { ! 245: return tmc.vertical; ! 246: } ! 247: ! 248: void tmc_vcr_write0(Uint8 val) { ! 249: tmc.vertical &= 0x00FFFFFF; ! 250: tmc.vertical |= (val&0xFF)<<24; ! 251: } ! 252: void tmc_vcr_write1(Uint8 val) { ! 253: tmc.vertical &= 0xFF00FFFF; ! 254: tmc.vertical |= (val&0xFF)<<16; ! 255: } ! 256: void tmc_vcr_write2(Uint8 val) { ! 257: tmc.vertical &= 0xFFFF00FF; ! 258: tmc.vertical |= (val&0xFF)<<8; ! 259: } ! 260: void tmc_vcr_write3(Uint8 val) { ! 261: tmc.vertical &= 0xFFFFFF00; ! 262: tmc.vertical |= val&0xFF; ! 263: } ! 264: ! 265: ! 266: /* Read register functions */ ! 267: static Uint8 (*tmc_read_reg[36])(void) = { ! 268: tmc_scr1_read0, tmc_scr1_read1, tmc_scr1_read2, tmc_scr1_read3, ! 269: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 270: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 271: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 272: tmc_ctrl_read0, tmc_ctrl_read1, tmc_ctrl_read2, tmc_ctrl_read3, ! 273: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 274: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 275: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 276: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read ! 277: }; ! 278: ! 279: static Uint8 (*tmc_read_vid_reg[16])(void) = { ! 280: tmc_vir_read0, tmc_void_read, tmc_void_read, tmc_void_read, ! 281: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 282: tmc_hcr_read0, tmc_hcr_read1, tmc_hcr_read2, tmc_hcr_read3, ! 283: tmc_vcr_read0, tmc_vcr_read1, tmc_vcr_read2, tmc_vcr_read3 ! 284: }; ! 285: ! 286: /* Write register functions */ ! 287: static void (*tmc_write_reg[36])(Uint8) = { ! 288: tmc_ill_write, tmc_ill_write, tmc_ill_write, tmc_ill_write, ! 289: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 290: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 291: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 292: tmc_ctrl_write0, tmc_ctrl_write1, tmc_ctrl_write2, tmc_ctrl_write3, ! 293: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 294: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 295: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 296: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write ! 297: }; ! 298: ! 299: static void (*tmc_write_vid_reg[16])(Uint8) = { ! 300: tmc_vir_write0, tmc_void_write, tmc_void_write, tmc_void_write, ! 301: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 302: tmc_hcr_write0, tmc_hcr_write1, tmc_hcr_write2, tmc_hcr_write3, ! 303: tmc_vcr_write0, tmc_vcr_write1, tmc_vcr_write2, tmc_vcr_write3 ! 304: }; ! 305: ! 306: ! 307: Uint32 tmc_lget(uaecptr addr) { ! 308: Uint32 val = 0; ! 309: ! 310: if (addr%4) { ! 311: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 312: abort(); ! 313: } ! 314: ! 315: if (addr==0x02210000) { ! 316: Log_Printf(LOG_WARN, "[TMC] Nitro register lget from $%08X",addr); ! 317: if (ConfigureParams.System.nCpuFreq==40) { ! 318: val = tmc.nitro; ! 319: } else { ! 320: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!"); ! 321: M68000_BusError(addr, 1); ! 322: } ! 323: return val; ! 324: } ! 325: ! 326: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 327: return adb_lget(addr); ! 328: } ! 329: ! 330: Log_Printf(LOG_TMC_LEVEL, "[TMC] lget from %08X",addr); ! 331: ! 332: addr &= TMC_REGS_MASK; ! 333: ! 334: if (addr<36) { ! 335: val = tmc_read_reg[addr]()<<24; ! 336: val |= tmc_read_reg[addr+1]()<<16; ! 337: val |= tmc_read_reg[addr+2]()<<8; ! 338: val |= tmc_read_reg[addr+3](); ! 339: } else if (addr>=128 && addr<144) { ! 340: val = tmc_read_vid_reg[addr&0xF]()<<24; ! 341: val |= tmc_read_vid_reg[(addr+1)&0xF]()<<16; ! 342: val |= tmc_read_vid_reg[(addr+2)&0xF]()<<8; ! 343: val |= tmc_read_vid_reg[(addr+3)&0xF](); ! 344: } ! 345: ! 346: return val; ! 347: } ! 348: ! 349: Uint32 tmc_wget(uaecptr addr) { ! 350: Uint32 val = 0; ! 351: ! 352: if (addr%2) { ! 353: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 354: abort(); ! 355: } ! 356: ! 357: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 358: return adb_wget(addr); ! 359: } ! 360: ! 361: Log_Printf(LOG_TMC_LEVEL, "[TMC] wget from %08X",addr); ! 362: ! 363: addr &= TMC_REGS_MASK; ! 364: ! 365: if (addr<36) { ! 366: val = tmc_read_reg[addr]()<<8; ! 367: val |= tmc_read_reg[addr+1](); ! 368: } else if (addr>=128 && addr<144) { ! 369: val = tmc_read_vid_reg[addr&0xF]()<<8; ! 370: val |= tmc_read_vid_reg[(addr+1)&0xF](); ! 371: } ! 372: ! 373: return val; ! 374: } ! 375: ! 376: Uint32 tmc_bget(uaecptr addr) { ! 377: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 378: return adb_bget(addr); ! 379: } ! 380: ! 381: Log_Printf(LOG_TMC_LEVEL, "[TMC] bget from %08X",addr); ! 382: ! 383: addr &= TMC_REGS_MASK; ! 384: ! 385: if (addr<36) { ! 386: return tmc_read_reg[addr](); ! 387: } else if (addr>=128 && addr<144) { ! 388: return tmc_read_vid_reg[addr&0xF](); ! 389: } ! 390: ! 391: return 0; ! 392: } ! 393: ! 394: void tmc_lput(uaecptr addr, Uint32 l) { ! 395: if (addr%4) { ! 396: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 397: abort(); ! 398: } ! 399: ! 400: if (addr==0x02210000) { ! 401: Log_Printf(LOG_WARN, "[TMC] Nitro register lput %08X at $%08X",l,addr); ! 402: if (ConfigureParams.System.nCpuFreq==40) { ! 403: tmc.nitro = l&0x0000011F; ! 404: } else { ! 405: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!"); ! 406: M68000_BusError(addr, 0); ! 407: } ! 408: return; ! 409: } ! 410: ! 411: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 412: adb_lput(addr, l); ! 413: return; ! 414: } ! 415: ! 416: Log_Printf(LOG_TMC_LEVEL, "[TMC] lput %08X to %08X",l,addr); ! 417: ! 418: addr &= TMC_REGS_MASK; ! 419: ! 420: if (addr<36) { ! 421: tmc_write_reg[addr](l>>24); ! 422: tmc_write_reg[addr+1](l>>16); ! 423: tmc_write_reg[addr+2](l>>8); ! 424: tmc_write_reg[addr+3](l); ! 425: } else if (addr>=128 && addr<144) { ! 426: tmc_write_vid_reg[addr&0xF](l>>24); ! 427: tmc_write_vid_reg[(addr+1)&0xF](l>>16); ! 428: tmc_write_vid_reg[(addr+2)&0xF](l>>8); ! 429: tmc_write_vid_reg[(addr+3)&0xF](l); ! 430: } ! 431: } ! 432: ! 433: void tmc_wput(uaecptr addr, Uint32 w) { ! 434: if (addr%2) { ! 435: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 436: abort(); ! 437: } ! 438: ! 439: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 440: adb_wput(addr, w); ! 441: return; ! 442: } ! 443: ! 444: Log_Printf(LOG_TMC_LEVEL, "[TMC] wput %04X to %08X",w,addr); ! 445: ! 446: addr &= TMC_REGS_MASK; ! 447: ! 448: if (addr<36) { ! 449: tmc_write_reg[addr](w>>8); ! 450: tmc_write_reg[addr+1](w); ! 451: } else if (addr>=128 && addr<144) { ! 452: tmc_write_vid_reg[addr&0xF](w>>8); ! 453: tmc_write_vid_reg[(addr+1)&0xF](w); ! 454: } ! 455: } ! 456: ! 457: void tmc_bput(uaecptr addr, Uint32 b) { ! 458: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 459: adb_bput(addr, b); ! 460: return; ! 461: } ! 462: ! 463: Log_Printf(LOG_TMC_LEVEL, "[TMC] bput %02X to %08X",b,addr); ! 464: ! 465: addr &= TMC_REGS_MASK; ! 466: ! 467: if (addr<36) { ! 468: tmc_write_reg[addr](b); ! 469: } else if (addr>=128 && addr<144) { ! 470: tmc_write_vid_reg[addr&0xF](b); ! 471: } ! 472: } ! 473: ! 474: ! 475: /* TMC Reset */ ! 476: ! 477: void TMC_Reset(void) { ! 478: TurboSCR1_Reset(); ! 479: ! 480: tmc_video_reg_reset(); ! 481: tmc.control = 0x0D17038F; ! 482: tmc.nitro = 0x00000000; ! 483: ADB_Reset(); ! 484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.