|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2022 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // HD647180 I/O アクセス ! 9: // ! 10: ! 11: #include "mpu64180.h" ! 12: #include "hd647180.h" ! 13: #include "pio.h" ! 14: #include "scheduler.h" ! 15: #include "xpbus.h" ! 16: ! 17: //#define ENABLE_SERIAL_LOG ! 18: //#define ENABLE_SSG_LOG ! 19: ! 20: uint32 ! 21: MPU64180Device::ReadIO(uint32 addr) ! 22: { ! 23: CYCLE(iowait); ! 24: ! 25: // 内蔵 I/O ! 26: if (io_address <= addr && addr < io_address + 0x80) { ! 27: return ReadInternalIO(addr - io_address); ! 28: } ! 29: ! 30: return ReadExternalIO(addr); ! 31: } ! 32: ! 33: uint32 ! 34: MPU64180Device::ReadInternalIO(uint32 offset) ! 35: { ! 36: uint32 data = -1; ! 37: ! 38: switch (offset) { ! 39: case 0x00: // IO_CNTLA0 ! 40: case 0x01: // IO_CNTLA1 ! 41: data = 0x10; ! 42: #if defined(ENABLE_SERIAL_LOG) ! 43: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)", ! 44: IOName(offset).c_str(), data); ! 45: #endif ! 46: return data; ! 47: case 0x02: // IO_CNTLB0 ! 48: case 0x03: // IO_CNTLB1 ! 49: break; ! 50: case 0x04: // IO_STAT0 ! 51: case 0x05: // IO_STAT1 ! 52: data = 0x02; ! 53: #if defined(ENABLE_SERIAL_LOG) ! 54: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)", ! 55: IOName(offset).c_str(), data); ! 56: #endif ! 57: return data; ! 58: case 0x06: // IO_TDR0 ! 59: case 0x07: // IO_TDR1 ! 60: case 0x08: // IO_TSR0 ! 61: case 0x09: // IO_TSR1 ! 62: case 0x0a: // IO_CNTR ! 63: case 0x0b: // IO_TRDR ! 64: break; ! 65: ! 66: case 0x0c: // IO_TMDR0L ! 67: data = ReadTMDRL(0); ! 68: break; ! 69: case 0x0d: // IO_TMDR0H ! 70: data = ReadTMDRH(0); ! 71: break; ! 72: case 0x0e: // IO_RLDR0L ! 73: data = PeekRLDRL(0); ! 74: break; ! 75: case 0x0f: // IO_RLDR0H ! 76: data = PeekRLDRH(0); ! 77: break; ! 78: case 0x10: // IO_TCR ! 79: data = ReadTCR(); ! 80: break; ! 81: case 0x14: // IO_TMDR1L ! 82: data = ReadTMDRL(1); ! 83: break; ! 84: case 0x15: // IO_TMDR1H ! 85: data = ReadTMDRH(1); ! 86: break; ! 87: case 0x16: // IO_RLDR1L ! 88: data = PeekRLDRH(0); ! 89: break; ! 90: case 0x17: // IO_RLDR1H ! 91: data = PeekRLDRH(1); ! 92: break; ! 93: case 0x18: // IO_FRC ! 94: data = PeekFRC(); ! 95: break; ! 96: ! 97: case 0x20: // IO_SAR0L ! 98: case 0x21: // IO_SAR0H ! 99: case 0x22: // IO_SAR0B ! 100: case 0x23: // IO_DAR0L ! 101: case 0x24: // IO_DAR0H ! 102: case 0x25: // IO_DAR0B ! 103: case 0x26: // IO_BCR0L ! 104: case 0x27: // IO_BCR0H ! 105: case 0x28: // IO_MAR1L ! 106: case 0x29: // IO_MAR1H ! 107: case 0x2a: // IO_MAR1B ! 108: case 0x2b: // IO_IAR1L ! 109: case 0x2c: // IO_IAR1H ! 110: case 0x2e: // IO_BCR1L ! 111: case 0x2f: // IO_BCR1H ! 112: case 0x30: // IO_DSTAT ! 113: case 0x31: // IO_DMODE ! 114: break; ! 115: case 0x32: // IO_DCNTL ! 116: data = PeekDCNTL(); ! 117: break; ! 118: ! 119: case 0x33: // IO_IL ! 120: data = PeekIL(); ! 121: break; ! 122: case 0x34: // IO_ITC ! 123: data = PeekITC(); ! 124: break; ! 125: case 0x36: // IO_RCR ! 126: data = PeekRCR(); ! 127: break; ! 128: ! 129: case 0x38: // IO_CBR ! 130: data = PeekCBR(); ! 131: break; ! 132: ! 133: case 0x39: // IO_BBR ! 134: data = PeekBBR(); ! 135: break; ! 136: ! 137: case 0x3a: // IO_CBAR ! 138: data = PeekCBAR(); ! 139: break; ! 140: ! 141: case 0x3e: // IO_OMCR ! 142: break; ! 143: case 0x3f: // IO_ICR ! 144: data = PeekICR(); ! 145: break; ! 146: ! 147: case 0x40: // IO_T2FRCL ! 148: case 0x41: // IO_T2FRCH ! 149: case 0x42: // IO_T2OCR1L ! 150: case 0x43: // IO_T2OCR1H ! 151: case 0x44: // IO_T2OCR2L ! 152: case 0x45: // IO_T2OCR2H ! 153: case 0x46: // IO_T2ICRL ! 154: case 0x47: // IO_T2ICRH ! 155: case 0x48: // IO_T2CSR1 ! 156: case 0x49: // IO_T2CSR2 ! 157: break; ! 158: ! 159: case 0x50: // IO_CCSR ! 160: break; ! 161: case 0x51: // IO_RMCR ! 162: data = PeekRMCR(); ! 163: break; ! 164: ! 165: case 0x53: // IO_DERA ! 166: break; ! 167: case 0x60: // IO_IODRA ! 168: data = 0xff; ! 169: #if defined(ENABLE_SERIAL_LOG) ! 170: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)", ! 171: IOName(offset).c_str(), data); ! 172: #endif ! 173: return data; ! 174: case 0x61: // IO_IODRB ! 175: case 0x62: // IO_IODRC ! 176: case 0x63: // IO_IODRD ! 177: case 0x64: // IO_IODRE ! 178: case 0x65: // IO_IODRF ! 179: case 0x66: // IO_IDRG ! 180: case 0x70: // IO_DDRA ! 181: case 0x71: // IO_DDRB ! 182: case 0x72: // IO_DDRC ! 183: case 0x73: // IO_DDRD ! 184: case 0x74: // IO_DDRE ! 185: case 0x75: // IO_DDRF ! 186: break; ! 187: ! 188: default: ! 189: break; ! 190: } ! 191: ! 192: // 表示して値を返す部分はだいたいほぼ共通なので。 ! 193: if ((int32)data < 0) { ! 194: // data が (32bitで) 負なら未実装ポート。 ! 195: data = 0xff; ! 196: putlog(0, "ReadInternalIO %s -> $%02x (NOT IMPLEMENTED)", ! 197: IOName(offset).c_str(), data); ! 198: } else { ! 199: putlog(2, "%s -> $%02x", IOName(offset).c_str(), data); ! 200: } ! 201: return data; ! 202: } ! 203: ! 204: uint32 ! 205: MPU64180Device::ReadExternalIO(uint32 addr) ! 206: { ! 207: uint32 data = -1; ! 208: ! 209: // LUNA の外部 I/O はアドレスの上位バイト不問 ! 210: switch (addr & 0xff) { ! 211: case 0x82: // SSG ! 212: case 0x83: // SSG ! 213: #if !defined(ENABLE_SSG_LOG) ! 214: data = 0xff; ! 215: #endif ! 216: break; ! 217: ! 218: case 0x90: // INT0 ネゲート ! 219: // 読み込みでも (というかアクセスがあっただけで) ネゲート。 ! 220: putlog(1, "%s Negate INT0", IOName(addr).c_str()); ! 221: NegateINT0(); ! 222: // 実際何が読めるかは不明だが。 ! 223: return 0xff; ! 224: ! 225: case 0xa0: // レベル5 割り込み要求 ! 226: case 0xb0: // レベル1 割り込み要求 ! 227: // 読み込みでも割り込み上げそうだがとりあえず未実装へ回しておく。 ! 228: break; ! 229: ! 230: default: ! 231: break; ! 232: } ! 233: ! 234: // 表示して値を返す部分はだいたいほぼ共通なので。 ! 235: if ((int32)data < 0) { ! 236: // data が (32bitで) 負なら未実装ポート。 ! 237: data = 0xff; ! 238: putlog(0, "ReadExternalIO %s -> $%02x (NOT IMPLEMENTED)", ! 239: IOName(addr).c_str(), data); ! 240: } else { ! 241: putlog(2, "%s -> $%02x", IOName(addr).c_str(), data); ! 242: } ! 243: return data; ! 244: } ! 245: ! 246: uint32 ! 247: MPU64180Device::ReadTMDRL(int ch) ! 248: { ! 249: auto& t = timer[ch]; ! 250: ! 251: // TDR 読み出しで割り込みフラグクリアの実績を解除 ! 252: t.tif &= ~0x02; ! 253: ChangeTimerInterrupt(); ! 254: ! 255: // L の読み出しで count を tmp にラッチ ! 256: t.tmpcount = t.count; ! 257: ! 258: // でラッチした L を読み出す ! 259: return t.tmpcount & 0xff; ! 260: } ! 261: ! 262: uint32 ! 263: MPU64180Device::ReadTMDRH(int ch) ! 264: { ! 265: auto& t = timer[ch]; ! 266: ! 267: // TDR 読み出しで割り込みフラグクリアの実績を解除 ! 268: t.tif &= ~0x02; ! 269: ChangeTimerInterrupt(); ! 270: ! 271: // L 読み出し時にラッチしたやつを読み出す。 ! 272: return t.tmpcount >> 8; ! 273: } ! 274: ! 275: uint32 ! 276: MPU64180Device::ReadTCR() ! 277: { ! 278: // TCR 読み出しで割り込みフラグクリアの実績を解除 ! 279: timer[0].tif &= ~0x01; ! 280: timer[1].tif &= ~0x01; ! 281: ChangeTimerInterrupt(); ! 282: ! 283: return PeekTCR(); ! 284: } ! 285: ! 286: uint32 ! 287: MPU64180Device::WriteIO(uint32 addr, uint32 data) ! 288: { ! 289: CYCLE(iowait); ! 290: ! 291: // 内蔵 I/O ! 292: if (io_address <= addr && addr < io_address + 0x80) { ! 293: return WriteInternalIO(addr - io_address, data); ! 294: } ! 295: ! 296: return WriteExternalIO(addr, data); ! 297: } ! 298: ! 299: uint32 ! 300: MPU64180Device::WriteInternalIO(uint32 offset, uint32 data) ! 301: { ! 302: switch (offset) { ! 303: case 0x00: // IO_CNTLA0 ! 304: case 0x01: // IO_CNTLA1 ! 305: #if defined(USE_XPSERIAL) ! 306: putlog(0, "%s <- $%02x (NOT IMPLEMENTED)", ! 307: IOName(offset).c_str(), data); ! 308: #endif ! 309: return 0; ! 310: case 0x02: // IO_CNTLB0 ! 311: case 0x03: // IO_CNTLB1 ! 312: case 0x04: // IO_STAT0 ! 313: case 0x05: // IO_STAT1 ! 314: case 0x06: // IO_TDR0 ! 315: case 0x07: // IO_TDR1 ! 316: case 0x08: // IO_TSR0 ! 317: case 0x09: // IO_TSR1 ! 318: case 0x0a: // IO_CNTR ! 319: case 0x0b: // IO_TRDR ! 320: break; ! 321: ! 322: case 0x0c: // IO_TMDR0L ! 323: return WriteTMDRL(0, data); ! 324: case 0x0d: // IO_TMDR0H ! 325: return WriteTMDRH(0, data); ! 326: case 0x0e: // IO_RLDR0L ! 327: return WriteRLDRL(0, data); ! 328: case 0x0f: // IO_RLDR0H ! 329: return WriteRLDRH(0, data); ! 330: case 0x10: // IO_TCR ! 331: return WriteTCR(data); ! 332: case 0x14: // IO_TMDR1L ! 333: return WriteTMDRL(1, data); ! 334: case 0x15: // IO_TMDR1H ! 335: return WriteTMDRH(1, data); ! 336: case 0x16: // IO_RLDR1L ! 337: return WriteRLDRL(1, data); ! 338: case 0x17: // IO_RLDR1H ! 339: return WriteRLDRH(1, data); ! 340: case 0x18: // IO_FRC ! 341: // 書き込みは出来るけど、してはいけないっぽい。 ! 342: // たぶん現在値が変わるだけだと思うけど未対応。 ! 343: break; ! 344: ! 345: case 0x20: // IO_SAR0L ! 346: case 0x21: // IO_SAR0H ! 347: case 0x22: // IO_SAR0B ! 348: case 0x23: // IO_DAR0L ! 349: case 0x24: // IO_DAR0H ! 350: case 0x25: // IO_DAR0B ! 351: case 0x26: // IO_BCR0L ! 352: case 0x27: // IO_BCR0H ! 353: case 0x28: // IO_MAR1L ! 354: case 0x29: // IO_MAR1H ! 355: case 0x2a: // IO_MAR1B ! 356: case 0x2b: // IO_IAR1L ! 357: case 0x2c: // IO_IAR1H ! 358: case 0x2e: // IO_BCR1L ! 359: case 0x2f: // IO_BCR1H ! 360: case 0x30: // IO_DSTAT ! 361: case 0x31: // IO_DMODE ! 362: break; ! 363: case 0x32: // IO_DCNTL ! 364: return WriteDCNTL(data); ! 365: break; ! 366: ! 367: case 0x33: // IO_IL ! 368: return WriteIL(data); ! 369: case 0x34: // IO_ITC ! 370: return WriteITC(data); ! 371: case 0x36: // IO_RCR ! 372: return WriteRCR(data); ! 373: ! 374: case 0x38: // IO_CBR ! 375: return WriteCBR(data); ! 376: case 0x39: // IO_BBR ! 377: return WriteBBR(data); ! 378: case 0x3a: // IO_CBAR ! 379: return WriteCBAR(data); ! 380: ! 381: case 0x3e: // IO_OMCR ! 382: break; ! 383: case 0x3f: // IO_ICR ! 384: return WriteICR(data); ! 385: ! 386: case 0x40: // IO_T2FRCL ! 387: case 0x41: // IO_T2FRCH ! 388: case 0x42: // IO_T2OCR1L ! 389: case 0x43: // IO_T2OCR1H ! 390: case 0x44: // IO_T2OCR2L ! 391: case 0x45: // IO_T2OCR2H ! 392: case 0x46: // IO_T2ICRL ! 393: case 0x47: // IO_T2ICRH ! 394: case 0x48: // IO_T2CSR1 ! 395: case 0x49: // IO_T2CSR2 ! 396: break; ! 397: ! 398: case 0x50: // IO_CCSR ! 399: break; ! 400: case 0x51: // IO_RMCR ! 401: return WriteRMCR(data); ! 402: ! 403: case 0x53: // IO_DERA ! 404: case 0x60: // IO_IODRA ! 405: case 0x61: // IO_IODRB ! 406: case 0x62: // IO_IODRC ! 407: case 0x63: // IO_IODRD ! 408: case 0x64: // IO_IODRE ! 409: case 0x65: // IO_IODRF ! 410: case 0x66: // IO_IDRG ! 411: case 0x70: // IO_DDRA ! 412: case 0x71: // IO_DDRB ! 413: case 0x72: // IO_DDRC ! 414: case 0x73: // IO_DDRD ! 415: case 0x74: // IO_DDRE ! 416: case 0x75: // IO_DDRF ! 417: break; ! 418: ! 419: default: ! 420: break; ! 421: } ! 422: ! 423: putlog(0, "WriteInternalIO %s <- $%02x (NOT IMPLEMENTED)", ! 424: IOName(offset).c_str(), data); ! 425: return 0; ! 426: } ! 427: ! 428: uint32 ! 429: MPU64180Device::WriteExternalIO(uint32 addr, uint32 data) ! 430: { ! 431: // LUNA の外部 I/O はアドレスの上位バイト不問 ! 432: switch (addr & 0xff) { ! 433: case 0x82: // SSG ! 434: case 0x83: // SSG ! 435: #if !defined(ENABLE_SSG_LOG) ! 436: return 0; ! 437: #endif ! 438: break; ! 439: ! 440: case 0x90: // INT0 ネゲート ! 441: putlog(1, "%s Negate INT0", IOName(addr).c_str()); ! 442: NegateINT0(); ! 443: return 0; ! 444: ! 445: case 0xa0: // レベル5 割り込み要求 ! 446: putlog(1, "%s Interrupt High", IOName(addr).c_str()); ! 447: pio0->InterruptXPHigh(); ! 448: return 0; ! 449: ! 450: case 0xb0: // レベル1 割り込み要求 ! 451: putlog(1, "%s Interrupt Low", IOName(addr).c_str()); ! 452: pio0->InterruptXPLow(); ! 453: return 0; ! 454: ! 455: default: ! 456: break; ! 457: } ! 458: ! 459: putlog(0, "WriteExternalIO %s <- $%02x (NOT IMPLEMENTED)", ! 460: IOName(addr).c_str(), data); ! 461: return 0; ! 462: } ! 463: ! 464: uint32 ! 465: MPU64180Device::WriteTMDRL(int ch, uint32 data) ! 466: { ! 467: auto& t = timer[ch]; ! 468: if (t.running) { ! 469: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる? ! 470: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)", ! 471: IOName(HD647180::IO_TMDRL(ch)).c_str(), data); ! 472: } else { ! 473: t.count = (t.count & 0xff00) | data; ! 474: putlog(1, "%s <- $%02x (TMDR%d = $%04x)", ! 475: IOName(HD647180::IO_TMDRL(ch)).c_str(), data, ch, t.count); ! 476: } ! 477: return 0; ! 478: } ! 479: ! 480: uint32 ! 481: MPU64180Device::WriteTMDRH(int ch, uint32 data) ! 482: { ! 483: auto& t = timer[ch]; ! 484: if (t.running) { ! 485: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる? ! 486: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)", ! 487: IOName(HD647180::IO_TMDRH(ch)).c_str(), data); ! 488: } else { ! 489: t.count = (data << 8) | (t.count & 0x00ff); ! 490: putlog(1, "%s <- $%02x (TMDR%d = $%04x)", ! 491: IOName(HD647180::IO_TMDRH(ch)).c_str(), data, ch, t.count); ! 492: } ! 493: return 0; ! 494: } ! 495: ! 496: uint32 ! 497: MPU64180Device::WriteRLDRL(int ch, uint32 data) ! 498: { ! 499: // 動作中にも変更可能 ! 500: auto& t = timer[ch]; ! 501: t.reload = (t.reload & 0xff00) | data; ! 502: putlog(1, "%s <- $%02x (RLDR%d = $%04x)", ! 503: IOName(HD647180::IO_RLDRL(ch)).c_str(), data, ch, t.reload); ! 504: return 0; ! 505: } ! 506: ! 507: uint32 ! 508: MPU64180Device::WriteRLDRH(int ch, uint32 data) ! 509: { ! 510: // 動作中にも変更可能 ! 511: auto& t = timer[ch]; ! 512: t.reload = (data << 8) | (t.reload & 0x00ff); ! 513: putlog(1, "%s <- $%02x (RLDR%d = $%04x)", ! 514: IOName(HD647180::IO_RLDRH(ch)).c_str(), data, ch, t.reload); ! 515: return 0; ! 516: } ! 517: ! 518: uint32 ! 519: MPU64180Device::WriteTCR(uint32 data) ! 520: { ! 521: std::array<bool, 2> new_tde; ! 522: std::string msg; ! 523: ! 524: timer[1].intr_enable = (data & 0x20); ! 525: timer[0].intr_enable = (data & 0x10); ! 526: // intr_enable を変更したので ChangeTimerInterrupt() を呼ぶのは ! 527: // 最後に行っている。 ! 528: ! 529: timer_toc = (data >> 2) & 3; ! 530: ! 531: new_tde[1] = (data & 0x02); ! 532: new_tde[0] = (data & 0x01); ! 533: msg = string_format("TIE1=%d TIE0=%d TOC=$%d", ! 534: (timer[1].intr_enable ? 1 : 0), ! 535: (timer[0].intr_enable ? 1 : 0), ! 536: timer_toc); ! 537: ! 538: for (int ch = 0; ch < timer.size(); ch++) { ! 539: auto& t = timer[ch]; ! 540: if (t.running == false && new_tde[ch] == true) { ! 541: // カウントダウン開始 ! 542: t.count = t.reload; ! 543: t.running = true; ! 544: MakeActiveTimer(); ! 545: msg += string_format(" Timer%d=Start", ch); ! 546: EnableTimer(); ! 547: } else if (t.running == true && new_tde[ch] == false) { ! 548: // カウントダウン停止 ! 549: ! 550: // ここではタイマーの状態を停止にするだけでよい。 ! 551: // タイマーイベントの中で running が落ちてたら停止してくれる。 ! 552: t.running = false; ! 553: MakeActiveTimer(); ! 554: msg += string_format(" Timer%d=Stop", ch); ! 555: } else { ! 556: // 変化なし ! 557: } ! 558: } ! 559: ! 560: putlog(1, "%s <- $%02x: %s", ! 561: IOName(HD647180::IO_TCR).c_str(), data, msg.c_str()); ! 562: ! 563: // ログの順序的に書き込みログの後で変更する ! 564: ChangeTimerInterrupt(); ! 565: ! 566: return 0; ! 567: } ! 568: ! 569: uint32 ! 570: MPU64180Device::WriteDCNTL(uint32 data) ! 571: { ! 572: // メモリウェイト 0,1,2,3 ! 573: memwait = (data >> 6) & 3; ! 574: ! 575: // I/O ウェイトは 0,2,3,4 ! 576: iowait = (data >> 4) & 3; ! 577: if (iowait != 0) ! 578: iowait++; ! 579: ! 580: // 下位4ビット分は未実装 ! 581: dcntl = data & 0x0f; ! 582: return 0; ! 583: } ! 584: ! 585: uint32 ! 586: MPU64180Device::WriteIL(uint32 data) ! 587: { ! 588: // 書き込み時にマスクする ! 589: intvec_low = data & 0xe0; ! 590: return 0; ! 591: } ! 592: ! 593: uint32 ! 594: MPU64180Device::WriteITC(uint32 data) ! 595: { ! 596: itc_trap = (data & 0x80); ! 597: // UFO は ReadOnly ! 598: itc_ite2 = (data & 0x04); ! 599: itc_ite1 = (data & 0x02); ! 600: itc_ite0 = (data & 0x01); ! 601: ! 602: // XXX 割り込み変わったら何かする? ! 603: ! 604: return 0; ! 605: } ! 606: ! 607: uint32 ! 608: MPU64180Device::WriteRCR(uint32 data) ! 609: { ! 610: // 未実装 ! 611: rcr = data | 0x3c; ! 612: ! 613: if ((rcr & 0x80)) { ! 614: // Refresh Enable は未実装。無効にするなら表示不要。 ! 615: putlog(0, "%s <- $%02x: Refresh Enable (NOT IMPLEMENTED)", ! 616: IOName(HD647180::IO_RCR).c_str(), data); ! 617: } else { ! 618: // ログレベル 1 なら全部表示 ! 619: putlog(1, "%s <- $%02x (NOT IMPLEMENTED)", ! 620: IOName(HD647180::IO_RCR).c_str(), data); ! 621: } ! 622: return 0; ! 623: } ! 624: ! 625: uint32 ! 626: MPU64180Device::WriteCBR(uint32 data) ! 627: { ! 628: int lv; ! 629: uint32 new_base = data << 12; ! 630: if (commbase != new_base) { ! 631: lv = 1; ! 632: commbase = new_base; ! 633: } else { ! 634: lv = 2; ! 635: } ! 636: putlog(lv, "%s <- $%02x: Common Base Addr=$%05x", ! 637: IOName(HD647180::IO_CBR).c_str(), data, commbase); ! 638: return 0; ! 639: } ! 640: ! 641: uint32 ! 642: MPU64180Device::WriteBBR(uint32 data) ! 643: { ! 644: int lv; ! 645: uint32 new_base = data << 12; ! 646: if (bankbase != new_base) { ! 647: lv = 1; ! 648: bankbase = new_base; ! 649: } else { ! 650: lv = 2; ! 651: } ! 652: putlog(lv, "%s <- $%02x: Bank Base Addr=$%05x", ! 653: IOName(HD647180::IO_BBR).c_str(), data, bankbase); ! 654: return 0; ! 655: } ! 656: ! 657: uint32 ! 658: MPU64180Device::WriteCBAR(uint32 data) ! 659: { ! 660: int lv; ! 661: uint32 new_comm = (data & 0xf0) << 8; ! 662: uint32 new_bank = (data & 0x0f) << 12; ! 663: if (commarea != new_comm || bankarea != new_bank) { ! 664: lv = 1; ! 665: commarea = new_comm; ! 666: bankarea = new_bank; ! 667: } else { ! 668: lv = 2; ! 669: } ! 670: putlog(lv, "%s <- $%02x: CommArea=$%04x BankArea=$%04x", ! 671: IOName(HD647180::IO_CBAR).c_str(), data, commarea, bankarea); ! 672: return 0; ! 673: } ! 674: ! 675: uint32 ! 676: MPU64180Device::WriteICR(uint32 data) ! 677: { ! 678: io_address = data & 0x80; ! 679: putlog(1, "%s <- $%02x: I/O Address=$%02x", ! 680: IOName(HD647180::IO_ICR).c_str(), data, io_address); ! 681: ! 682: // IOSTP は未実装 ! 683: if ((data & 0x20) != 0) { ! 684: putlog(0, "%s IOSTP (NOT IMPLEMENTED)"); ! 685: } ! 686: return 0; ! 687: } ! 688: ! 689: uint32 ! 690: MPU64180Device::WriteRMCR(uint32 data) ! 691: { ! 692: xpbus->SetRMCR(data); ! 693: putlog(1, "%s <- $%02x: RAM address=$%05x", ! 694: IOName(HD647180::IO_RMCR).c_str(), data, xpbus->GetXPRAMAddr()); ! 695: return 0; ! 696: } ! 697: ! 698: uint32 ! 699: MPU64180Device::PeekIO(uint32 addr) ! 700: { ! 701: // 内蔵 I/O ! 702: if (io_address <= addr && addr < io_address + 0x80) { ! 703: return PeekInternalIO(addr - io_address); ! 704: } ! 705: ! 706: return PeekExternalIO(addr); ! 707: } ! 708: ! 709: uint32 ! 710: MPU64180Device::PeekInternalIO(uint32 offset) ! 711: { ! 712: switch (offset) { ! 713: case 0x00: // IO_CNTLA0 ! 714: case 0x01: // IO_CNTLA1 ! 715: case 0x02: // IO_CNTLB0 ! 716: case 0x03: // IO_CNTLB1 ! 717: case 0x04: // IO_STAT0 ! 718: case 0x05: // IO_STAT1 ! 719: case 0x06: // IO_TDR0 ! 720: case 0x07: // IO_TDR1 ! 721: case 0x08: // IO_TSR0 ! 722: case 0x09: // IO_TSR1 ! 723: case 0x0a: // IO_CNTR ! 724: case 0x0b: // IO_TRDR ! 725: break; ! 726: ! 727: case 0x0c: // IO_TMDR0L ! 728: return PeekTMDRL(0); ! 729: case 0x0d: // IO_TMDR0H ! 730: return PeekTMDRH(0); ! 731: case 0x0e: // IO_RLDR0L ! 732: return PeekRLDRL(0); ! 733: case 0x0f: // IO_RLDR0H ! 734: return PeekRLDRH(0); ! 735: case 0x10: // IO_TCR ! 736: return PeekTCR(); ! 737: case 0x14: // IO_TMDR1L ! 738: return PeekTMDRL(1); ! 739: case 0x15: // IO_TMDR1H ! 740: return PeekTMDRH(1); ! 741: case 0x16: // IO_RLDR1L ! 742: return PeekRLDRL(1); ! 743: case 0x17: // IO_RLDR1H ! 744: return PeekRLDRH(1); ! 745: case 0x18: // IO_FRC ! 746: return PeekFRC(); ! 747: ! 748: case 0x20: // IO_SAR0L ! 749: case 0x21: // IO_SAR0H ! 750: case 0x22: // IO_SAR0B ! 751: case 0x23: // IO_DAR0L ! 752: case 0x24: // IO_DAR0H ! 753: case 0x25: // IO_DAR0B ! 754: case 0x26: // IO_BCR0L ! 755: case 0x27: // IO_BCR0H ! 756: case 0x28: // IO_MAR1L ! 757: case 0x29: // IO_MAR1H ! 758: case 0x2a: // IO_MAR1B ! 759: case 0x2b: // IO_IAR1L ! 760: case 0x2c: // IO_IAR1H ! 761: case 0x2e: // IO_BCR1L ! 762: case 0x2f: // IO_BCR1H ! 763: case 0x30: // IO_DSTAT ! 764: case 0x31: // IO_DMODE ! 765: break; ! 766: case 0x32: // IO_DCNTL ! 767: return PeekDCNTL(); ! 768: ! 769: case 0x33: // IO_IL ! 770: return PeekIL(); ! 771: case 0x34: // IO_ITC ! 772: return PeekITC(); ! 773: case 0x36: // IO_RCR ! 774: return PeekRCR(); ! 775: ! 776: case 0x38: // IO_CBR ! 777: return PeekCBR(); ! 778: case 0x39: // IO_BBR ! 779: return PeekBBR(); ! 780: case 0x3a: // IO_CBAR ! 781: return PeekCBAR(); ! 782: ! 783: case 0x3e: // IO_OMCR ! 784: break; ! 785: case 0x3f: // IO_ICR ! 786: return PeekICR(); ! 787: ! 788: case 0x40: // IO_T2FRCL ! 789: case 0x41: // IO_T2FRCH ! 790: case 0x42: // IO_T2OCR1L ! 791: case 0x43: // IO_T2OCR1H ! 792: case 0x44: // IO_T2OCR2L ! 793: case 0x45: // IO_T2OCR2H ! 794: case 0x46: // IO_T2ICRL ! 795: case 0x47: // IO_T2ICRH ! 796: case 0x48: // IO_T2CSR1 ! 797: case 0x49: // IO_T2CSR2 ! 798: break; ! 799: ! 800: case 0x50: // IO_CCSR ! 801: break; ! 802: case 0x51: // IO_RMCR ! 803: return xpbus->GetRMCR(); ! 804: ! 805: case 0x53: // IO_DERA ! 806: case 0x60: // IO_IODRA ! 807: case 0x61: // IO_IODRB ! 808: case 0x62: // IO_IODRC ! 809: case 0x63: // IO_IODRD ! 810: case 0x64: // IO_IODRE ! 811: case 0x65: // IO_IODRF ! 812: case 0x66: // IO_IDRG ! 813: case 0x70: // IO_DDRA ! 814: case 0x71: // IO_DDRB ! 815: case 0x72: // IO_DDRC ! 816: case 0x73: // IO_DDRD ! 817: case 0x74: // IO_DDRE ! 818: case 0x75: // IO_DDRF ! 819: break; ! 820: ! 821: default: ! 822: break; ! 823: } ! 824: return 0xff; ! 825: } ! 826: ! 827: uint32 ! 828: MPU64180Device::PeekExternalIO(uint32 addr) ! 829: { ! 830: // LUNA の外部 I/O はアドレスの上位バイト不問 ! 831: switch (addr & 0xff) { ! 832: case 0x82: // SSG ! 833: case 0x83: // SSG ! 834: break; ! 835: ! 836: case 0x90: // INT0 ネゲート ! 837: break; ! 838: ! 839: case 0xa0: // レベル5 割り込み要求 ! 840: case 0xb0: // レベル1 割り込み要求 ! 841: break; ! 842: ! 843: default: ! 844: break; ! 845: } ! 846: return 0xff; ! 847: } ! 848: ! 849: uint32 ! 850: MPU64180Device::PeekTMDRL(int ch) const ! 851: { ! 852: return timer[ch].count & 0xff; ! 853: } ! 854: ! 855: uint32 ! 856: MPU64180Device::PeekTMDRH(int ch) const ! 857: { ! 858: return timer[ch].count >> 8; ! 859: } ! 860: ! 861: uint32 ! 862: MPU64180Device::PeekRLDRL(int ch) const ! 863: { ! 864: return timer[ch].reload & 0xff; ! 865: } ! 866: ! 867: uint32 ! 868: MPU64180Device::PeekRLDRH(int ch) const ! 869: { ! 870: return timer[ch].reload >> 8; ! 871: } ! 872: ! 873: uint32 ! 874: MPU64180Device::PeekTCR() const ! 875: { ! 876: uint32 data = (timer_toc << 2); ! 877: ! 878: if (timer[1].tif != 0) ! 879: data |= 0x80; ! 880: if (timer[0].tif != 0) ! 881: data |= 0x40; ! 882: if (timer[1].intr_enable) ! 883: data |= 0x20; ! 884: if (timer[0].intr_enable) ! 885: data |= 0x10; ! 886: if (timer[1].running) ! 887: data |= 0x02; ! 888: if (timer[0].running) ! 889: data |= 0x01; ! 890: ! 891: return data; ! 892: } ! 893: ! 894: uint32 ! 895: MPU64180Device::PeekFRC() const ! 896: { ! 897: if (opmode == OpMode::Reset) { ! 898: return 0xff; ! 899: } else { ! 900: // Free Running Counter はリセット時に 0FFH で、 ! 901: // そこから 10φ ごとに1ずつ減っていく。 ! 902: // そのため、リセット時の時刻を覚えておき、経過時間から計算する。 ! 903: uint64 time = scheduler->GetVirtTime() - timer_epoch; ! 904: return 0xff - (uint8)(time / (clock_nsec * 10)); ! 905: } ! 906: } ! 907: ! 908: uint32 ! 909: MPU64180Device::PeekDCNTL() const ! 910: { ! 911: uint32 data; ! 912: ! 913: data = (memwait << 6); ! 914: if (iowait != 0) { ! 915: data |= (iowait - 1) << 4; ! 916: } ! 917: data |= dcntl; ! 918: ! 919: return data; ! 920: } ! 921: ! 922: uint32 ! 923: MPU64180Device::PeekIL() const ! 924: { ! 925: return intvec_low; ! 926: } ! 927: ! 928: uint32 ! 929: MPU64180Device::PeekITC() const ! 930: { ! 931: uint32 data = 0x38; ! 932: if (itc_trap) ! 933: data |= 0x80; ! 934: if (itc_ufo) ! 935: data |= 0x40; ! 936: if (itc_ite2) ! 937: data |= 0x04; ! 938: if (itc_ite1) ! 939: data |= 0x02; ! 940: if (itc_ite0) ! 941: data |= 0x01; ! 942: return data; ! 943: } ! 944: ! 945: uint32 ! 946: MPU64180Device::PeekRCR() const ! 947: { ! 948: return rcr; ! 949: } ! 950: ! 951: uint32 ! 952: MPU64180Device::PeekCBR() const ! 953: { ! 954: return (commbase >> 12) & 0xff; ! 955: } ! 956: ! 957: uint32 ! 958: MPU64180Device::PeekBBR() const ! 959: { ! 960: return (bankbase >> 12) & 0xff; ! 961: } ! 962: ! 963: uint32 ! 964: MPU64180Device::PeekCBAR() const ! 965: { ! 966: uint32 data; ! 967: ! 968: data = (commarea >> 8) & 0xf0; ! 969: data |= (bankarea >> 12) & 0x0f; ! 970: ! 971: return data; ! 972: } ! 973: ! 974: uint32 ! 975: MPU64180Device::PeekICR() const ! 976: { ! 977: // IOSTP は未実装 ! 978: return io_address | 0x5f; ! 979: } ! 980: ! 981: uint32 ! 982: MPU64180Device::PeekRMCR() const ! 983: { ! 984: return xpbus->GetRMCR(); ! 985: } ! 986: ! 987: // アドレス (とあれば名前) を返す。 ! 988: /*static*/ std::string ! 989: MPU64180Device::IOName(uint32 addr) ! 990: { ! 991: std::string buf; ! 992: ! 993: if (addr < 0x100) { ! 994: buf = string_format("%02XH", addr); ! 995: } else { ! 996: buf = string_format("%04XH", addr); ! 997: } ! 998: ! 999: if (addr < ionames.size() && ionames[addr] != NULL) { ! 1000: buf += '('; ! 1001: buf += ionames[addr]; ! 1002: buf += ')'; ! 1003: } ! 1004: return buf; ! 1005: } ! 1006: ! 1007: /*static*/ std::vector<const char *> ! 1008: MPU64180Device::ionames = { ! 1009: "CNTLA0", // 00 ! 1010: "CNTLA1", // 01 ! 1011: "CNTLB0", // 02 ! 1012: "CNTLB1", // 03 ! 1013: "STAT0", // 04 ! 1014: "STAT1", // 05 ! 1015: "TDR0", // 06 ! 1016: "TDR1", // 07 ! 1017: "TSR0", // 08 ! 1018: "TSR1", // 09 ! 1019: "CNTR", // 0a ! 1020: "TRDR", // 0b ! 1021: "TMDR0L", // 0c ! 1022: "TMDR0H", // 0d ! 1023: "RLDR0L", // 0e ! 1024: "RLDR0H", // 0f ! 1025: ! 1026: "TCR", // 10 ! 1027: NULL, // 11 ! 1028: NULL, // 12 ! 1029: NULL, // 13 ! 1030: "TMDR1L", // 14 ! 1031: "TMDR1H", // 15 ! 1032: "RLDR1L", // 16 ! 1033: "RLDR1H", // 17 ! 1034: "FRFC", // 18 ! 1035: NULL, // 19 ! 1036: NULL, // 1a ! 1037: NULL, // 1b ! 1038: NULL, // 1c ! 1039: NULL, // 1d ! 1040: NULL, // 1e ! 1041: NULL, // 1f ! 1042: ! 1043: "SAR0L", // 20 ! 1044: "SAR0H", // 21 ! 1045: "SAR0B", // 22 ! 1046: "DAR0L", // 23 ! 1047: "DAR0H", // 24 ! 1048: "DAR0B", // 25 ! 1049: "BCR0L", // 26 ! 1050: "BCR0H", // 27 ! 1051: "MAR1L", // 28 ! 1052: "MAR1H", // 29 ! 1053: "MAR1B", // 2a ! 1054: "IAR1L", // 2b ! 1055: "IAR1H", // 2c ! 1056: NULL, // 2d ! 1057: "BCR1L", // 2e ! 1058: "BCR1H", // 2f ! 1059: ! 1060: "DSTAT", // 30 ! 1061: "DMODE", // 31 ! 1062: "DCNTL", // 32 ! 1063: "IL", // 33 ! 1064: "ITC", // 34 ! 1065: NULL, // 35 ! 1066: "RCR", // 36 ! 1067: NULL, // 37 ! 1068: "CBR", // 38 ! 1069: "BBR", // 39 ! 1070: "CBAR", // 3a ! 1071: NULL, // 3b ! 1072: NULL, // 3c ! 1073: NULL, // 3d ! 1074: "OMCR", // 3e ! 1075: "ICR", // 3f ! 1076: ! 1077: "T2FRCL", // 40 ! 1078: "T2FRCH", // 41 ! 1079: "T2OCR1L", // 42 ! 1080: "T2OCR1H", // 43 ! 1081: "T2OCR2L", // 44 ! 1082: "T2OCR2H", // 45 ! 1083: "T2ICRL", // 46 ! 1084: "T2ICRH", // 47 ! 1085: "T2CSR1", // 48 ! 1086: "T2CSR2", // 49 ! 1087: NULL, // 4a ! 1088: NULL, // 4b ! 1089: NULL, // 4c ! 1090: NULL, // 4d ! 1091: NULL, // 4e ! 1092: NULL, // 4f ! 1093: ! 1094: "CCSR", // 50 ! 1095: "RMCR", // 51 ! 1096: NULL, // 52 ! 1097: "DERA", // 53 ! 1098: NULL, // 54 ! 1099: NULL, // 55 ! 1100: NULL, // 56 ! 1101: NULL, // 57 ! 1102: NULL, // 58 ! 1103: NULL, // 59 ! 1104: NULL, // 5a ! 1105: NULL, // 5b ! 1106: NULL, // 5c ! 1107: NULL, // 5d ! 1108: NULL, // 5e ! 1109: NULL, // 5f ! 1110: ! 1111: "IODRA", // 60 ! 1112: "IODRB", // 61 ! 1113: "IODRC", // 62 ! 1114: "IODRD", // 63 ! 1115: "IODRE", // 64 ! 1116: "IODRF", // 65 ! 1117: "IDRG", // 66 ! 1118: NULL, // 67 ! 1119: NULL, // 68 ! 1120: NULL, // 69 ! 1121: NULL, // 6a ! 1122: NULL, // 6b ! 1123: NULL, // 6c ! 1124: NULL, // 6d ! 1125: NULL, // 6e ! 1126: NULL, // 6f ! 1127: ! 1128: "DDRA", // 70 ! 1129: "DDRB", // 71 ! 1130: "DDRC", // 72 ! 1131: "DDRD", // 73 ! 1132: "DDRE", // 74 ! 1133: "DDRF", // 75 ! 1134: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.