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