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