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