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