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