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