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