|
|
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: static void TurboSCR1_Reset(void) { ! 52: Uint8 memory_speed = 0; ! 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: static void tmc_ill_write(Uint8 val) { ! 88: Log_Printf(LOG_WARN, "[TMC] Illegal write!\n"); ! 89: } ! 90: ! 91: static Uint8 tmc_unimpl_read(void) { ! 92: Log_Printf(LOG_WARN, "[TMC] Unimplemented read!\n"); ! 93: return 0; ! 94: } ! 95: ! 96: static void tmc_unimpl_write(Uint8 val) { ! 97: Log_Printf(LOG_WARN, "[TMC] Unimplemented write!\n"); ! 98: } ! 99: ! 100: static Uint8 tmc_void_read(void) { ! 101: return 0; ! 102: } ! 103: ! 104: static void tmc_void_write(Uint8 val) { ! 105: } ! 106: ! 107: /* SCR1 */ ! 108: static Uint8 tmc_scr1_read0(void) { ! 109: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200000 PC=$%08x\n",m68k_getpc()); ! 110: return (tmc.scr1>>24); ! 111: } ! 112: static Uint8 tmc_scr1_read1(void) { ! 113: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200001 PC=$%08x\n",m68k_getpc()); ! 114: return (tmc.scr1>>16); ! 115: } ! 116: static Uint8 tmc_scr1_read2(void) { ! 117: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200002 PC=$%08x\n",m68k_getpc()); ! 118: return (tmc.scr1>>8); ! 119: } ! 120: static Uint8 tmc_scr1_read3(void) { ! 121: Log_Printf(LOG_WARN,"[TMC] SCR1 read at $0x2200003 PC=$%08x\n",m68k_getpc()); ! 122: return tmc.scr1; ! 123: } ! 124: ! 125: /* TMC Control Register */ ! 126: ! 127: static Uint8 tmc_ctrl_read0(void) { ! 128: return (tmc.control>>24); ! 129: } ! 130: static Uint8 tmc_ctrl_read1(void) { ! 131: return (tmc.control>>16); ! 132: } ! 133: static Uint8 tmc_ctrl_read2(void) { ! 134: return (tmc.control>>8); ! 135: } ! 136: static Uint8 tmc_ctrl_read3(void) { ! 137: return tmc.control; ! 138: } ! 139: ! 140: static void tmc_ctrl_write0(Uint8 val) { ! 141: tmc.control &= 0x00FFFFFF; ! 142: tmc.control |= (val&0xFF)<<24; ! 143: } ! 144: static void tmc_ctrl_write1(Uint8 val) { ! 145: tmc.control &= 0xFF00FFFF; ! 146: tmc.control |= (val&0xFF)<<16; ! 147: } ! 148: static void tmc_ctrl_write2(Uint8 val) { ! 149: val &= ~0x04; /* no parity memory */ ! 150: ! 151: tmc.control &= 0xFFFF00FF; ! 152: tmc.control |= (val&0xFF)<<8; ! 153: } ! 154: static void tmc_ctrl_write3(Uint8 val) { ! 155: tmc.control &= 0xFFFFFF00; ! 156: tmc.control |= val&0xFF; ! 157: } ! 158: ! 159: ! 160: /* Video Interrupt Register */ ! 161: #define TMC_VI_INTERRUPT 0x01 ! 162: #define TMC_VI_INT_MASK 0x02 ! 163: ! 164: /* Horizontal and Vertical Configruation Registers */ ! 165: #define HFPORCH 0x18 ! 166: #define HSYNC 0x20 ! 167: #define HBPORCH 0x48 ! 168: #define HDISCNT 0x118 ! 169: ! 170: #define VFPORCH 0x08 ! 171: #define VSYNC 0x08 ! 172: #define VBPORCH 0x30 ! 173: #define VDISCNT 0x340 ! 174: ! 175: static void tmc_video_reg_reset(void) { ! 176: tmc.video_intr = 0x00; ! 177: tmc.horizontal = (HFPORCH<<25)|(HSYNC<<19)|(HBPORCH<<12)|HDISCNT; ! 178: tmc.vertical = (VFPORCH<<25)|(VSYNC<<19)|(VBPORCH<<12)|VDISCNT; ! 179: } ! 180: ! 181: void tmc_video_interrupt(void) { ! 182: if (tmc.video_intr&TMC_VI_INT_MASK) { ! 183: set_interrupt(INT_DISK, SET_INT); ! 184: tmc.video_intr |= TMC_VI_INTERRUPT; ! 185: } ! 186: } ! 187: ! 188: static Uint8 tmc_vir_read0(void) { ! 189: return tmc.video_intr; ! 190: } ! 191: ! 192: static void tmc_vir_write0(Uint8 val) { ! 193: tmc.video_intr = val; ! 194: if (tmc.video_intr&TMC_VI_INTERRUPT) { ! 195: tmc.video_intr &= ~TMC_VI_INTERRUPT; ! 196: set_interrupt(INT_DISK, RELEASE_INT); ! 197: } ! 198: } ! 199: ! 200: static Uint8 tmc_hcr_read0(void) { ! 201: return (tmc.horizontal>>24); ! 202: } ! 203: static Uint8 tmc_hcr_read1(void) { ! 204: return (tmc.horizontal>>16); ! 205: } ! 206: static Uint8 tmc_hcr_read2(void) { ! 207: return (tmc.horizontal>>8); ! 208: } ! 209: static Uint8 tmc_hcr_read3(void) { ! 210: return tmc.horizontal; ! 211: } ! 212: ! 213: static void tmc_hcr_write0(Uint8 val) { ! 214: tmc.horizontal &= 0x00FFFFFF; ! 215: tmc.horizontal |= (val&0xFF)<<24; ! 216: } ! 217: static void tmc_hcr_write1(Uint8 val) { ! 218: tmc.horizontal &= 0xFF00FFFF; ! 219: tmc.horizontal |= (val&0xFF)<<16; ! 220: } ! 221: static void tmc_hcr_write2(Uint8 val) { ! 222: tmc.horizontal &= 0xFFFF00FF; ! 223: tmc.horizontal |= (val&0xFF)<<8; ! 224: } ! 225: static void tmc_hcr_write3(Uint8 val) { ! 226: tmc.horizontal &= 0xFFFFFF00; ! 227: tmc.horizontal |= val&0xFF; ! 228: } ! 229: ! 230: static Uint8 tmc_vcr_read0(void) { ! 231: return (tmc.vertical>>24); ! 232: } ! 233: static Uint8 tmc_vcr_read1(void) { ! 234: return (tmc.vertical>>16); ! 235: } ! 236: static Uint8 tmc_vcr_read2(void) { ! 237: return (tmc.vertical>>8); ! 238: } ! 239: static Uint8 tmc_vcr_read3(void) { ! 240: return tmc.vertical; ! 241: } ! 242: ! 243: static void tmc_vcr_write0(Uint8 val) { ! 244: tmc.vertical &= 0x00FFFFFF; ! 245: tmc.vertical |= (val&0xFF)<<24; ! 246: } ! 247: static void tmc_vcr_write1(Uint8 val) { ! 248: tmc.vertical &= 0xFF00FFFF; ! 249: tmc.vertical |= (val&0xFF)<<16; ! 250: } ! 251: static void tmc_vcr_write2(Uint8 val) { ! 252: tmc.vertical &= 0xFFFF00FF; ! 253: tmc.vertical |= (val&0xFF)<<8; ! 254: } ! 255: static void tmc_vcr_write3(Uint8 val) { ! 256: tmc.vertical &= 0xFFFFFF00; ! 257: tmc.vertical |= val&0xFF; ! 258: } ! 259: ! 260: ! 261: /* Read register functions */ ! 262: static Uint8 (*tmc_read_reg[36])(void) = { ! 263: tmc_scr1_read0, tmc_scr1_read1, tmc_scr1_read2, tmc_scr1_read3, ! 264: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 265: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 266: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 267: tmc_ctrl_read0, tmc_ctrl_read1, tmc_ctrl_read2, tmc_ctrl_read3, ! 268: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 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: }; ! 273: ! 274: static Uint8 (*tmc_read_vid_reg[16])(void) = { ! 275: tmc_vir_read0, tmc_void_read, tmc_void_read, tmc_void_read, ! 276: tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, tmc_unimpl_read, ! 277: tmc_hcr_read0, tmc_hcr_read1, tmc_hcr_read2, tmc_hcr_read3, ! 278: tmc_vcr_read0, tmc_vcr_read1, tmc_vcr_read2, tmc_vcr_read3 ! 279: }; ! 280: ! 281: /* Write register functions */ ! 282: static void (*tmc_write_reg[36])(Uint8) = { ! 283: tmc_ill_write, tmc_ill_write, tmc_ill_write, tmc_ill_write, ! 284: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 285: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 286: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 287: tmc_ctrl_write0, tmc_ctrl_write1, tmc_ctrl_write2, tmc_ctrl_write3, ! 288: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_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: }; ! 293: ! 294: static void (*tmc_write_vid_reg[16])(Uint8) = { ! 295: tmc_vir_write0, tmc_void_write, tmc_void_write, tmc_void_write, ! 296: tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, tmc_unimpl_write, ! 297: tmc_hcr_write0, tmc_hcr_write1, tmc_hcr_write2, tmc_hcr_write3, ! 298: tmc_vcr_write0, tmc_vcr_write1, tmc_vcr_write2, tmc_vcr_write3 ! 299: }; ! 300: ! 301: ! 302: Uint32 tmc_lget(uaecptr addr) { ! 303: Uint32 val = 0; ! 304: ! 305: if (addr%4) { ! 306: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 307: abort(); ! 308: } ! 309: ! 310: if (addr==0x02210000) { ! 311: Log_Printf(LOG_WARN, "[TMC] Nitro register lget from $%08X",addr); ! 312: if (ConfigureParams.System.nCpuFreq==40) { ! 313: val = tmc.nitro; ! 314: } else { ! 315: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!"); ! 316: M68000_BusError(addr, 1); ! 317: } ! 318: return val; ! 319: } ! 320: ! 321: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 322: return adb_lget(addr); ! 323: } ! 324: ! 325: Log_Printf(LOG_TMC_LEVEL, "[TMC] lget from %08X",addr); ! 326: ! 327: addr &= TMC_REGS_MASK; ! 328: ! 329: if (addr<36) { ! 330: val = tmc_read_reg[addr]()<<24; ! 331: val |= tmc_read_reg[addr+1]()<<16; ! 332: val |= tmc_read_reg[addr+2]()<<8; ! 333: val |= tmc_read_reg[addr+3](); ! 334: } else if (addr>=128 && addr<144) { ! 335: val = tmc_read_vid_reg[addr&0xF]()<<24; ! 336: val |= tmc_read_vid_reg[(addr+1)&0xF]()<<16; ! 337: val |= tmc_read_vid_reg[(addr+2)&0xF]()<<8; ! 338: val |= tmc_read_vid_reg[(addr+3)&0xF](); ! 339: } ! 340: ! 341: return val; ! 342: } ! 343: ! 344: Uint32 tmc_wget(uaecptr addr) { ! 345: Uint32 val = 0; ! 346: ! 347: if (addr%2) { ! 348: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 349: abort(); ! 350: } ! 351: ! 352: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 353: return adb_wget(addr); ! 354: } ! 355: ! 356: Log_Printf(LOG_TMC_LEVEL, "[TMC] wget from %08X",addr); ! 357: ! 358: addr &= TMC_REGS_MASK; ! 359: ! 360: if (addr<36) { ! 361: val = tmc_read_reg[addr]()<<8; ! 362: val |= tmc_read_reg[addr+1](); ! 363: } else if (addr>=128 && addr<144) { ! 364: val = tmc_read_vid_reg[addr&0xF]()<<8; ! 365: val |= tmc_read_vid_reg[(addr+1)&0xF](); ! 366: } ! 367: ! 368: return val; ! 369: } ! 370: ! 371: Uint32 tmc_bget(uaecptr addr) { ! 372: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 373: return adb_bget(addr); ! 374: } ! 375: ! 376: Log_Printf(LOG_TMC_LEVEL, "[TMC] bget from %08X",addr); ! 377: ! 378: addr &= TMC_REGS_MASK; ! 379: ! 380: if (addr<36) { ! 381: return tmc_read_reg[addr](); ! 382: } else if (addr>=128 && addr<144) { ! 383: return tmc_read_vid_reg[addr&0xF](); ! 384: } ! 385: ! 386: return 0; ! 387: } ! 388: ! 389: void tmc_lput(uaecptr addr, Uint32 l) { ! 390: if (addr%4) { ! 391: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 392: abort(); ! 393: } ! 394: ! 395: if (addr==0x02210000) { ! 396: Log_Printf(LOG_WARN, "[TMC] Nitro register lput %08X at $%08X",l,addr); ! 397: if (ConfigureParams.System.nCpuFreq==40) { ! 398: tmc.nitro = l&0x0000011F; ! 399: } else { ! 400: Log_Printf(LOG_WARN, "[TMC] No nitro --> bus error!"); ! 401: M68000_BusError(addr, 0); ! 402: } ! 403: return; ! 404: } ! 405: ! 406: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 407: adb_lput(addr, l); ! 408: return; ! 409: } ! 410: ! 411: Log_Printf(LOG_TMC_LEVEL, "[TMC] lput %08X to %08X",l,addr); ! 412: ! 413: addr &= TMC_REGS_MASK; ! 414: ! 415: if (addr<36) { ! 416: tmc_write_reg[addr](l>>24); ! 417: tmc_write_reg[addr+1](l>>16); ! 418: tmc_write_reg[addr+2](l>>8); ! 419: tmc_write_reg[addr+3](l); ! 420: } else if (addr>=128 && addr<144) { ! 421: tmc_write_vid_reg[addr&0xF](l>>24); ! 422: tmc_write_vid_reg[(addr+1)&0xF](l>>16); ! 423: tmc_write_vid_reg[(addr+2)&0xF](l>>8); ! 424: tmc_write_vid_reg[(addr+3)&0xF](l); ! 425: } ! 426: } ! 427: ! 428: void tmc_wput(uaecptr addr, Uint32 w) { ! 429: if (addr%2) { ! 430: Log_Printf(LOG_WARN, "[TMC] Unaligned access."); ! 431: abort(); ! 432: } ! 433: ! 434: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 435: adb_wput(addr, w); ! 436: return; ! 437: } ! 438: ! 439: Log_Printf(LOG_TMC_LEVEL, "[TMC] wput %04X to %08X",w,addr); ! 440: ! 441: addr &= TMC_REGS_MASK; ! 442: ! 443: if (addr<36) { ! 444: tmc_write_reg[addr](w>>8); ! 445: tmc_write_reg[addr+1](w); ! 446: } else if (addr>=128 && addr<144) { ! 447: tmc_write_vid_reg[addr&0xF](w>>8); ! 448: tmc_write_vid_reg[(addr+1)&0xF](w); ! 449: } ! 450: } ! 451: ! 452: void tmc_bput(uaecptr addr, Uint32 b) { ! 453: if ((addr&0xFFFFF00)==TMC_ADB_ADDR_MASK) { ! 454: adb_bput(addr, b); ! 455: return; ! 456: } ! 457: ! 458: Log_Printf(LOG_TMC_LEVEL, "[TMC] bput %02X to %08X",b,addr); ! 459: ! 460: addr &= TMC_REGS_MASK; ! 461: ! 462: if (addr<36) { ! 463: tmc_write_reg[addr](b); ! 464: } else if (addr>=128 && addr<144) { ! 465: tmc_write_vid_reg[addr&0xF](b); ! 466: } ! 467: } ! 468: ! 469: ! 470: /* TMC Reset */ ! 471: ! 472: void TMC_Reset(void) { ! 473: TurboSCR1_Reset(); ! 474: ! 475: tmc_video_reg_reset(); ! 476: tmc.control = 0x0D17038F; ! 477: tmc.nitro = 0x00000000; ! 478: ADB_Reset(); ! 479: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.