|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.12 root 7: //
8: // MFP (MC68901)
9: //
10:
1.1 root 11: #include "mfp.h"
1.1.1.7 root 12: #include "interrupt.h"
13: #include "keyboard.h"
1.1.1.17 root 14: #include "monitor.h"
1.1.1.12 root 15: #include "mpu.h"
16: #include "scheduler.h"
1.1.1.9 root 17: #include "x68kkbd.h"
1.1 root 18:
1.1.1.15 root 19: // InsideOut p.135
20: static const busdata wait = busdata::Wait(24 * 40_nsec);
21:
1.1 root 22: // コンストラクタ
23: MFPDevice::MFPDevice()
1.1.1.14 root 24: : inherited(OBJ_MFP)
1.1 root 25: {
1.1.1.17 root 26: monitor = gMonitorManager->Regist(ID_MONITOR_MFP, this);
27: monitor->func = ToMonitorCallback(&MFPDevice::MonitorUpdate);
28: monitor->SetSize(77, 26);
1.1 root 29: }
30:
31: // デストラクタ
32: MFPDevice::~MFPDevice()
33: {
1.1.1.14 root 34: }
35:
36: // 初期化
37: bool
38: MFPDevice::Init()
39: {
40: interrupt = GetInterruptDevice();
41: keyboard = dynamic_cast<X68030Keyboard *>(GetKeyboard());
42:
1.1.1.16 root 43: for (int ch = 0; ch < event.size(); ch++) {
44: event[ch].dev = this;
45: event[ch].func = ToEventCallback(&MFPDevice::TimerCallback);
46: event[ch].code = ch;
47: event[ch].SetName(string_format("MFP Timer-%c", ch + 'A'));
48: scheduler->RegistEvent(event[ch]);
49: }
50:
51: // キーボード周りは x68kkbd.cpp のコメント参照
52: key_event.func = ToEventCallback(&MFPDevice::KeyCallback);
53: key_event.time = 3750_usec;
54: key_event.SetName("MFP USART");
55: scheduler->RegistEvent(key_event);
56:
1.1.1.14 root 57: return true;
1.1 root 58: }
59:
1.1.1.12 root 60: // リセット
1.1.1.6 root 61: void
1.1.1.12 root 62: MFPDevice::ResetHard(bool poweron)
1.1.1.6 root 63: {
1.1.1.15 root 64: // 3.3 RESET OPERATION には
1.1.1.6 root 65: // All internal registers are cleared expect the TxDR, UDR, and TSR.
1.1.1.15 root 66: // と書いてあるが、6.2.1 には TxDR はリセット時に $00 と書いてある。
67: // 内部カウンタは影響を受けずに next_tdr だけリセットされるという
68: // 意味だろうか。
1.1.1.6 root 69: mfp.aer = 0;
70: mfp.ddr = 0;
71: mfp.ier.w = 0;
72: mfp.ipr.w = 0;
73: mfp.isr.w = 0;
74: mfp.imr.w = 0;
1.1.1.16 root 75: for (int i = 0; i < countof(mfp.timer); i++) {
76: mfp.timer[i].tcr = 0;
77: mfp.timer[i].next_tdr = 256;
1.1.1.6 root 78: }
79: mfp.scr = 0;
80: mfp.ucr = 0;
81: mfp.rsr = 0;
82: // XXX TSR は変化しないがたぶんバッファはクリアされるので BE は立つ
83: // ということかな。
84: mfp.tsr = MFP::TSR_BE;
1.1 root 85:
1.1.1.6 root 86: // All timers are stopped.
1.1.1.11 root 87: for (auto& ev : event) {
1.1.1.14 root 88: scheduler->StopEvent(ev);
1.1 root 89: }
1.1.1.14 root 90: scheduler->StopEvent(key_event);
1.1 root 91:
1.1.1.6 root 92: // USART RX and TX are disabled.
93: // SO line is placed in HighZ.
94: // The interrupt channels are disabled, and
95: // any pending interrupts are cleared.
96: // GPIO lines are placed in HighZ.
97: // timer outputs are driven low.
98: // External signals are nagated.
99: // VR is initialized to $00 (not $0f).
1.1.1.7 root 100: mfp.vr_vec = 0;
101: mfp.vr_s = 0;
1.1.1.13 root 102:
103: // CIRQ | FMIRQ | EXPON | ALARM にしておく
104: mfp.gpip = 0x6b;
1.1.1.15 root 105:
1.1.1.18! root 106: // Human68k モードなら、10msec ごとに Timer-C 割り込みを上げる。
! 107: // 時間計測用。
! 108: if (gMainApp.human_mode) {
! 109: WritePort(MFP::VR, 0x40);
! 110: WritePort(MFP::TCDR, 200);
! 111: WritePort(MFP::TCDCR, 0x70);
! 112: WritePort(MFP::IMRB, 0x20);
! 113: WritePort(MFP::IERB, 0x20);
! 114: }
! 115:
1.1.1.15 root 116: ChangeInterrupt();
1.1.1.3 root 117: }
118:
1.1.1.15 root 119: busdata
1.1.1.16 root 120: MFPDevice::ReadPort(uint32 offset)
1.1 root 121: {
1.1.1.15 root 122: busdata data;
1.1.1.6 root 123:
1.1.1.8 root 124: switch (offset) {
1.1 root 125: case MFP::GPIP:
126: data = mfp.gpip;
127: break;
128: case MFP::AER:
129: data = mfp.aer;
130: break;
131: case MFP::DDR:
132: data = mfp.ddr;
133: break;
134: case MFP::IERA:
135: data = mfp.ier.a;
136: break;
137: case MFP::IERB:
138: data = mfp.ier.b;
139: break;
140: case MFP::IPRA:
141: data = mfp.ipr.a;
142: break;
143: case MFP::IPRB:
144: data = mfp.ipr.b;
145: break;
146: case MFP::ISRA:
147: data = mfp.isr.a;
148: break;
149: case MFP::ISRB:
150: data = mfp.isr.b;
151: break;
152: case MFP::IMRA:
153: data = mfp.imr.a;
154: break;
155: case MFP::IMRB:
156: data = mfp.imr.b;
157: break;
158: case MFP::VR:
1.1.1.7 root 159: data = mfp.GetVR();
1.1 root 160: break;
161: case MFP::TACR:
1.1.1.16 root 162: data = mfp.timer[0].tcr;
1.1 root 163: break;
164: case MFP::TBCR:
1.1.1.16 root 165: data = mfp.timer[1].tcr;
1.1 root 166: break;
167: case MFP::TCDCR:
1.1.1.16 root 168: data = mfp.GetTCDCR();
1.1 root 169: break;
170: case MFP::TADR:
171: data = GetTDR(0);
172: break;
173: case MFP::TBDR:
174: data = GetTDR(1);
175: break;
176: case MFP::TCDR:
177: data = GetTDR(2);
178: break;
179: case MFP::TDDR:
180: data = GetTDR(3);
181: break;
182: case MFP::SCR:
183: data = mfp.scr;
184: break;
185: case MFP::UCR:
186: data = mfp.ucr;
187: break;
188: case MFP::RSR:
189: data = mfp.rsr;
190: break;
191: case MFP::TSR:
192: data = mfp.tsr;
193: break;
194: case MFP::UDR:
1.1.1.9 root 195: // UDR からデータを読み出したら Buffer Full をクリア
1.1 root 196: data = mfp.udr;
1.1.1.9 root 197: ClearBF();
1.1 root 198: break;
1.1.1.4 root 199: default:
200: data = 0xff;
201: break;
1.1 root 202: }
1.1.1.15 root 203:
1.1.1.16 root 204: if (__predict_false(loglevel >= 3)) {
205: if (offset == MFP::TCDR) {
206: putlog(4, "%s -> $%02x", regname[offset], data.Data());
207: } else if (offset < MFP::RegMax) {
208: putlogn("%s -> $%02x", regname[offset], data.Data());
209: } else {
210: putlogn("$%06x -> $%02x", mpu->GetPaddr(), data.Data());
211: }
212: }
1.1.1.15 root 213: data |= wait;
1.1.1.16 root 214: data |= BusData::Size1;
1.1 root 215: return data;
216: }
217:
1.1.1.15 root 218: busdata
1.1.1.16 root 219: MFPDevice::WritePort(uint32 offset, uint32 data)
1.1 root 220: {
1.1.1.8 root 221: switch (offset) {
1.1 root 222: case MFP::GPIP:
1.1.1.13 root 223: putlog(0, "Write GPIP <- $%02x (NOT IMPLEMENTED)", data);
1.1 root 224: mfp.gpip = data;
225: break;
226: case MFP::AER:
1.1.1.16 root 227: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 228: mfp.aer = data;
229: break;
230: case MFP::DDR:
231: if (data != 0) {
1.1.1.13 root 232: putlog(0, "Write DDR <- $%02x (NOT IMPLEMENTED)", data);
1.1 root 233: }
234: mfp.ddr = data;
235: break;
236: case MFP::IERA:
1.1.1.16 root 237: putlog(2, "%s <- $%02x", regname[offset], data);
1.1.1.15 root 238: SetIER(mfp.ier.a, mfp.ipr.a, data);
1.1 root 239: break;
240: case MFP::IERB:
1.1.1.16 root 241: putlog(2, "%s <- $%02x", regname[offset], data);
1.1.1.15 root 242: SetIER(mfp.ier.b, mfp.ipr.b, data);
1.1 root 243: break;
244: case MFP::IPRA:
1.1.1.16 root 245: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 246: mfp.ipr.a = data;
1.1.1.7 root 247: ChangeInterrupt();
1.1 root 248: break;
249: case MFP::IPRB:
1.1.1.16 root 250: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 251: mfp.ipr.b = data;
1.1.1.7 root 252: ChangeInterrupt();
1.1 root 253: break;
254: case MFP::ISRA:
1.1.1.16 root 255: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 256: mfp.isr.a = data;
257: break;
258: case MFP::ISRB:
1.1.1.16 root 259: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 260: mfp.isr.b = data;
261: break;
262: case MFP::IMRA:
1.1.1.16 root 263: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 264: mfp.imr.a = data;
1.1.1.7 root 265: ChangeInterrupt();
1.1 root 266: break;
267: case MFP::IMRB:
1.1.1.16 root 268: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 269: mfp.imr.b = data;
1.1.1.7 root 270: ChangeInterrupt();
1.1 root 271: break;
272: case MFP::VR:
1.1.1.7 root 273: mfp.vr_vec = data & 0xf0;
274: mfp.vr_s = data & 0x08;
1.1.1.16 root 275: putlog(2, "%s <- $%02x", regname[offset], mfp.GetVR());
1.1 root 276: break;
277: case MFP::TACR:
1.1.1.16 root 278: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 279: SetTCR(0, data);
280: break;
281: case MFP::TBCR:
1.1.1.16 root 282: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 283: SetTCR(1, data);
284: break;
285: case MFP::TCDCR:
1.1.1.16 root 286: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 287: SetTCR(2, data >> 4);
288: SetTCR(3, data & 7);
289: break;
290: case MFP::TADR:
1.1.1.16 root 291: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 292: SetTDR(0, data);
293: break;
294: case MFP::TBDR:
1.1.1.16 root 295: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 296: SetTDR(1, data);
297: break;
298: case MFP::TCDR:
1.1.1.16 root 299: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 300: SetTDR(2, data);
301: break;
302: case MFP::TDDR:
1.1.1.16 root 303: putlog(2, "%s <- $%02x", regname[offset], data);
1.1 root 304: SetTDR(3, data);
305: break;
306: case MFP::SCR:
1.1.1.13 root 307: putlog(0, "SCR <- $%02x (NOT IMPLEMENTED)", data);
1.1 root 308: mfp.scr = data;
309: break;
310: case MFP::UCR:
1.1.1.16 root 311: putlog(2, "%s <- $%02x", regname[offset], data);
1.1.1.4 root 312: SetUCR(data);
1.1 root 313: break;
314: case MFP::RSR:
1.1.1.16 root 315: putlog(2, "%s <- $%02x", regname[offset], data);
1.1.1.4 root 316: SetRSR(data);
1.1 root 317: break;
318: case MFP::TSR:
1.1.1.13 root 319: if ((data & 0x0e)) {
320: // SO 端子関係の B, H, L ビットは未実装
321: putlog(0, "TSR <- $%02x (B,H,L bit NOT IMPLEMENTED)", data);
322: }
1.1 root 323: mfp.tsr = (mfp.tsr & 0xf0) | (data & 0x0f);
324: break;
325: case MFP::UDR:
1.1.1.16 root 326: if (__predict_false(loglevel >= 2)) {
327: if (data == 0x40 || data == 0x41) {
328: // MSCTRL だけ頻度が高いのでログレベルを上げておく
329: putlog(3, "%s <- $%02x", regname[offset], data);
330: } else {
331: putlogn("%s <- $%02x", regname[offset], data);
332: }
1.1.1.4 root 333: }
334: SetUDR(data);
335: break;
336: default:
1.1 root 337: break;
338: }
1.1.1.15 root 339:
1.1.1.16 root 340: busdata r = wait;
341: r |= BusData::Size1;
342: return r;
1.1 root 343: }
344:
1.1.1.15 root 345: busdata
1.1.1.16 root 346: MFPDevice::PeekPort(uint32 offset)
1.1 root 347: {
348: uint8 data;
349:
1.1.1.8 root 350: switch (offset) {
1.1 root 351: case MFP::GPIP:
352: data = mfp.gpip;
353: break;
354: case MFP::AER:
355: data = mfp.aer;
356: break;
357: case MFP::DDR:
358: data = mfp.ddr;
359: break;
360: case MFP::IERA:
361: data = mfp.ier.a;
362: break;
363: case MFP::IERB:
364: data = mfp.ier.b;
365: break;
366: case MFP::IPRA:
367: data = mfp.ipr.a;
368: break;
369: case MFP::IPRB:
370: data = mfp.ipr.b;
371: break;
372: case MFP::ISRA:
373: data = mfp.isr.a;
374: break;
375: case MFP::ISRB:
376: data = mfp.isr.b;
377: break;
378: case MFP::IMRA:
379: data = mfp.imr.a;
380: break;
381: case MFP::IMRB:
382: data = mfp.imr.b;
383: break;
384: case MFP::VR:
1.1.1.7 root 385: data = mfp.GetVR();
1.1 root 386: break;
387: case MFP::TACR:
1.1.1.16 root 388: data = mfp.timer[0].tcr;
1.1 root 389: break;
390: case MFP::TBCR:
1.1.1.16 root 391: data = mfp.timer[1].tcr;
1.1 root 392: break;
393: case MFP::TCDCR:
1.1.1.16 root 394: data = mfp.GetTCDCR();
1.1 root 395: break;
396: case MFP::TADR:
397: data = GetTDR(0);
398: break;
399: case MFP::TBDR:
400: data = GetTDR(1);
401: break;
402: case MFP::TCDR:
403: data = GetTDR(2);
404: break;
405: case MFP::TDDR:
406: data = GetTDR(3);
407: break;
408: case MFP::SCR:
409: data = mfp.scr;
410: break;
411: case MFP::UCR:
412: data = mfp.ucr;
413: break;
414: case MFP::RSR:
415: data = mfp.rsr;
416: break;
417: case MFP::TSR:
418: data = mfp.tsr;
419: break;
420: case MFP::UDR:
421: data = mfp.udr;
422: break;
1.1.1.4 root 423: default:
424: data = 0xff;
1.1 root 425: }
426: return data;
427: }
428:
1.1.1.16 root 429: bool
430: MFPDevice::PokePort(uint32 offset, uint32 data)
431: {
432: return false;
433: }
434:
1.1.1.5 root 435: void
1.1.1.10 root 436: MFPDevice::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 437: {
1.1.1.15 root 438: MFP mfp_;
439: std::array<uint8, 4> tdr_;
1.1 root 440: int x;
441: int y;
442:
1.1.1.15 root 443: // ローカルにコピー。
444: memcpy(&mfp_, &mfp, sizeof(mfp));
445: for (int ch = 0; ch < tdr_.size(); ch++) {
446: tdr_[ch] = GetTDR(ch);
447: }
448:
1.1.1.10 root 449: screen.Clear();
1.1 root 450:
451: // 0 1 2 3 4 5 6
1.1.1.7 root 452: // 01234567890123456789012345678901234567890123456789012345678901234567890
453: // $e88001(GPIP):$00 $e88007(IERA):$00 $e88019(TACR):$00 $e88027
1.1.1.13 root 454: // IER IMR IPR ISR Mode TDR Cnt
455: // An:MPSC TxEmpty Enable Mask Pend Serv Timer-A Delay(50us) 255 255
1.1 root 456:
1.1.1.7 root 457: #define A(x) (baseaddr + (x * 2) + 1)
458:
459: // レジスタ生値
460: // 1列目(GPIP 関連と VR)
461: x = 0;
462: y = 0;
1.1.1.15 root 463: screen.Print(x, y++, "$%06x(GPIP):$%02x", A(MFP::GPIP), mfp_.gpip);
464: screen.Print(x, y++, "$%06x(AER): $%02x", A(MFP::AER), mfp_.aer);
465: screen.Print(x, y++, "$%06x(DDR): $%02x", A(MFP::DDR), mfp_.ddr);
466: screen.Print(x, y++, "$%06x(VR): $%02x", A(MFP::VR), mfp_.GetVR());
1.1.1.7 root 467: // 2列目(割り込み関連)
468: x = 20;
469: y = 0;
1.1.1.15 root 470: screen.Print(x, y++, "$%06x(IERA):$%02x", A(MFP::IERA), mfp_.ier.a);
471: screen.Print(x, y++, "$%06x(IERB):$%02x", A(MFP::IERB), mfp_.ier.b);
472: screen.Print(x, y++, "$%06x(IPRA):$%02x", A(MFP::IPRA), mfp_.ipr.a);
473: screen.Print(x, y++, "$%06x(IPRB):$%02x", A(MFP::IPRB), mfp_.ipr.b);
474: screen.Print(x, y++, "$%06x(ISRA):$%02x", A(MFP::ISRA), mfp_.isr.a);
475: screen.Print(x, y++, "$%06x(ISRB):$%02x", A(MFP::ISRB), mfp_.isr.b);
476: screen.Print(x, y++, "$%06x(IMRA):$%02x", A(MFP::IMRA), mfp_.imr.a);
477: screen.Print(x, y++, "$%06x(IMRB):$%02x", A(MFP::IMRB), mfp_.imr.b);
1.1.1.7 root 478: // 3列目(タイマー関連)
479: x = 40;
480: y = 0;
1.1.1.16 root 481: screen.Print(x, y++, "$%06x(TACR): $%02x", A(MFP::TACR), mfp_.timer[0].tcr);
482: screen.Print(x, y++, "$%06x(TBCR): $%02x", A(MFP::TBCR), mfp_.timer[1].tcr);
483: screen.Print(x, y++, "$%06x(TCDCR):$%02x", A(MFP::TCDCR), mfp_.GetTCDCR());
1.1.1.15 root 484: screen.Print(x, y++, "$%06x(TADR): $%02x", A(MFP::TADR), tdr_[0]);
485: screen.Print(x, y++, "$%06x(TBDR): $%02x", A(MFP::TBDR), tdr_[1]);
486: screen.Print(x, y++, "$%06x(TCDR): $%02x", A(MFP::TCDR), tdr_[2]);
487: screen.Print(x, y++, "$%06x(TDDR): $%02x", A(MFP::TDDR), tdr_[3]);
1.1.1.7 root 488: // 4列目(USART 関連)
489: x = 61;
490: y = 0;
1.1.1.15 root 491: screen.Print(x, y++, "$%06x(SCR):$%02x", A(MFP::SCR), mfp_.scr);
492: screen.Print(x, y++, "$%06x(UCR):$%02x", A(MFP::UCR), mfp_.ucr);
493: screen.Print(x, y++, "$%06x(RSR):$%02x", A(MFP::RSR), mfp_.rsr);
494: screen.Print(x, y++, "$%06x(TSR):$%02x", A(MFP::TSR), mfp_.tsr);
1.1.1.10 root 495: screen.Print(x, y, "$%06x(UDR):", A(MFP::UDR));
1.1.1.15 root 496: if ((int16)mfp_.udr >= 0) {
497: screen.Print(x + 13, y, "$%02x", mfp_.udr);
1.1.1.7 root 498: } else {
1.1.1.10 root 499: screen.Print(x + 13, y, "---");
1.1.1.7 root 500: }
501:
1.1 root 502: // 割り込み関連
1.1.1.7 root 503: y = 9;
1.1.1.10 root 504: screen.Print(0, y++, "<Interrupt> %-6s %-4s %-4s %-4s",
1.1.1.7 root 505: "IER", "IMR", "IPR", "ISR");
1.1 root 506: for (int i = 15; i >= 0; i--, y++) {
507: uint16 mask = (1 << i);
1.1.1.16 root 508: screen.Print(0, y, "%c%u:%-12s %-6s %-4s %-4s %-4s",
1.1 root 509: i >= 8 ? 'A' : 'B',
510: (i % 8),
511: intrname[i],
1.1.1.15 root 512: (mfp_.ier.w & mask) ? "Enable" : "",
513: (mfp_.imr.w & mask) ? "" : "Mask", // %0 でマスクする
514: (mfp_.ipr.w & mask) ? "Pend" : "",
515: (mfp_.isr.w & mask) ? "Serv" : "");
1.1 root 516: }
517:
518: // タイマー関連
1.1.1.13 root 519: x = 40;
1.1.1.7 root 520: y = 9;
1.1.1.15 root 521: screen.Print(x, y++, "<Timer> Mode TDR Next");
1.1 root 522: for (int ch = 0; ch < 4; ch++) {
1.1.1.10 root 523: screen.Print(x, y, "Timer-%c", ch + 'A');
1.1.1.16 root 524: uint8 tcr = mfp_.timer[ch].tcr;
525: if (tcr == 0) {
1.1.1.10 root 526: screen.Print(x + 8, y, "Stopped");
1.1.1.16 root 527: } else if (tcr == 8) {
1.1.1.10 root 528: screen.Print(x + 8, y, "Event");
1.1.1.16 root 529: } else if (tcr > 8) {
530: screen.Print(x + 8, y, "Pulse(%s)", prescale_str[tcr - 8]);
1.1 root 531: } else {
1.1.1.16 root 532: screen.Print(x + 8, y, "Delay(%s)", prescale_str[tcr]);
1.1 root 533: }
534:
1.1.1.16 root 535: screen.Print(x + 20, y, "%3u", tdr_[ch]);
536: screen.Print(x + 25, y, "%3u", mfp_.timer[ch].next_tdr & 0xff);
1.1.1.7 root 537: y++;
1.1 root 538: }
539:
540: // GPIP 関連
1.1.1.13 root 541: x = 40;
1.1.1.7 root 542: y = 9 + 8;
1.1.1.10 root 543: screen.Puts(x, y++, "<GPIP> GPIP AER DDR");
1.1 root 544: for (int i = 7; i >= 0; i--, y++) {
545: uint mask = (1 << i);
1.1.1.16 root 546: screen.Print(x, y, "b%u %-6s %u %u %s", i, gpipname[i],
1.1.1.15 root 547: (mfp_.gpip & mask) ? 1 : 0,
548: (mfp_.aer & mask) ? 1 : 0,
549: (mfp_.ddr & mask) ? "OUT" : "IN");
1.1 root 550: }
551: }
552:
553: /*static*/ const char *
554: MFPDevice::intrname[] = {
555: "RTC Alarm",
556: "EXPON",
557: "POW SW",
558: "FM IRQ",
559: "Timer-D",
560: "Timer-C",
561: "V-Disp",
562: "---",
563: "Timer-B",
564: "MPSC TxErr",
565: "MPSC TxEmpty",
566: "MPSC RxErr",
567: "MPSC RxFull",
568: "Timer-A",
569: "CRTC IRQ",
570: "H-Sync",
571: };
572:
573: /*static*/ const char *
574: MFPDevice::gpipname[] = {
575: "ALARM",
576: "EXPON",
577: "POW SW",
578: "FMIRQ",
579: "V-Disp",
580: "------",
581: "CIRQ",
582: "H-Sync",
583: };
584:
585: // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す
1.1.1.16 root 586: /*static*/ const uint
1.1 root 587: MFPDevice::prescale_ns[8] = {
588: 0,
589: 1000, // /4
590: 2500, // /10
591: 4000, // /16
592: 12500, // /50
593: 16000, // /64
594: 25000, // /100
595: 50000, // /200
596: };
597:
598: /*static*/ const char *
599: MFPDevice::prescale_str[8] = {
600: "",
601: "1us",
602: "2.5us",
603: "4us",
604: "12.5us",
605: "16us",
606: "25us",
607: "50us",
608: };
609:
1.1.1.7 root 610: // タイマーのチャンネルから MFP 割り込みチャンネル番号に変換する
1.1.1.16 root 611: /*static*/ const uint
1.1.1.4 root 612: MFPDevice::timer_vector[4] = {
613: MFP::INTR_TIMER_A,
614: MFP::INTR_TIMER_B,
615: MFP::INTR_TIMER_C,
616: MFP::INTR_TIMER_D,
617: };
1.1 root 618:
1.1.1.15 root 619: // IER[AB] に data をセットする
620: void
621: MFPDevice::SetIER(uint8& ier, uint8& ipr, uint32 data)
622: {
623: // clr は、data によって %1 -> %0 に変化するビットだけを立てたもの。
624: uint8 clr = ier & (ier ^ data);
625:
626: // IER を下げたところは IPR も下げる。(紙資料 p4-4)
627: ipr &= ~clr;
628:
629: // どちらにしても新しい IER によって信号線の状態は変える。
630: ier = data;
631: ChangeInterrupt();
632: }
633:
1.1 root 634: // TxCR をセットする
635: void
636: MFPDevice::SetTCR(int ch, uint32 data)
637: {
638: uint32 prev;
639:
1.1.1.16 root 640: prev = mfp.timer[ch].tcr;
1.1 root 641: data &= 0x0f;
642:
1.1.1.16 root 643: mfp.timer[ch].tcr = data;
1.1.1.7 root 644: if (data == 0) {
645: if (prev == 0) {
646: // 0 -> 0 なら何も起きない
647: return;
648: } else if (prev < 8) {
649: // タイマー停止
1.1.1.13 root 650: putlog(1, "Timer-%c Stop", ch + 'A');
1.1.1.7 root 651:
652: // ここで TDR を確定させる。
653: // タイマー動作中の TDR の参照はイベント終了時刻から現在値を逆算
654: // していたが、イベントを停止すると求められなくなるので、イベント
655: // 停止前に求めておく。
656: uint64 period = prescale_ns[prev];
1.1.1.14 root 657: uint64 now = scheduler->GetVirtTime();
1.1.1.16 root 658: mfp.timer[ch].tdr = ((event[ch].vtime - now) + period - 1) / period;
1.1.1.7 root 659:
660: // でイベント停止
1.1.1.14 root 661: scheduler->StopEvent(event[ch]);
1.1.1.7 root 662: return;
663: } else if (prev == 8) {
664: // イベントカウントモードから停止しても何も起きないはず
665: } else {
666: // パルス幅測定モード (未実装)
667: }
1.1 root 668: return;
1.1.1.7 root 669:
670: } else if (data < 8) {
671: // タイマー開始
672:
1.1.1.15 root 673: // TDR は触らずイベントを開始。
1.1.1.16 root 674: uint64 period = prescale_ns[mfp.timer[ch].tcr];
675: event[ch].time = period * mfp.timer[ch].tdr;
1.1.1.14 root 676: scheduler->RestartEvent(event[ch]);
1.1.1.7 root 677:
1.1.1.13 root 678: putlog(1, "Timer-%c Start Delay mode(%u x %u.%uusec)",
1.1.1.7 root 679: ch + 'A',
1.1.1.16 root 680: mfp.timer[ch].tdr,
1.1.1.7 root 681: (uint)period / 1000,
682: (uint)(period / 100) % 10);
683: return;
684:
685: } else if (data == 8) {
1.1 root 686: // イベントカウントモード
687:
688: // TDR をロードする
1.1.1.16 root 689: mfp.timer[ch].next_tdr = mfp.timer[ch].tdr;
1.1.1.13 root 690: putlog(1, "Timer-%c Event count mode", ch + 'A');
1.1 root 691: return;
692:
693: } else {
1.1.1.13 root 694: putlog(0, "T%cCR Pulse-Width Measurement Mode $%02x (NOT IMPLEMENTED)",
1.1.1.7 root 695: ch + 'A', data);
696: return;
1.1 root 697: }
698: }
699:
700: // TxDR の読み出し
1.1.1.7 root 701: // (副作用はないので Peek 系からも呼び出してよい)
1.1 root 702: uint8
1.1.1.3 root 703: MFPDevice::GetTDR(int ch) const
1.1 root 704: {
1.1.1.16 root 705: uint8 tcr = mfp.timer[ch].tcr;
1.1 root 706:
1.1.1.7 root 707: if (tcr == 0) {
708: // 停止中なら tdr に現在値が保持されている
1.1.1.16 root 709: return mfp.timer[ch].tdr & 0xff;
1.1 root 710:
1.1.1.7 root 711: } else if (tcr < 8) {
712: // ディレイモード動作中なら現在値は保持していないので、
713: // プリスケーラと終了時刻から算出。
714:
715: uint64 period = prescale_ns[tcr];
1.1.1.14 root 716: uint64 now = scheduler->GetVirtTime();
1.1.1.15 root 717: uint8 data = ((event[ch].vtime - now) + period - 1) / period;
718: return data;
1.1 root 719:
1.1.1.7 root 720: } else {
721: // イベントモード、パルス幅測定モードは未対応
1.1.1.16 root 722: return mfp.timer[ch].tdr & 0xff;
1.1 root 723:
1.1.1.7 root 724: }
1.1 root 725: }
726:
727: // TxDR への書き込み
728: void
729: MFPDevice::SetTDR(int ch, uint32 data)
730: {
1.1.1.16 root 731: uint8& tcr = mfp.timer[ch].tcr;
1.1 root 732:
1.1.1.15 root 733: if (data == 0) {
734: data = 256;
735: }
1.1.1.16 root 736: mfp.timer[ch].next_tdr = data;
1.1.1.15 root 737:
1.1.1.7 root 738: if (tcr == 0) {
1.1.1.15 root 739: // 停止中の書き込みはメインカウンタも更新。
1.1.1.16 root 740: mfp.timer[ch].tdr = data;
1.1.1.7 root 741:
742: } else if (tcr < 8) {
1.1.1.15 root 743: // ディレイモード動作中の書き込みは
744: // メインカウンタは影響を受けない。
1.1 root 745:
1.1.1.7 root 746: } else {
747: // イベントモード、パルス幅測定モードは未対応
1.1.1.13 root 748: putlog(0, "Write T%cDR $%02x during unsupported mode (NOT IMPLEMENTED)",
1.1.1.16 root 749: ch + 'A', mfp.timer[ch].next_tdr);
1.1 root 750: }
751: }
752:
753: // イベントコールバック
754: void
1.1.1.6 root 755: MFPDevice::TimerCallback(Event& ev)
1.1 root 756: {
1.1.1.6 root 757: int& ch = ev.code;
1.1 root 758:
1.1.1.7 root 759: // TDR がゼロになったところで呼ばれるので、TDR をリロードする
1.1.1.16 root 760: mfp.timer[ch].tdr = mfp.timer[ch].next_tdr;
1.1 root 761:
1.1.1.7 root 762: // 割り込みを上げる
763: SetInterrupt(timer_vector[ch]);
764:
765: // 次のイベントをセット
766: // XXX 1回のイベントで複数のタイムアウトパルスを跨ぐ状況は考慮してない
767:
768: // period が1メインパルス期間
769: // time が1タイムアウトパルス期間
1.1.1.16 root 770: uint64 period = prescale_ns[mfp.timer[ch].tcr];
771: ev.time = period * mfp.timer[ch].tdr;
1.1.1.14 root 772: scheduler->RestartEvent(ev);
1.1.1.12 root 773: }
774:
775: // HSync 入力
776: void
777: MFPDevice::SetHSync(bool hsync)
778: {
779: SetGPIP(MFP::GPIP_HSYNC, hsync);
1.1 root 780: }
781:
782: // VDisp 入力
783: void
784: MFPDevice::SetVDisp(bool vdisp)
785: {
786: // TAI への入力はイベントカウントモードの時のみ
1.1.1.16 root 787: if (mfp.timer[0].tcr == 8) {
1.1 root 788: // AER が示す方向と同じエッジ方向の時
789: bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP));
790: if (aer == vdisp) {
791: // カウンタを減算
1.1.1.16 root 792: mfp.timer[0].tdr--;
793: if (mfp.timer[0].tdr == 0) {
1.1 root 794: // 0 になったらリロード
1.1.1.16 root 795: mfp.timer[0].tdr = mfp.timer[0].next_tdr;
1.1 root 796:
1.1.1.7 root 797: SetInterrupt(MFP::INTR_TIMER_A);
1.1 root 798: }
799: }
800: }
801:
802: // GPIP への入力
803: SetGPIP(MFP::GPIP_VDISP, vdisp);
804: }
805:
1.1.1.13 root 806: // 電源ボタン状態入力 (PowerDevice から呼ばれる)
807: void
808: MFPDevice::SetPowSW(bool powsw)
809: {
810: SetGPIP(MFP::GPIP_POWSW, powsw);
811: }
812:
813: // ALARM 信号入力 (RTC の ALARM_OUT 出力端子)
814: void
815: MFPDevice::SetAlarmOut(bool alarm)
816: {
817: SetGPIP(MFP::GPIP_ALARM, alarm);
818: }
819:
1.1 root 820: // GPIP への入力。
821: // num はビット番号(0..7)。
822: void
823: MFPDevice::SetGPIP(int num, bool val)
824: {
825: bool aer = (mfp.aer & (1 << num));
826: bool old = (mfp.gpip & (1 << num));
827:
828: // 立ち上がりか立ち下がりで割り込みを上げる (AER による)
829: // AER OLD VAL Interrupt
830: // 0 0 0 0
831: // 0 0 1 0
832: // 0 1 0 1
833: // 0 1 1 0
834: // 1 0 0 0
835: // 1 0 1 1
836: // 1 1 0 0
837: // 1 1 1 0
1.1.1.3 root 838: if ((old != val) && (aer == val)) {
1.1.1.13 root 839: // ここで割り込みを上げる
840: // XXX GPIP ビット番号と INTR の対応どうなってんの
841: int intr;
842: if (num < 4) {
843: intr = num;
844: } else if (num < 6) {
845: intr = num + 2;
846: } else {
847: intr = num - MFP::GPIP_CIRQ + MFP::INTR_CRTC_IRQ;
848: }
849: SetInterrupt(intr);
1.1 root 850: }
851:
852: if (val) {
853: mfp.gpip |= (1 << num);
854: } else {
855: mfp.gpip &= ~(1 << num);
856: }
857: }
1.1.1.4 root 858:
859: // UCR への書き込み
860: void
861: MFPDevice::SetUCR(uint32 data)
862: {
863: mfp.ucr = data;
864:
865: if ((mfp.ucr & MFP::UCR_CLK) == 0) {
1.1.1.13 root 866: putlog(0, "UCR CLK=0 (NOT IMPLEMENTED)");
1.1.1.4 root 867: }
868: if (((mfp.ucr & MFP::UCR_WL) >> 5) != 0) {
1.1.1.16 root 869: putlog(0, "UCR WL=%u (NOT IMPLEMENTED)", (mfp.ucr >> 5) & 3);
1.1.1.4 root 870: }
871: if (((mfp.ucr & MFP::UCR_ST) >> 3) != 1) {
1.1.1.16 root 872: putlog(0, "UCR ST=%u (NOT IMPLEMENTED)", (mfp.ucr >> 3) & 3);
1.1.1.4 root 873: }
874: }
875:
876: // RSR への書き込み
877: void
878: MFPDevice::SetRSR(uint32 data)
879: {
880: uint32 old = mfp.rsr;
881:
882: mfp.rsr = data;
883:
884: if ((old & MFP::RSR_RE) == 0 && (mfp.rsr & MFP::RSR_RE)) {
885: // RE 0 -> 1
886: }
887: if ((old & MFP::RSR_RE) && (mfp.rsr & MFP::RSR_RE) == 0) {
888: // RE 1 -> 0
1.1.1.9 root 889: // 上位4ビットのステータスを %0 に
890: mfp.rsr &= ~(MFP::RSR_OE | MFP::RSR_PE | MFP::RSR_FE);
891: ClearBF();
1.1.1.4 root 892: }
893: }
894:
1.1.1.9 root 895: // RSR::BF (Buffer Full) をセットする
896: void
897: MFPDevice::SetBF()
898: {
899: mfp.rsr |= MFP::RSR_BF;
900: }
901:
902: // RSR::BF (Buffer Full) をクリアする
903: void
904: MFPDevice::ClearBF()
905: {
906: mfp.rsr &= ~MFP::RSR_BF;
907:
908: // バッファが空いたのでキーボードに次の転送を催促。
909: // 実際のハードウェアでは、キーボードが本体 MFP が Ready になるのを待って
910: // いるが、それに相当。
911: // システムポートの KEYCTRL はキーボード側で処理している。
1.1.1.16 root 912: if (RxIsReady()) {
913: keyboard->Ready();
914: }
1.1.1.9 root 915: }
916:
1.1.1.4 root 917: // UDR への書き込み
918: void
919: MFPDevice::SetUDR(uint32 data)
920: {
921: if ((mfp.tsr & MFP::TSR_TE)) {
1.1.1.14 root 922: keyboard->Command(data);
1.1.1.4 root 923: }
924: }
925:
1.1.1.9 root 926: // __
927: // RR 線の状態を返す。アサートなら true。
928: bool
929: MFPDevice::IsRR() const
1.1.1.4 root 930: {
1.1.1.9 root 931: // __
932: // 実際の RR 信号線は、BF が立っていて、PE | FE がクリアされている場合に
933: // アサートされる。ただしエミュレータでは Parity Error も Frame Error も
934: // 起きないので、この2ビットは無視する。
935: return ((mfp.rsr & MFP::RSR_BF) != 0);
1.1.1.4 root 936: }
937:
1.1.1.9 root 938: // キーボードからの受信が可能なら true を返す。
1.1.1.4 root 939: bool
1.1.1.9 root 940: MFPDevice::RxIsReady() const
1.1.1.4 root 941: {
1.1.1.9 root 942: // __
943: // RR は本来 MFP から CPU/DMAC など上位に対しての Ready で、
944: // UDR にデータが用意できたので引き取ってほしいの意。
945: // X680x0 ではこれを CPU/DMAC (上位) 向けではなく、下位のキーボードからの
946: // フロー制御に流用しており、
947: // 上位への(本来の)「UDR にデータが用意できた」(IsRR() = true) は、
948: // キーボードに対しては「UDR にデータがあるので送信禁止」、
949: // 上位への(本来の)「UDR にデータが用意できていない」(IsRR() = false) は、
950: // キーボードに対しては「UDR は空いているので送信してよい」と
951: // ここで意味が論理反転することに注意。
952: //
953: // また、システムポートの KEYCTRL は X680x0Keyboard 側で処理しているので
954: // こちらでは不要。
955: //
956: // UDR が空いていてキーボードからデータが送られてきている間は RR は Ready
957: // だが、そもそもキーボードは送出作業中で、新たな送信はできないはずなので
958: // この場合、つまり key_event の動作中も false (送信不可) にする。
959:
960: return !IsRR() && !key_event.IsRunning();
1.1.1.4 root 961: }
962:
963: // キーボードからデータを受信
964: void
965: MFPDevice::Rx(uint32 data)
966: {
1.1.1.9 root 967: // ここは受信したビットをシフトレジスタへ入れ始めたところに相当する
968: // ので、まだ Buffer Full は立てない。
1.1.1.4 root 969:
970: key_event.code = data;
1.1.1.14 root 971: scheduler->RestartEvent(key_event);
1.1.1.4 root 972: }
973:
974: // キーボードからのデータが受信し終わった頃に呼ばれるイベント。
975: void
1.1.1.6 root 976: MFPDevice::KeyCallback(Event& ev)
1.1.1.4 root 977: {
1.1.1.9 root 978: // UDR にデータを置いて Buffer Full をセット
1.1.1.6 root 979: mfp.udr = ev.code;
1.1.1.9 root 980: SetBF();
981:
982: // Manual 7-5 7.2.1 Receiver Interrupt Channels より
983: // | 割り込みは1文字受信ごとに1回しか発生しませんが、2つの専用割り込み
984: // | チャネルにより、正常な受信状態と異常な受信状態に別々のベクター番号を
985: // | 割り当てることができます。受信したワードにエラーがあり、エラー割り込み
986: // | チャネルが有効な場合は、エラーチャネルのみに割り込みが発生します。
987: // | しかし、エラーチャネルが無効の場合、エラー状態の割り込みは、
988: // | バッファフル状態の割り込みと一緒にバッファフル割り込みチャネルに
989: // | 生成されます。どのエラー条件で割り込みが発生したかを判断するためには、
990: // | 常にRSRを読み出す必要があります。
991: // XXX: まだエラー状態は実装されていない、なおエラーは起きないので
992: // メモだけのままかも知れない。
1.1.1.4 root 993:
1.1.1.7 root 994: SetInterrupt(MFP::INTR_RXFULL);
995: }
996:
997: // 必要なら割り込みを上げる。
998: // ch は MFP 内の割り込みチャンネル番号。MFP::INTR_*
999: void
1000: MFPDevice::SetInterrupt(uint ch)
1001: {
1002: assertmsg(ch < 16, "ch=%u", ch);
1003: __assume(ch < 16);
1004:
1005: uint b = (1U << ch);
1006:
1007: // IER で割り込みが無効なら何もしない
1008: if ((mfp.ier.w & b) == 0) {
1009: return;
1.1.1.4 root 1010: }
1.1.1.7 root 1011:
1012: // IPR にペンディングを立てる
1013: mfp.ipr.w |= b;
1014:
1015: // 割り込み信号線の状態を変える
1016: ChangeInterrupt();
1017: }
1018:
1019: // 割り込み信号線の状態を変える
1020: void
1021: MFPDevice::ChangeInterrupt()
1022: {
1023: // ペンディングの割り込みがあればアサートされる、
1024: // IPR をクリアするか IMR をクリアすると /IRQ はネゲートされる。
1025: bool irq = ((mfp.ipr.w & mfp.imr.w) != 0);
1.1.1.14 root 1026: interrupt->ChangeINT(this, irq);
1.1.1.7 root 1027: }
1028:
1029: // 割り込みアクノリッジ
1.1.1.15 root 1030: busdata
1.1.1.7 root 1031: MFPDevice::InterruptAcknowledge()
1032: {
1.1.1.15 root 1033: busdata data;
1034:
1035: // IPR が誰も立ってなければ、無視するっぽい?
1036: // 実際には MFP がバスエラーを出しているのではなく、MFP は俺知らない
1037: // と思って放置してると上位回路 (たぶん SAKI ちゃん) がタイムアウトして
1038: // MPU にバスエラー応答する。
1.1.1.7 root 1039: uint32 pending = mfp.ipr.w;
1.1.1.15 root 1040: if (__predict_false(pending == 0)) {
1041: data.SetBusErr();
1042: } else {
1043: // ch はこの時点で IPR に立ってる一番優先度の高いチャンネルのビット
1044: int ch = 31 - __builtin_clz(pending);
1045: uint b = (1U << ch);
1.1.1.7 root 1046:
1.1.1.15 root 1047: // MPU にベクタを引き渡したので Pending をクリア
1048: mfp.ipr.w &= ~b;
1049: ChangeInterrupt();
1.1.1.7 root 1050:
1.1.1.15 root 1051: // ソフトウェア EOI なら In Service を立てる
1052: if (mfp.vr_s) {
1053: mfp.isr.w |= b;
1054: }
1.1.1.7 root 1055:
1.1.1.15 root 1056: data = mfp.vr_vec + ch;
1.1.1.7 root 1057: }
1058:
1.1.1.15 root 1059: // /IEI ネゲート時の /IACK と /IEI の関係がいまいち分からないけど、
1060: // とりあえず /IACK がアサートされてから 3 MFP クロック後に
1061: // データバスにベクタを供給、次の 1 MFP クロックで DTACK 応答。
1062: // で次の 1 MFP クロック以内に CPU が /IACK を下げるとして、
1063: // 計 5 MFP クロック (= 1.25_usec) としておく。
1064: const busdata intack_wait = busdata::Wait(5 * 250_nsec);
1065: data |= intack_wait;
1066:
1067: return data;
1.1.1.4 root 1068: }
1.1.1.16 root 1069:
1070: /*static*/ const char *
1071: MFPDevice::regname[MFP::RegMax] = {
1072: "GPIP",
1073: "AER",
1074: "DDR",
1075: "IERA",
1076: "IERB",
1077: "IPRA",
1078: "IPRB",
1079: "ISRA",
1080: "ISRB",
1081: "IMRA",
1082: "IMRB",
1083: "VR",
1084: "TACR",
1085: "TBCR",
1086: "TCDCR",
1087: "TADR",
1088: "TBDR",
1089: "TCDR",
1090: "TDDR",
1091: "SCR",
1092: "UCR",
1093: "RSR",
1094: "TSR",
1095: "UDR",
1096: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.