|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "scc.h"
1.1.1.5 root 8: #include "interrupt.h"
9: #include "mpu.h"
1.1 root 10:
11: // IODevice
12: // |
13: // v
14: // upd7201Device (uPD7201 と Z8530 の共通部分)
15: // |
16: // +---------+----------+
17: // v v
18: // SIODevice SCCDevice
19: // (LUNA, uPD7201) (X68030, Z8530)
20:
1.1.1.2 root 21: std::unique_ptr<SCCDevice> gSCC;
22:
1.1 root 23: SCCDevice::SCCDevice()
24: {
25: logname = "scc";
26: devname = "SCC";
27: devaddr = baseaddr;
28: devlen = 0x2000;
1.1.1.2 root 29:
30: cr.chan[0].desc = "Serial Port";
31: cr.chan[1].desc = "Mouse";
1.1 root 32: }
33:
34: SCCDevice::~SCCDevice()
35: {
36: }
37:
38: // Z8530 は RD と WR を同時に Low にするとリセットがかかる。
39: // 回路図からは PEDEC から繋がってるという以上のことは分からないけど
40: // 普通に考えればハードリセットでリセットされるよな。
41:
42: uint64
1.1.1.6 ! root 43: SCCDevice::Read(uint32 offset)
1.1 root 44: {
1.1.1.4 root 45: gMPU->AddCycle(41); // InsideOut p.135
46:
1.1.1.6 ! root 47: switch (offset) {
1.1.1.3 root 48: case 0: // $E98001
1.1 root 49: return ReadCtrl(&cr.chan[1]);
50:
1.1.1.3 root 51: case 1: // $E98003
1.1 root 52: // マウス非接続は 0x00 ?
53: putlog(0, "ChB データレジスタ読み込み (未実装)");
54: return 0x00;
55:
1.1.1.3 root 56: case 2: // $E98005
1.1 root 57: return ReadCtrl(&cr.chan[0]);
58:
1.1.1.3 root 59: case 3: // $E98007
1.1 root 60: putlog(0, "ChA データレジスタ読み込み (未実装)");
1.1.1.2 root 61: return ReadData(&cr.chan[0]);
1.1 root 62: }
1.1.1.3 root 63: __unreachable();
1.1 root 64: }
65:
66: uint64
1.1.1.6 ! root 67: SCCDevice::Write(uint32 offset, uint32 data)
1.1 root 68: {
1.1.1.4 root 69: gMPU->AddCycle(49); // InsideOut p.135
70:
1.1.1.6 ! root 71: switch (offset) {
1.1.1.3 root 72: case 0: // $E98001
1.1 root 73: WriteCtrl(&cr.chan[1], data);
74: return 0;
75:
1.1.1.3 root 76: case 1: // $E98003
1.1 root 77: WriteData(&cr.chan[1], data);
78: return 0;
79:
1.1.1.3 root 80: case 2: // $E98005
1.1 root 81: WriteCtrl(&cr.chan[0], data);
82: return 0;
83:
1.1.1.3 root 84: case 3: // $E98007
1.1 root 85: WriteData(&cr.chan[0], data);
86: return 0;
87: }
1.1.1.3 root 88: __unreachable();
1.1 root 89: }
90:
91: uint64
1.1.1.6 ! root 92: SCCDevice::Peek(uint32 offset)
1.1 root 93: {
1.1.1.6 ! root 94: switch (offset) {
1.1.1.3 root 95: case 0: // $E98001
1.1.1.2 root 96: return PeekCtrl(&cr.chan[1]);
97:
1.1.1.3 root 98: case 1: // $E98003
1.1.1.2 root 99: // マウス非接続は 0x00 ?
100: return 0x00;
101:
1.1.1.3 root 102: case 2: // $E98005
1.1.1.2 root 103: return PeekCtrl(&cr.chan[0]);
104:
1.1.1.3 root 105: case 3: // $E98007
1.1.1.2 root 106: return PeekData(&cr.chan[0]);
107: }
1.1.1.3 root 108: __unreachable();
1.1 root 109: }
110:
111: // Z8530 制御ポート読み込み
112: uint8
113: SCCDevice::ReadCtrl(struct SIO::channel *chan)
114: {
115: return inherited::ReadCtrl(chan);
116: }
117:
118: // Z8530 制御ポート書き込み
119: void
120: SCCDevice::WriteCtrl(struct SIO::channel *chan, uint32 data)
121: {
122: switch (chan->ptr) {
123: case 0: // WR0
124: chan->cr0 = data;
125:
126: switch ((chan->cr0 & SIO::WR0_CMD) >> 3) {
127: case 0:
128: case 1:
129: // コマンド 0、1 がレジスタ切り替え
130: chan->ptr = chan->cr0 & SIO::WR0_PTR;
131: putlog(3, "WR0%s <- $%02x (ptr=%d)", chan->name, data, chan->ptr);
132: break;
133:
134: case 2: // Reset Ext/Status Interrupts
135: putlog(0, "WR0 Reset Ext/Status Interrupts 未実装");
136: break;
137: case 3: // Send Abort
138: putlog(0, "WR0 Send Abort 未実装");
139: break;
140: case 4: // Enable Int on Next Rx Character
141: putlog(0, "WR0 Enable Int on Next Rx Character 未実装");
142: break;
143: case 5: // Reset Tx Int Pending
144: putlog(0, "WR0 Reset Tx Int Pending 未実装");
145: break;
146: case 6: // Error Reset
147: putlog(0, "WR0 Error Reset 未実装");
148: break;
149: case 7: // Reset Highest IUS
150: putlog(0, "WR0 Reset Highest IUS");
151: break;
152: }
153: break;
154:
155: case 2: // WR2
156: // Z8530 の WR2 は A/B 共通でベクタ設定
157: putlog(2, "WR2 <- $%02x ベクタ設定", data);
158: cr.vector = data;
159: // アクセス後は WR0 へ戻す
160: chan->ptr = 0;
161: break;
162:
163: case 1: // WR1
164: case 3:
165: case 4:
166: case 5:
167: case 6:
168: case 7:
169: inherited::WriteCtrl(chan, data);
170: break;
171:
172: case 8: // WR8
173: WriteData(chan, data);
174: // アクセス後は WR0 へ戻す
175: chan->ptr = 0;
176: break;
177:
178: case 9: // WR9
179: putlog(2, "WR%d%s <- $%02x", chan->ptr, chan->name, data);
180: switch ((data & 0xc0) >> 6) {
181: case 0: // No Reset
182: break;
183: case 1: // Channel Reset A
184: ResetChannel(&cr.chan[0]);
185: break;
186: case 2: // Channel Reset B
187: ResetChannel(&cr.chan[1]);
188: break;
189: case 3: // Force Hardware Reset
1.1.1.6 ! root 190: ResetHard();
1.1 root 191: break;
192: default:
193: __unreachable();
194: }
195: // アクセス後は WR0 へ戻す
196: chan->ptr = 0;
197: break;
198:
1.1.1.5 root 199: case 10: // WR10
200: putlog(2, "WR%d%s <- $%02x (未実装)", chan->ptr, chan->name, data);
201: chan->wr10 = data;
202: // アクセス後は WR0 へ戻す
203: chan->ptr = 0;
204: break;
205:
1.1 root 206: case 11: // WR11
207: putlog(2, "WR%d%s <- $%02x (未実装)", chan->ptr, chan->name, data);
208: chan->wr11 = data;
209: // アクセス後は WR0 へ戻す
210: chan->ptr = 0;
211: break;
212:
213: case 12: // WR12
214: chan->tc = (chan->tc & 0xff00) | data;
215: putlog(2, "WR%d%s TC(L)=%04x", chan->ptr, chan->name, chan->tc);
216: // アクセス後は WR0 へ戻す
217: chan->ptr = 0;
218: break;
219:
220: case 13: // WR13
221: chan->tc = (chan->tc & 0x00ff) | (data << 8);
222: putlog(2, "WR%d%s TC(H)=%04x", chan->ptr, chan->name, chan->tc);
223: // アクセス後は WR0 へ戻す
224: chan->ptr = 0;
225: break;
226:
227: case 14: // WR14
228: putlog(2, "WR%d%s <- $%02x (未実装)", chan->ptr, chan->name, data);
229: chan->wr14 = data;
230: // アクセス後は WR0 へ戻す
231: chan->ptr = 0;
232: break;
233:
234: case 15: // WR15
235: putlog(2, "WR%d%s <- $%02x (未実装)", chan->ptr, chan->name, data);
236: chan->wr15 = data;
237: // アクセス後は WR0 へ戻す
238: chan->ptr = 0;
239: break;
240:
241: default:
242: PANIC("未実装レジスタ書き込み WR%d%s <- $%02x",
243: chan->ptr, chan->name, data);
244: break;
245: }
246: }
247:
248: // 割り込みを上げる
249: void
250: SCCDevice::Interrupt()
251: {
252: putlog(0, "割り込み(未実装)");
1.1.1.5 root 253: // gInterrupt->Raise(this);
254: }
255:
256: // 割り込みアクノリッジ
257: int
258: SCCDevice::InterruptAcknowledge()
259: {
260: return 0x50; /* XXX 実際は WR2 とか要因で変わる */
1.1 root 261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.