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