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