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