|
|
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:
1.1.1.10 root 7: //
8: // DMAC (HD63450)
9: //
10:
1.1 root 11: #pragma once
12:
13: #include "device.h"
1.1.1.11 root 14: #include "fixedqueue.h"
1.1.1.8 root 15: #include "monitor.h"
1.1.1.10 root 16: #include "event.h"
1.1.1.9 root 17: #include <array>
1.1 root 18:
1.1.1.12! root 19: class ADPCMDevice;
! 20: class FDCDevice;
! 21: class InterruptDevice;
! 22: class MainbusDevice;
! 23:
1.1 root 24: struct DMAC
25: {
1.1.1.2 root 26: static const uint32 CSR = 0x00; // .B
27: static const uint32 CER = 0x01; // .B
28: static const uint32 DCR = 0x04; // .B
29: static const uint32 OCR = 0x05; // .B
30: static const uint32 SCR = 0x06; // .B
31: static const uint32 CCR = 0x07; // .B
32: static const uint32 MTC = 0x0a; // .W
33: static const uint32 MAR = 0x0c; // .L
34: static const uint32 DAR = 0x14; // .L
35: static const uint32 BTC = 0x1a; // .W
36: static const uint32 BAR = 0x1c; // .L
37: static const uint32 NIV = 0x25; // .B
38: static const uint32 EIV = 0x27; // .B
39: static const uint32 MFC = 0x29; // .B
40: static const uint32 CPR = 0x2d; // .B
41: static const uint32 DFC = 0x31; // .B
42: static const uint32 BFC = 0x39; // .B
43: static const uint32 GCR = 0x3f; // .B (ch#3のみ)
44:
1.1.1.11 root 45: // b7 b6 b5 b4 b3 b2 b1 b0
46: // +-----+-----+-----+-----+-----+-----+-----+-----+
47: // CSR | COC | BTC | NDT | ERR | ACT | DIT | PCT | PCS |
48: // +-----+-----+-----+-----+-----+-----+-----+-----+
1.1.1.2 root 49: //
50: static const uint32 CSR_COC = 0x80; // Channel Operation Complete
51: static const uint32 CSR_BTC = 0x40; // Block Transfer Complete
52: static const uint32 CSR_NDT = 0x20; // Normal Device Termination
53: static const uint32 CSR_ERR = 0x10; // Error Bit
54: static const uint32 CSR_ACT = 0x08; // Channel Active
1.1.1.11 root 55: static const uint32 CSR_DIT = 0x04; // DONE Input Transition
1.1.1.2 root 56: static const uint32 CSR_PCT = 0x02; // PCL Transition
57: static const uint32 CSR_PCS = 0x01; // PCL Input Line State
58:
1.1.1.11 root 59: // b7 b6 b5 b4 b3 b2 b1 b0
60: // +-----+-----+-----+-----+-----+-----+-----+-----+
61: // CER | 0 | Error Code |
62: // +-----+-----+-----+-----+-----+-----+-----+-----+
63: //
1.1.1.2 root 64: static const uint32 CER_NO_ERROR = 0x00; // No Error
65: static const uint32 CER_CONFIG = 0x01; // Configuration Error
1.1.1.11 root 66: static const uint32 CER_TIMING = 0x02; // Operation Timing Error
1.1.1.2 root 67: static const uint32 CER_ADDR_MAR = 0x05; // Address error in MAR
68: static const uint32 CER_ADDR_DAR = 0x06; // Address error in DAR
69: static const uint32 CER_ADDR_BAR = 0x07; // Address error in BAR
70: static const uint32 CER_BUS_MAR = 0x09; // Bus error in MAR
71: static const uint32 CER_BUS_DAR = 0x0a; // Bus error in DAR
72: static const uint32 CER_BUS_BAR = 0x0b; // Bus error in BAR
73: static const uint32 CER_COUNT_MTC = 0x0d; // Count error in MTC
74: static const uint32 CER_COUNT_BTC = 0x0f; // Count error in BTC
75: static const uint32 CER_EXT_ABORT = 0x10; // External Abort
76: static const uint32 CER_SOFT_ABORT = 0x11; // Software Abort
77:
1.1.1.11 root 78: // b7 b6 b5 b4 b3 b2 b1 b0
79: // +-----+-----+-----+-----+-----+-----+-----+-----+
80: // DCR | XRM | DTYP | DPS | 0 | PCL |
81: // +-----+-----+-----+-----+-----+-----+-----+-----+
82: //
83: static const uint32 XRM_BURST = 0; // Burst Transfer
84: static const uint32 XRM_CYCLE_WO_HOLD = 2; // Cycle Steal without Hold
85: static const uint32 XRM_CYCLE_WITH_HOLD = 3;// Cycle Steal with Hold
86: static const uint32 DTYP_68000 = 0; // 68000 devices
87: static const uint32 DTYP_6800 = 1; // 6800 devices
88: static const uint32 DTYP_ACK = 2; // Devices with ACK
89: static const uint32 DTYP_ACK_REDY = 3; // Devices with ACK+READY
90: static const uint32 DPS_8BIT = 0; // 8bit port
91: static const uint32 DPS_16BIT = 1; // 16bit port
92: static const uint32 PCL_STATUS = 0; // Status Input
93: static const uint32 PCL_STATUS_INTR = 1; // Status Input with Interrupt
94: static const uint32 PCL_PULSE = 2; // Start Pulse
95: static const uint32 PCL_ABORT = 3; // Abort Input
96:
97: // b7 b6 b5 b4 b3 b2 b1 b0
98: // +-----+-----+-----+-----+-----+-----+-----+-----+
99: // OCR | DIR | 0 | SIZE | CHAIN | REQG |
100: // +-----+-----+-----+-----+-----+-----+-----+-----+
101: //
102: static const uint32 DIR_MtoD = 0; // Memory to Device
103: static const uint32 DIR_DtoM = 1; // Device to Memory
104: static const uint32 SIZE_8BIT_PACK = 0; // 8bit (Packed)
105: static const uint32 SIZE_16BIT = 1; // 16bit
106: static const uint32 SIZE_32BIT = 2; // 32bit
107: static const uint32 SIZE_8BIT_UNPK = 3; // 8bit UnPacked
108: static const uint32 CHAIN_NOCHAIN = 0; // Chain operation is disabled
109: static const uint32 CHAIN_ARRAY = 2; // Array Chaining
110: static const uint32 CHAIN_LINK = 3; // Linked Array Chaining
111: static const uint32 REQG_AUTO_LIM = 0; // Auto Request (Limited)
112: static const uint32 REQG_AUTO_MAX = 1; // AUto Request (Max)
113: static const uint32 REQG_EXTERNAL = 2; // External Request
114: static const uint32 REQG_AUTOFIRST = 3; // Auto first then ext.
115:
116: // b7 b6 b5 b4 b3 b2 b1 b0
117: // +-----+-----+-----+-----+-----+-----+-----+-----+
118: // SCR | 0 | MAC | DAC |
119: // +-----+-----+-----+-----+-----+-----+-----+-----+
120: //
1.1.1.2 root 121: static const uint32 SCR_NO_COUNT = 0; // Does not count
122: static const uint32 SCR_COUNT_UP = 1; // Count up
123: static const uint32 SCR_COUNT_DOWN = 2; // Count down
124:
1.1.1.11 root 125: // b7 b6 b5 b4 b3 b2 b1 b0
126: // +-----+-----+-----+-----+-----+-----+-----+-----+
127: // CCR | STR | CNT | HLT | SAB | INT | 0 |
128: // +-----+-----+-----+-----+-----+-----+-----+-----+
129: //
1.1.1.2 root 130: static const uint32 CCR_STR = 0x80; // Start Operation
131: static const uint32 CCR_CNT = 0x40; // Continue Operation
132: static const uint32 CCR_HLT = 0x20; // Halt Operation
133: static const uint32 CCR_SAB = 0x10; // Software Abort
134: static const uint32 CCR_INT = 0x08; // Interrupt Enable
1.1 root 135:
1.1.1.11 root 136: // b7 b6 b5 b4 b3 b2 b1 b0
137: // +-----+-----+-----+-----+-----+-----+-----+-----+
138: // CPR | 0 | CP |
139: // +-----+-----+-----+-----+-----+-----+-----+-----+
140:
141: // b7 b6 b5 b4 b3 b2 b1 b0
142: // +-----+-----+-----+-----+-----+-----+-----+-----+
143: // GCR | 0 | BT | BR |
144: // +-----+-----+-----+-----+-----+-----+-----+-----+
145: };
1.1 root 146:
1.1.1.11 root 147: // 各チャンネル
148: class DMACChan
149: {
150: public:
151: // 二次変数など
152: int ch; // チャンネル番号
153: const char *desc; // チャンネルの用途(モニタ表示用)
154: uint8 priority; // 現在の実効プライオリティ
155: bool req; // REQ#n 信号
156:
157: // レジスタ
158:
159: // CSR
160: uint8 csr; // COC,BTC,NDT,ERR を保持
161: bool active; // ACT
162: bool pcl_pin; // PCL 信号線の状態 (High が true)
163: bool pcl_prev; // 前回の PCL の状態 (High が true)
164: uint8 GetCSR() const;
165: bool IsINTR() const { // CSR の割り込み要因が立っていれば true
166: // XXX PCT は未対応
167: return csr;
168: }
169:
170: uint8 cer;
171:
172: // DCR
173: uint xrm;
174: uint dtyp;
175: uint dps;
176: uint dcr_pcl;
177: uint8 GetDCR() const;
178: void SetDCR(uint8);
179: uint GetXRM() const { return xrm; }
180: uint GetDTYP() const { return dtyp; }
181: uint GetDPS() const { return dps; }
182: uint GetPCL() const { return dcr_pcl; }
183:
184: // OCR
185: uint dir;
186: uint size;
187: uint chain;
188: uint reqg;
189: uint8 GetOCR() const;
190: void SetOCR(uint8);
191: uint32 GetDIR() const { return dir; }
192: uint32 GetSIZE() const { return size; }
193: uint32 GetCHAIN() const { return chain; }
194: uint32 GetREQG() const { return reqg; }
195: bool IsChain() const { return GetCHAIN() & 0x02; }
196: bool IsSingleAddress() const { return GetREQG() & 0x02; }
197:
198: // SCR
199: // XXX 名前が衝突してるのは後からなんとかする
200: uint scr_mac;
201: uint scr_dac;
202: uint8 GetSCR() const;
203: void SetSCR(uint8);
204: uint32 GetMAC() const { return scr_mac; }
205: uint32 GetDAC() const { return scr_dac; }
206: int mac;
207: int dac;
208:
209: // CCR
210: bool str;
211: bool cnt;
212: bool hlt;
213: bool sab;
214: bool int_enable;
215: uint8 GetCCR() const;
216: void SetCCR(uint8);
217:
218: uint16 mtc;
219: uint32 mar;
220: uint32 dar;
221: uint16 btc;
222: uint32 bar;
223: uint8 niv;
224: uint8 eiv;
225: uint8 mfc;
226: uint8 cpr;
227: uint8 dfc;
228: uint8 bfc;
229: void SetNIV(uint8);
230: void SetEIV(uint8);
231: void SetMFC(uint8);
232: void SetCPR(uint8);
233: void SetDFC(uint8);
234: void SetBFC(uint8);
235:
236: // 転送シーケンス
237: std::vector<int> seq {};
238: int seq_index {};
239:
240: // 転送リトライカウンタ。
241: // 実際には (SPC からの) DTACK を待つのだが、
242: // 待つのは大変なのでこちらでポーリングしている。
243: int retry {};
244:
245: // 転送中データ
246: FixedQueue<uint8, 2> data;
1.1 root 247: };
248:
1.1.1.8 root 249: class DMACDevice : public IODevice
1.1 root 250: {
1.1.1.3 root 251: using inherited = IODevice;
1.1 root 252:
253: static const int baseaddr = 0xe84000;
254:
1.1.1.11 root 255: // 転送シーケンス
256: enum {
257: NOP = 0,
258: RD_M8,
259: RD_M16,
260: RD_D8,
261: RD_D16,
262: WR_M8,
263: WR_M16,
264: WR_D8,
265: WR_D16,
266: };
267:
1.1 root 268: public:
269: DMACDevice();
1.1.1.6 root 270: virtual ~DMACDevice() override;
1.1 root 271:
1.1.1.12! root 272: bool Init() override;
1.1.1.10 root 273: void ResetHard(bool poweron) override;
1.1.1.2 root 274:
1.1.1.11 root 275: uint64 Read8(uint32 addr) override;
276: uint64 Read16(uint32 addr) override;
277: uint64 Write8(uint32 addr, uint32 data) override;
278: uint64 Write16(uint32 addr, uint32 data) override;
279: uint64 Peek8(uint32 addr) override;
280:
281: // 外部デバイスが REQ 信号を操作する
282: void AssertREQ(int ch);
283: void NegateREQ(int ch);
1.1.1.2 root 284:
1.1.1.6 root 285: // 割り込みアクノリッジ
286: int InterruptAcknowledge();
287:
1.1.1.3 root 288: protected:
289: // BusIO インタフェース
290: static const uint NPORT = 256;
1.1.1.7 root 291: uint64 Read(uint32 offset);
292: uint64 Write(uint32 offset, uint32 data);
293: uint64 Peek(uint32 offset);
1.1.1.3 root 294:
1.1 root 295: private:
1.1.1.8 root 296: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
1.1.1.10 root 297:
1.1.1.4 root 298: void MonitorReg4(TextScreen&,
299: int x, int y, uint32 reg, const char * const *names);
1.1 root 300:
1.1.1.11 root 301: // チャンネル操作
302: void WriteCSR(DMACChan *chan, uint32 data);
303: void WriteCCR(DMACChan *chan, uint32 data, uint8 up);
304: void WriteGCR(uint8 data);
305:
1.1.1.6 root 306: // 割り込み信号線の状態を変更
307: void ChangeInterrupt();
308:
1.1.1.11 root 309: // 転送
310: void StartTransfer(DMACChan *chan);
311: void AbortTransfer(DMACChan *chan);
312: DMACChan *SelectChannel();
313:
1.1.1.10 root 314: // 転送イベントコールバック
315: void StartCallback(Event& ev);
1.1.1.11 root 316: void TransferCallback(Event& ev);
1.1.1.10 root 317:
318: // 転送中エラー
1.1.1.11 root 319: void TransferError(DMACChan *, int op, uint64);
1.1.1.10 root 320:
1.1.1.11 root 321: // エラー発生
322: void Error(DMACChan *chan, uint8 errcode);
1.1.1.10 root 323:
1.1.1.11 root 324: void AssertACK(DMACChan *);
325: void NegateACK(DMACChan *);
1.1.1.10 root 326:
1.1.1.11 root 327: // レジスタ
328: std::array<DMACChan, 4> channel {};
329: uint8 gcr;
330:
1.1.1.12! root 331: ADPCMDevice *adpcm {};
! 332: FDCDevice *fdc {};
! 333: InterruptDevice *interrupt {};
! 334: MainbusDevice *mainbus {};
! 335:
1.1.1.11 root 336: Event event { this };
1.1.1.2 root 337:
1.1.1.8 root 338: Monitor monitor { this };
339:
1.1.1.2 root 340: static const char * const errnames[];
1.1 root 341: };
1.1.1.2 root 342:
1.1.1.12! root 343: static inline DMACDevice *GetDMACDevice() {
! 344: return Object::GetObject<DMACDevice>(OBJ_DMAC);
! 345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.