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