|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // HD647180 I/O アクセス
9: //
10:
11: #include "mpu64180.h"
12: #include "hd647180.h"
1.1.1.3 root 13: #include "hd647180asci.h"
1.1 root 14: #include "pio.h"
15: #include "scheduler.h"
1.1.1.2 root 16: #include "ssg.h"
1.1 root 17: #include "xpbus.h"
18:
19: //#define ENABLE_SERIAL_LOG
20:
21: uint32
22: MPU64180Device::ReadIO(uint32 addr)
23: {
24: CYCLE(iowait);
25:
26: // 内蔵 I/O
27: if (io_address <= addr && addr < io_address + 0x80) {
28: return ReadInternalIO(addr - io_address);
29: }
30:
31: return ReadExternalIO(addr);
32: }
33:
34: uint32
35: MPU64180Device::ReadInternalIO(uint32 offset)
36: {
37: uint32 data = -1;
38:
39: switch (offset) {
40: case 0x00: // IO_CNTLA0
1.1.1.3 root 41: data = asci->ReadCNTLA(0);
42: break;
1.1 root 43: case 0x01: // IO_CNTLA1
1.1.1.3 root 44: data = asci->ReadCNTLA(1);
45: break;
1.1 root 46: case 0x02: // IO_CNTLB0
1.1.1.3 root 47: data = asci->ReadCNTLB(0);
48: break;
1.1 root 49: case 0x03: // IO_CNTLB1
1.1.1.3 root 50: data = asci->ReadCNTLB(1);
1.1 root 51: break;
52: case 0x04: // IO_STAT0
1.1.1.3 root 53: data = asci->ReadSTAT(0);
54: break;
1.1 root 55: case 0x05: // IO_STAT1
1.1.1.3 root 56: data = asci->ReadSTAT(1);
57: break;
1.1 root 58: case 0x06: // IO_TDR0
1.1.1.3 root 59: data = asci->ReadTDR(0);
60: break;
1.1 root 61: case 0x07: // IO_TDR1
1.1.1.3 root 62: data = asci->ReadTDR(1);
63: break;
64: case 0x08: // IO_RDR0
65: data = asci->ReadRDR(0);
66: break;
67: case 0x09: // IO_RDR1
68: data = asci->ReadRDR(1);
69: break;
70:
1.1 root 71: case 0x0a: // IO_CNTR
72: case 0x0b: // IO_TRDR
73: break;
74:
75: case 0x0c: // IO_TMDR0L
76: data = ReadTMDRL(0);
77: break;
78: case 0x0d: // IO_TMDR0H
79: data = ReadTMDRH(0);
80: break;
81: case 0x0e: // IO_RLDR0L
82: data = PeekRLDRL(0);
83: break;
84: case 0x0f: // IO_RLDR0H
85: data = PeekRLDRH(0);
86: break;
87: case 0x10: // IO_TCR
88: data = ReadTCR();
89: break;
90: case 0x14: // IO_TMDR1L
91: data = ReadTMDRL(1);
92: break;
93: case 0x15: // IO_TMDR1H
94: data = ReadTMDRH(1);
95: break;
96: case 0x16: // IO_RLDR1L
97: data = PeekRLDRH(0);
98: break;
99: case 0x17: // IO_RLDR1H
100: data = PeekRLDRH(1);
101: break;
102: case 0x18: // IO_FRC
103: data = PeekFRC();
104: break;
105:
106: case 0x20: // IO_SAR0L
107: case 0x21: // IO_SAR0H
108: case 0x22: // IO_SAR0B
109: case 0x23: // IO_DAR0L
110: case 0x24: // IO_DAR0H
111: case 0x25: // IO_DAR0B
112: case 0x26: // IO_BCR0L
113: case 0x27: // IO_BCR0H
114: case 0x28: // IO_MAR1L
115: case 0x29: // IO_MAR1H
116: case 0x2a: // IO_MAR1B
117: case 0x2b: // IO_IAR1L
118: case 0x2c: // IO_IAR1H
119: case 0x2e: // IO_BCR1L
120: case 0x2f: // IO_BCR1H
121: case 0x30: // IO_DSTAT
122: case 0x31: // IO_DMODE
123: break;
124: case 0x32: // IO_DCNTL
125: data = PeekDCNTL();
126: break;
127:
128: case 0x33: // IO_IL
129: data = PeekIL();
130: break;
131: case 0x34: // IO_ITC
132: data = PeekITC();
133: break;
134: case 0x36: // IO_RCR
135: data = PeekRCR();
136: break;
137:
138: case 0x38: // IO_CBR
139: data = PeekCBR();
140: break;
141:
142: case 0x39: // IO_BBR
143: data = PeekBBR();
144: break;
145:
146: case 0x3a: // IO_CBAR
147: data = PeekCBAR();
148: break;
149:
150: case 0x3e: // IO_OMCR
151: break;
152: case 0x3f: // IO_ICR
153: data = PeekICR();
154: break;
155:
156: case 0x40: // IO_T2FRCL
157: case 0x41: // IO_T2FRCH
158: case 0x42: // IO_T2OCR1L
159: case 0x43: // IO_T2OCR1H
160: case 0x44: // IO_T2OCR2L
161: case 0x45: // IO_T2OCR2H
162: case 0x46: // IO_T2ICRL
163: case 0x47: // IO_T2ICRH
164: case 0x48: // IO_T2CSR1
165: case 0x49: // IO_T2CSR2
166: break;
167:
168: case 0x50: // IO_CCSR
169: break;
170: case 0x51: // IO_RMCR
171: data = PeekRMCR();
172: break;
173:
174: case 0x53: // IO_DERA
175: break;
176: case 0x60: // IO_IODRA
177: data = 0xff;
178: #if defined(ENABLE_SERIAL_LOG)
179: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
180: IOName(offset).c_str(), data);
181: #endif
182: return data;
183: case 0x61: // IO_IODRB
184: case 0x62: // IO_IODRC
185: case 0x63: // IO_IODRD
186: case 0x64: // IO_IODRE
187: case 0x65: // IO_IODRF
188: case 0x66: // IO_IDRG
189: case 0x70: // IO_DDRA
190: case 0x71: // IO_DDRB
191: case 0x72: // IO_DDRC
192: case 0x73: // IO_DDRD
193: case 0x74: // IO_DDRE
194: case 0x75: // IO_DDRF
195: break;
196:
197: default:
198: break;
199: }
200:
201: // 表示して値を返す部分はだいたいほぼ共通なので。
202: if ((int32)data < 0) {
203: // data が (32bitで) 負なら未実装ポート。
204: data = 0xff;
205: putlog(0, "ReadInternalIO %s -> $%02x (NOT IMPLEMENTED)",
206: IOName(offset).c_str(), data);
207: } else {
208: putlog(2, "%s -> $%02x", IOName(offset).c_str(), data);
209: }
210: return data;
211: }
212:
213: uint32
214: MPU64180Device::ReadExternalIO(uint32 addr)
215: {
216: uint32 data = -1;
217:
218: // LUNA の外部 I/O はアドレスの上位バイト不問
219: switch (addr & 0xff) {
220: case 0x82: // SSG
221: case 0x83: // SSG
1.1.1.2 root 222: if (ssg) {
223: data = ssg->Read1(addr);
224: } else {
225: data = 0xff; // ?
226: }
1.1 root 227: break;
228:
229: case 0x90: // INT0 ネゲート
230: // 読み込みでも (というかアクセスがあっただけで) ネゲート。
231: putlog(1, "%s Negate INT0", IOName(addr).c_str());
232: NegateINT0();
233: // 実際何が読めるかは不明だが。
234: return 0xff;
235:
236: case 0xa0: // レベル5 割り込み要求
237: case 0xb0: // レベル1 割り込み要求
238: // 読み込みでも割り込み上げそうだがとりあえず未実装へ回しておく。
239: break;
240:
241: default:
242: break;
243: }
244:
245: // 表示して値を返す部分はだいたいほぼ共通なので。
246: if ((int32)data < 0) {
247: // data が (32bitで) 負なら未実装ポート。
248: data = 0xff;
249: putlog(0, "ReadExternalIO %s -> $%02x (NOT IMPLEMENTED)",
250: IOName(addr).c_str(), data);
251: } else {
252: putlog(2, "%s -> $%02x", IOName(addr).c_str(), data);
253: }
254: return data;
255: }
256:
257: uint32
258: MPU64180Device::ReadTMDRL(int ch)
259: {
260: auto& t = timer[ch];
261:
262: // TDR 読み出しで割り込みフラグクリアの実績を解除
263: t.tif &= ~0x02;
264: ChangeTimerInterrupt();
265:
266: // L の読み出しで count を tmp にラッチ
267: t.tmpcount = t.count;
268:
269: // でラッチした L を読み出す
270: return t.tmpcount & 0xff;
271: }
272:
273: uint32
274: MPU64180Device::ReadTMDRH(int ch)
275: {
276: auto& t = timer[ch];
277:
278: // TDR 読み出しで割り込みフラグクリアの実績を解除
279: t.tif &= ~0x02;
280: ChangeTimerInterrupt();
281:
282: // L 読み出し時にラッチしたやつを読み出す。
283: return t.tmpcount >> 8;
284: }
285:
286: uint32
287: MPU64180Device::ReadTCR()
288: {
289: // TCR 読み出しで割り込みフラグクリアの実績を解除
290: timer[0].tif &= ~0x01;
291: timer[1].tif &= ~0x01;
292: ChangeTimerInterrupt();
293:
294: return PeekTCR();
295: }
296:
297: uint32
298: MPU64180Device::WriteIO(uint32 addr, uint32 data)
299: {
300: CYCLE(iowait);
301:
302: // 内蔵 I/O
303: if (io_address <= addr && addr < io_address + 0x80) {
304: return WriteInternalIO(addr - io_address, data);
305: }
306:
307: return WriteExternalIO(addr, data);
308: }
309:
310: uint32
311: MPU64180Device::WriteInternalIO(uint32 offset, uint32 data)
312: {
313: switch (offset) {
314: case 0x00: // IO_CNTLA0
1.1.1.3 root 315: return asci->WriteCNTLA(0, data);
1.1 root 316: case 0x01: // IO_CNTLA1
1.1.1.3 root 317: return asci->WriteCNTLA(1, data);
1.1 root 318: case 0x02: // IO_CNTLB0
1.1.1.3 root 319: return asci->WriteCNTLB(0, data);
1.1 root 320: case 0x03: // IO_CNTLB1
1.1.1.3 root 321: return asci->WriteCNTLB(1, data);
1.1 root 322: case 0x04: // IO_STAT0
1.1.1.3 root 323: return asci->WriteSTAT(0, data);
1.1 root 324: case 0x05: // IO_STAT1
1.1.1.3 root 325: return asci->WriteSTAT(1, data);
1.1 root 326: case 0x06: // IO_TDR0
1.1.1.3 root 327: return asci->WriteTDR(0, data);
1.1 root 328: case 0x07: // IO_TDR1
1.1.1.3 root 329: return asci->WriteTDR(1, data);
330: case 0x08: // IO_RDR0
331: return asci->WriteRDR(0, data);
332: case 0x09: // IO_RDR1
333: return asci->WriteRDR(1, data);
334:
1.1 root 335: case 0x0a: // IO_CNTR
336: case 0x0b: // IO_TRDR
337: break;
338:
339: case 0x0c: // IO_TMDR0L
340: return WriteTMDRL(0, data);
341: case 0x0d: // IO_TMDR0H
342: return WriteTMDRH(0, data);
343: case 0x0e: // IO_RLDR0L
344: return WriteRLDRL(0, data);
345: case 0x0f: // IO_RLDR0H
346: return WriteRLDRH(0, data);
347: case 0x10: // IO_TCR
348: return WriteTCR(data);
349: case 0x14: // IO_TMDR1L
350: return WriteTMDRL(1, data);
351: case 0x15: // IO_TMDR1H
352: return WriteTMDRH(1, data);
353: case 0x16: // IO_RLDR1L
354: return WriteRLDRL(1, data);
355: case 0x17: // IO_RLDR1H
356: return WriteRLDRH(1, data);
357: case 0x18: // IO_FRC
358: // 書き込みは出来るけど、してはいけないっぽい。
359: // たぶん現在値が変わるだけだと思うけど未対応。
360: break;
361:
362: case 0x20: // IO_SAR0L
363: case 0x21: // IO_SAR0H
364: case 0x22: // IO_SAR0B
365: case 0x23: // IO_DAR0L
366: case 0x24: // IO_DAR0H
367: case 0x25: // IO_DAR0B
368: case 0x26: // IO_BCR0L
369: case 0x27: // IO_BCR0H
370: case 0x28: // IO_MAR1L
371: case 0x29: // IO_MAR1H
372: case 0x2a: // IO_MAR1B
373: case 0x2b: // IO_IAR1L
374: case 0x2c: // IO_IAR1H
375: case 0x2e: // IO_BCR1L
376: case 0x2f: // IO_BCR1H
377: case 0x30: // IO_DSTAT
378: case 0x31: // IO_DMODE
379: break;
380: case 0x32: // IO_DCNTL
381: return WriteDCNTL(data);
382:
383: case 0x33: // IO_IL
384: return WriteIL(data);
385: case 0x34: // IO_ITC
386: return WriteITC(data);
387: case 0x36: // IO_RCR
388: return WriteRCR(data);
389:
390: case 0x38: // IO_CBR
391: return WriteCBR(data);
392: case 0x39: // IO_BBR
393: return WriteBBR(data);
394: case 0x3a: // IO_CBAR
395: return WriteCBAR(data);
396:
397: case 0x3e: // IO_OMCR
398: break;
399: case 0x3f: // IO_ICR
400: return WriteICR(data);
401:
402: case 0x40: // IO_T2FRCL
403: case 0x41: // IO_T2FRCH
404: case 0x42: // IO_T2OCR1L
405: case 0x43: // IO_T2OCR1H
406: case 0x44: // IO_T2OCR2L
407: case 0x45: // IO_T2OCR2H
408: case 0x46: // IO_T2ICRL
409: case 0x47: // IO_T2ICRH
410: case 0x48: // IO_T2CSR1
411: case 0x49: // IO_T2CSR2
412: break;
413:
414: case 0x50: // IO_CCSR
415: break;
416: case 0x51: // IO_RMCR
417: return WriteRMCR(data);
418:
419: case 0x53: // IO_DERA
420: case 0x60: // IO_IODRA
421: case 0x61: // IO_IODRB
422: case 0x62: // IO_IODRC
423: case 0x63: // IO_IODRD
424: case 0x64: // IO_IODRE
425: case 0x65: // IO_IODRF
426: case 0x66: // IO_IDRG
427: case 0x70: // IO_DDRA
428: case 0x71: // IO_DDRB
429: case 0x72: // IO_DDRC
430: case 0x73: // IO_DDRD
431: case 0x74: // IO_DDRE
432: case 0x75: // IO_DDRF
433: break;
434:
435: default:
436: break;
437: }
438:
439: putlog(0, "WriteInternalIO %s <- $%02x (NOT IMPLEMENTED)",
440: IOName(offset).c_str(), data);
441: return 0;
442: }
443:
444: uint32
445: MPU64180Device::WriteExternalIO(uint32 addr, uint32 data)
446: {
447: // LUNA の外部 I/O はアドレスの上位バイト不問
448: switch (addr & 0xff) {
449: case 0x82: // SSG
450: case 0x83: // SSG
1.1.1.2 root 451: if (ssg) {
452: ssg->Write1(addr, data);
453: }
1.1 root 454: return 0;
455:
456: case 0x90: // INT0 ネゲート
457: putlog(1, "%s Negate INT0", IOName(addr).c_str());
458: NegateINT0();
459: return 0;
460:
461: case 0xa0: // レベル5 割り込み要求
462: putlog(1, "%s Interrupt High", IOName(addr).c_str());
463: pio0->InterruptXPHigh();
464: return 0;
465:
466: case 0xb0: // レベル1 割り込み要求
467: putlog(1, "%s Interrupt Low", IOName(addr).c_str());
468: pio0->InterruptXPLow();
469: return 0;
470:
471: default:
472: break;
473: }
474:
475: putlog(0, "WriteExternalIO %s <- $%02x (NOT IMPLEMENTED)",
476: IOName(addr).c_str(), data);
477: return 0;
478: }
479:
480: uint32
481: MPU64180Device::WriteTMDRL(int ch, uint32 data)
482: {
483: auto& t = timer[ch];
484: if (t.running) {
485: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
486: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
487: IOName(HD647180::IO_TMDRL(ch)).c_str(), data);
488: } else {
489: t.count = (t.count & 0xff00) | data;
1.1.1.2 root 490: putlog(1, "%s <- $%02x (TMDR%u = $%04x)",
1.1 root 491: IOName(HD647180::IO_TMDRL(ch)).c_str(), data, ch, t.count);
492: }
493: return 0;
494: }
495:
496: uint32
497: MPU64180Device::WriteTMDRH(int ch, uint32 data)
498: {
499: auto& t = timer[ch];
500: if (t.running) {
501: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
502: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
503: IOName(HD647180::IO_TMDRH(ch)).c_str(), data);
504: } else {
505: t.count = (data << 8) | (t.count & 0x00ff);
1.1.1.2 root 506: putlog(1, "%s <- $%02x (TMDR%u = $%04x)",
1.1 root 507: IOName(HD647180::IO_TMDRH(ch)).c_str(), data, ch, t.count);
508: }
509: return 0;
510: }
511:
512: uint32
513: MPU64180Device::WriteRLDRL(int ch, uint32 data)
514: {
515: // 動作中にも変更可能
516: auto& t = timer[ch];
517: t.reload = (t.reload & 0xff00) | data;
1.1.1.2 root 518: putlog(1, "%s <- $%02x (RLDR%u = $%04x)",
1.1 root 519: IOName(HD647180::IO_RLDRL(ch)).c_str(), data, ch, t.reload);
520: return 0;
521: }
522:
523: uint32
524: MPU64180Device::WriteRLDRH(int ch, uint32 data)
525: {
526: // 動作中にも変更可能
527: auto& t = timer[ch];
528: t.reload = (data << 8) | (t.reload & 0x00ff);
1.1.1.2 root 529: putlog(1, "%s <- $%02x (RLDR%u = $%04x)",
1.1 root 530: IOName(HD647180::IO_RLDRH(ch)).c_str(), data, ch, t.reload);
531: return 0;
532: }
533:
534: uint32
535: MPU64180Device::WriteTCR(uint32 data)
536: {
537: std::array<bool, 2> new_tde;
538: std::string msg;
539:
540: timer[1].intr_enable = (data & 0x20);
541: timer[0].intr_enable = (data & 0x10);
542: // intr_enable を変更したので ChangeTimerInterrupt() を呼ぶのは
543: // 最後に行っている。
544:
545: timer_toc = (data >> 2) & 3;
546:
547: new_tde[1] = (data & 0x02);
548: new_tde[0] = (data & 0x01);
1.1.1.2 root 549: msg = string_format("TIE1=%u TIE0=%u TOC=$%x",
1.1 root 550: (timer[1].intr_enable ? 1 : 0),
551: (timer[0].intr_enable ? 1 : 0),
552: timer_toc);
553:
554: for (int ch = 0; ch < timer.size(); ch++) {
555: auto& t = timer[ch];
556: if (t.running == false && new_tde[ch] == true) {
557: // カウントダウン開始
558: t.count = t.reload;
559: t.running = true;
560: MakeActiveTimer();
1.1.1.2 root 561: msg += string_format(" Timer%u=Start", ch);
1.1 root 562: EnableTimer();
563: } else if (t.running == true && new_tde[ch] == false) {
564: // カウントダウン停止
565:
566: // ここではタイマーの状態を停止にするだけでよい。
567: // タイマーイベントの中で running が落ちてたら停止してくれる。
568: t.running = false;
569: MakeActiveTimer();
1.1.1.2 root 570: msg += string_format(" Timer%u=Stop", ch);
1.1 root 571: } else {
572: // 変化なし
573: }
574: }
575:
576: putlog(1, "%s <- $%02x: %s",
577: IOName(HD647180::IO_TCR).c_str(), data, msg.c_str());
578:
579: // ログの順序的に書き込みログの後で変更する
580: ChangeTimerInterrupt();
581:
582: return 0;
583: }
584:
585: uint32
586: MPU64180Device::WriteDCNTL(uint32 data)
587: {
588: // メモリウェイト 0,1,2,3
589: memwait = (data >> 6) & 3;
590:
591: // I/O ウェイトは 0,2,3,4
592: iowait = (data >> 4) & 3;
593: if (iowait != 0)
594: iowait++;
595:
596: // 下位4ビット分は未実装
597: dcntl = data & 0x0f;
598: return 0;
599: }
600:
601: uint32
602: MPU64180Device::WriteIL(uint32 data)
603: {
604: // 書き込み時にマスクする
605: intvec_low = data & 0xe0;
606: return 0;
607: }
608:
609: uint32
610: MPU64180Device::WriteITC(uint32 data)
611: {
612: itc_trap = (data & 0x80);
613: // UFO は ReadOnly
614: itc_ite2 = (data & 0x04);
615: itc_ite1 = (data & 0x02);
616: itc_ite0 = (data & 0x01);
617:
618: // XXX 割り込み変わったら何かする?
619:
620: return 0;
621: }
622:
623: uint32
624: MPU64180Device::WriteRCR(uint32 data)
625: {
626: // 未実装
627: rcr = data | 0x3c;
628:
629: if ((rcr & 0x80)) {
630: // Refresh Enable は未実装。無効にするなら表示不要。
631: putlog(0, "%s <- $%02x: Refresh Enable (NOT IMPLEMENTED)",
632: IOName(HD647180::IO_RCR).c_str(), data);
633: } else {
634: // ログレベル 1 なら全部表示
635: putlog(1, "%s <- $%02x (NOT IMPLEMENTED)",
636: IOName(HD647180::IO_RCR).c_str(), data);
637: }
638: return 0;
639: }
640:
641: uint32
642: MPU64180Device::WriteCBR(uint32 data)
643: {
644: int lv;
645: uint32 new_base = data << 12;
646: if (commbase != new_base) {
647: lv = 1;
648: commbase = new_base;
649: } else {
650: lv = 2;
651: }
652: putlog(lv, "%s <- $%02x: Common Base Addr=$%05x",
653: IOName(HD647180::IO_CBR).c_str(), data, commbase);
654: return 0;
655: }
656:
657: uint32
658: MPU64180Device::WriteBBR(uint32 data)
659: {
660: int lv;
661: uint32 new_base = data << 12;
662: if (bankbase != new_base) {
663: lv = 1;
664: bankbase = new_base;
665: } else {
666: lv = 2;
667: }
668: putlog(lv, "%s <- $%02x: Bank Base Addr=$%05x",
669: IOName(HD647180::IO_BBR).c_str(), data, bankbase);
670: return 0;
671: }
672:
673: uint32
674: MPU64180Device::WriteCBAR(uint32 data)
675: {
676: int lv;
677: uint32 new_comm = (data & 0xf0) << 8;
678: uint32 new_bank = (data & 0x0f) << 12;
679: if (commarea != new_comm || bankarea != new_bank) {
680: lv = 1;
681: commarea = new_comm;
682: bankarea = new_bank;
683: } else {
684: lv = 2;
685: }
686: putlog(lv, "%s <- $%02x: CommArea=$%04x BankArea=$%04x",
687: IOName(HD647180::IO_CBAR).c_str(), data, commarea, bankarea);
688: return 0;
689: }
690:
691: uint32
692: MPU64180Device::WriteICR(uint32 data)
693: {
694: io_address = data & 0x80;
695: putlog(1, "%s <- $%02x: I/O Address=$%02x",
696: IOName(HD647180::IO_ICR).c_str(), data, io_address);
697:
698: // IOSTP は未実装
699: if ((data & 0x20) != 0) {
700: putlog(0, "%s IOSTP (NOT IMPLEMENTED)");
701: }
702: return 0;
703: }
704:
705: uint32
706: MPU64180Device::WriteRMCR(uint32 data)
707: {
708: xpbus->SetRMCR(data);
709: putlog(1, "%s <- $%02x: RAM address=$%05x",
710: IOName(HD647180::IO_RMCR).c_str(), data, xpbus->GetXPRAMAddr());
711: return 0;
712: }
713:
714: uint32
715: MPU64180Device::PeekIO(uint32 addr)
716: {
717: // 内蔵 I/O
718: if (io_address <= addr && addr < io_address + 0x80) {
719: return PeekInternalIO(addr - io_address);
720: }
721:
722: return PeekExternalIO(addr);
723: }
724:
725: uint32
726: MPU64180Device::PeekInternalIO(uint32 offset)
727: {
728: switch (offset) {
729: case 0x00: // IO_CNTLA0
1.1.1.3 root 730: return asci->PeekCNTLA(0);
1.1 root 731: case 0x01: // IO_CNTLA1
1.1.1.3 root 732: return asci->PeekCNTLA(1);
1.1 root 733: case 0x02: // IO_CNTLB0
1.1.1.3 root 734: return asci->PeekCNTLB(0);
1.1 root 735: case 0x03: // IO_CNTLB1
1.1.1.3 root 736: return asci->PeekCNTLB(1);
1.1 root 737: case 0x04: // IO_STAT0
1.1.1.3 root 738: return asci->PeekSTAT(0);
1.1 root 739: case 0x05: // IO_STAT1
1.1.1.3 root 740: return asci->PeekSTAT(1);
1.1 root 741: case 0x06: // IO_TDR0
1.1.1.3 root 742: return asci->PeekTDR(0);
1.1 root 743: case 0x07: // IO_TDR1
1.1.1.3 root 744: return asci->PeekTDR(1);
745: case 0x08: // IO_RDR0
746: return asci->PeekRDR(0);
747: case 0x09: // IO_RDR1
748: return asci->PeekRDR(1);
749:
1.1 root 750: case 0x0a: // IO_CNTR
751: case 0x0b: // IO_TRDR
752: break;
753:
754: case 0x0c: // IO_TMDR0L
755: return PeekTMDRL(0);
756: case 0x0d: // IO_TMDR0H
757: return PeekTMDRH(0);
758: case 0x0e: // IO_RLDR0L
759: return PeekRLDRL(0);
760: case 0x0f: // IO_RLDR0H
761: return PeekRLDRH(0);
762: case 0x10: // IO_TCR
763: return PeekTCR();
764: case 0x14: // IO_TMDR1L
765: return PeekTMDRL(1);
766: case 0x15: // IO_TMDR1H
767: return PeekTMDRH(1);
768: case 0x16: // IO_RLDR1L
769: return PeekRLDRL(1);
770: case 0x17: // IO_RLDR1H
771: return PeekRLDRH(1);
772: case 0x18: // IO_FRC
773: return PeekFRC();
774:
775: case 0x20: // IO_SAR0L
776: case 0x21: // IO_SAR0H
777: case 0x22: // IO_SAR0B
778: case 0x23: // IO_DAR0L
779: case 0x24: // IO_DAR0H
780: case 0x25: // IO_DAR0B
781: case 0x26: // IO_BCR0L
782: case 0x27: // IO_BCR0H
783: case 0x28: // IO_MAR1L
784: case 0x29: // IO_MAR1H
785: case 0x2a: // IO_MAR1B
786: case 0x2b: // IO_IAR1L
787: case 0x2c: // IO_IAR1H
788: case 0x2e: // IO_BCR1L
789: case 0x2f: // IO_BCR1H
790: case 0x30: // IO_DSTAT
791: case 0x31: // IO_DMODE
792: break;
793: case 0x32: // IO_DCNTL
794: return PeekDCNTL();
795:
796: case 0x33: // IO_IL
797: return PeekIL();
798: case 0x34: // IO_ITC
799: return PeekITC();
800: case 0x36: // IO_RCR
801: return PeekRCR();
802:
803: case 0x38: // IO_CBR
804: return PeekCBR();
805: case 0x39: // IO_BBR
806: return PeekBBR();
807: case 0x3a: // IO_CBAR
808: return PeekCBAR();
809:
810: case 0x3e: // IO_OMCR
811: break;
812: case 0x3f: // IO_ICR
813: return PeekICR();
814:
815: case 0x40: // IO_T2FRCL
816: case 0x41: // IO_T2FRCH
817: case 0x42: // IO_T2OCR1L
818: case 0x43: // IO_T2OCR1H
819: case 0x44: // IO_T2OCR2L
820: case 0x45: // IO_T2OCR2H
821: case 0x46: // IO_T2ICRL
822: case 0x47: // IO_T2ICRH
823: case 0x48: // IO_T2CSR1
824: case 0x49: // IO_T2CSR2
825: break;
826:
827: case 0x50: // IO_CCSR
828: break;
829: case 0x51: // IO_RMCR
830: return xpbus->GetRMCR();
831:
832: case 0x53: // IO_DERA
833: case 0x60: // IO_IODRA
834: case 0x61: // IO_IODRB
835: case 0x62: // IO_IODRC
836: case 0x63: // IO_IODRD
837: case 0x64: // IO_IODRE
838: case 0x65: // IO_IODRF
839: case 0x66: // IO_IDRG
840: case 0x70: // IO_DDRA
841: case 0x71: // IO_DDRB
842: case 0x72: // IO_DDRC
843: case 0x73: // IO_DDRD
844: case 0x74: // IO_DDRE
845: case 0x75: // IO_DDRF
846: break;
847:
848: default:
849: break;
850: }
851: return 0xff;
852: }
853:
854: uint32
855: MPU64180Device::PeekExternalIO(uint32 addr)
856: {
857: // LUNA の外部 I/O はアドレスの上位バイト不問
858: switch (addr & 0xff) {
859: case 0x82: // SSG
860: case 0x83: // SSG
1.1.1.2 root 861: if (ssg) {
862: return ssg->Peek1(addr);
863: }
1.1 root 864: break;
865:
866: case 0x90: // INT0 ネゲート
867: break;
868:
869: case 0xa0: // レベル5 割り込み要求
870: case 0xb0: // レベル1 割り込み要求
871: break;
872:
873: default:
874: break;
875: }
876: return 0xff;
877: }
878:
879: uint32
880: MPU64180Device::PeekTMDRL(int ch) const
881: {
882: return timer[ch].count & 0xff;
883: }
884:
885: uint32
886: MPU64180Device::PeekTMDRH(int ch) const
887: {
888: return timer[ch].count >> 8;
889: }
890:
891: uint32
892: MPU64180Device::PeekRLDRL(int ch) const
893: {
894: return timer[ch].reload & 0xff;
895: }
896:
897: uint32
898: MPU64180Device::PeekRLDRH(int ch) const
899: {
900: return timer[ch].reload >> 8;
901: }
902:
903: uint32
904: MPU64180Device::PeekTCR() const
905: {
906: uint32 data = (timer_toc << 2);
907:
908: if (timer[1].tif != 0)
909: data |= 0x80;
910: if (timer[0].tif != 0)
911: data |= 0x40;
912: if (timer[1].intr_enable)
913: data |= 0x20;
914: if (timer[0].intr_enable)
915: data |= 0x10;
916: if (timer[1].running)
917: data |= 0x02;
918: if (timer[0].running)
919: data |= 0x01;
920:
921: return data;
922: }
923:
924: uint32
925: MPU64180Device::PeekFRC() const
926: {
927: if (opmode == OpMode::Reset) {
928: return 0xff;
929: } else {
930: // Free Running Counter はリセット時に 0FFH で、
931: // そこから 10φ ごとに1ずつ減っていく。
932: // そのため、リセット時の時刻を覚えておき、経過時間から計算する。
933: uint64 time = scheduler->GetVirtTime() - timer_epoch;
1.1.1.4 ! root 934: return 0xff - (uint8)(time / (clock_tsec * 10));
1.1 root 935: }
936: }
937:
938: uint32
939: MPU64180Device::PeekDCNTL() const
940: {
941: uint32 data;
942:
943: data = (memwait << 6);
944: if (iowait != 0) {
945: data |= (iowait - 1) << 4;
946: }
947: data |= dcntl;
948:
949: return data;
950: }
951:
952: uint32
953: MPU64180Device::PeekIL() const
954: {
955: return intvec_low;
956: }
957:
958: uint32
959: MPU64180Device::PeekITC() const
960: {
961: uint32 data = 0x38;
962: if (itc_trap)
963: data |= 0x80;
964: if (itc_ufo)
965: data |= 0x40;
966: if (itc_ite2)
967: data |= 0x04;
968: if (itc_ite1)
969: data |= 0x02;
970: if (itc_ite0)
971: data |= 0x01;
972: return data;
973: }
974:
975: uint32
976: MPU64180Device::PeekRCR() const
977: {
978: return rcr;
979: }
980:
981: uint32
982: MPU64180Device::PeekCBR() const
983: {
984: return (commbase >> 12) & 0xff;
985: }
986:
987: uint32
988: MPU64180Device::PeekBBR() const
989: {
990: return (bankbase >> 12) & 0xff;
991: }
992:
993: uint32
994: MPU64180Device::PeekCBAR() const
995: {
996: uint32 data;
997:
998: data = (commarea >> 8) & 0xf0;
999: data |= (bankarea >> 12) & 0x0f;
1000:
1001: return data;
1002: }
1003:
1004: uint32
1005: MPU64180Device::PeekICR() const
1006: {
1007: // IOSTP は未実装
1008: return io_address | 0x5f;
1009: }
1010:
1011: uint32
1012: MPU64180Device::PeekRMCR() const
1013: {
1014: return xpbus->GetRMCR();
1015: }
1016:
1017: // アドレス (とあれば名前) を返す。
1018: /*static*/ std::string
1019: MPU64180Device::IOName(uint32 addr)
1020: {
1021: std::string buf;
1022:
1023: if (addr < 0x100) {
1024: buf = string_format("%02XH", addr);
1025: } else {
1026: buf = string_format("%04XH", addr);
1027: }
1028:
1029: if (addr < ionames.size() && ionames[addr] != NULL) {
1030: buf += '(';
1031: buf += ionames[addr];
1032: buf += ')';
1033: }
1034: return buf;
1035: }
1036:
1037: /*static*/ std::vector<const char *>
1038: MPU64180Device::ionames = {
1039: "CNTLA0", // 00
1040: "CNTLA1", // 01
1041: "CNTLB0", // 02
1042: "CNTLB1", // 03
1043: "STAT0", // 04
1044: "STAT1", // 05
1045: "TDR0", // 06
1046: "TDR1", // 07
1.1.1.3 root 1047: "RDR0", // 08
1048: "RDR1", // 09
1.1 root 1049: "CNTR", // 0a
1050: "TRDR", // 0b
1051: "TMDR0L", // 0c
1052: "TMDR0H", // 0d
1053: "RLDR0L", // 0e
1054: "RLDR0H", // 0f
1055:
1056: "TCR", // 10
1057: NULL, // 11
1058: NULL, // 12
1059: NULL, // 13
1060: "TMDR1L", // 14
1061: "TMDR1H", // 15
1062: "RLDR1L", // 16
1063: "RLDR1H", // 17
1064: "FRFC", // 18
1065: NULL, // 19
1066: NULL, // 1a
1067: NULL, // 1b
1068: NULL, // 1c
1069: NULL, // 1d
1070: NULL, // 1e
1071: NULL, // 1f
1072:
1073: "SAR0L", // 20
1074: "SAR0H", // 21
1075: "SAR0B", // 22
1076: "DAR0L", // 23
1077: "DAR0H", // 24
1078: "DAR0B", // 25
1079: "BCR0L", // 26
1080: "BCR0H", // 27
1081: "MAR1L", // 28
1082: "MAR1H", // 29
1083: "MAR1B", // 2a
1084: "IAR1L", // 2b
1085: "IAR1H", // 2c
1086: NULL, // 2d
1087: "BCR1L", // 2e
1088: "BCR1H", // 2f
1089:
1090: "DSTAT", // 30
1091: "DMODE", // 31
1092: "DCNTL", // 32
1093: "IL", // 33
1094: "ITC", // 34
1095: NULL, // 35
1096: "RCR", // 36
1097: NULL, // 37
1098: "CBR", // 38
1099: "BBR", // 39
1100: "CBAR", // 3a
1101: NULL, // 3b
1102: NULL, // 3c
1103: NULL, // 3d
1104: "OMCR", // 3e
1105: "ICR", // 3f
1106:
1107: "T2FRCL", // 40
1108: "T2FRCH", // 41
1109: "T2OCR1L", // 42
1110: "T2OCR1H", // 43
1111: "T2OCR2L", // 44
1112: "T2OCR2H", // 45
1113: "T2ICRL", // 46
1114: "T2ICRH", // 47
1115: "T2CSR1", // 48
1116: "T2CSR2", // 49
1117: NULL, // 4a
1118: NULL, // 4b
1119: NULL, // 4c
1120: NULL, // 4d
1121: NULL, // 4e
1122: NULL, // 4f
1123:
1124: "CCSR", // 50
1125: "RMCR", // 51
1126: NULL, // 52
1127: "DERA", // 53
1128: NULL, // 54
1129: NULL, // 55
1130: NULL, // 56
1131: NULL, // 57
1132: NULL, // 58
1133: NULL, // 59
1134: NULL, // 5a
1135: NULL, // 5b
1136: NULL, // 5c
1137: NULL, // 5d
1138: NULL, // 5e
1139: NULL, // 5f
1140:
1141: "IODRA", // 60
1142: "IODRB", // 61
1143: "IODRC", // 62
1144: "IODRD", // 63
1145: "IODRE", // 64
1146: "IODRF", // 65
1147: "IDRG", // 66
1148: NULL, // 67
1149: NULL, // 68
1150: NULL, // 69
1151: NULL, // 6a
1152: NULL, // 6b
1153: NULL, // 6c
1154: NULL, // 6d
1155: NULL, // 6e
1156: NULL, // 6f
1157:
1158: "DDRA", // 70
1159: "DDRB", // 71
1160: "DDRC", // 72
1161: "DDRD", // 73
1162: "DDRE", // 74
1163: "DDRF", // 75
1164: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.