|
|
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.13 root 14: #include "bus.h"
1.1.1.14 root 15: #include "event.h"
1.1.1.11 root 16: #include "fixedqueue.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 cpr;
1.1.1.13 root 226: busaddr mfc;
227: busaddr dfc;
228: busaddr bfc;
1.1.1.11 root 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: // 転送シーケンス
1.1.1.14 root 237: std::vector<uint> seq {};
1.1.1.11 root 238: int seq_index {};
239:
240: // 転送リトライカウンタ。
241: // 実際には (SPC からの) DTACK を待つのだが、
242: // 待つのは大変なのでこちらでポーリングしている。
1.1.1.14 root 243: uint retry {};
1.1.1.11 root 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:
1.1.1.14 root 253: static const uint32 baseaddr = 0xe84000;
1.1 root 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,
1.1.1.14 root 266: SEQ_MAX,
1.1.1.11 root 267: };
268:
1.1 root 269: public:
270: DMACDevice();
1.1.1.13 root 271: ~DMACDevice() override;
1.1 root 272:
1.1.1.12 root 273: bool Init() override;
1.1.1.10 root 274: void ResetHard(bool poweron) override;
1.1.1.2 root 275:
1.1.1.14 root 276: busdata Read(busaddr addr) override;
277: busdata Write(busaddr addr, uint32 data) override;
278: busdata Peek1(uint32 addr) override;
1.1.1.11 root 279:
280: // 外部デバイスが REQ 信号を操作する
1.1.1.14 root 281: void AssertREQ(uint ch);
282: void NegateREQ(uint ch);
1.1.1.2 root 283:
1.1.1.6 root 284: // 割り込みアクノリッジ
1.1.1.13 root 285: busdata InterruptAcknowledge();
1.1.1.6 root 286:
1.1.1.13 root 287: // ユーザ空間制御
288: void SetUdevice(uint32 start, uint32 end, bool accessible);
1.1.1.3 root 289:
1.1 root 290: private:
1.1.1.8 root 291: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
1.1.1.10 root 292:
1.1.1.4 root 293: void MonitorReg4(TextScreen&,
294: int x, int y, uint32 reg, const char * const *names);
1.1 root 295:
1.1.1.14 root 296: busdata WriteByte(DMACChan *chan, uint32 n, uint32 data);
297: busdata WriteWord(DMACChan *chan, uint32 n, uint32 data);
298:
1.1.1.11 root 299: // チャンネル操作
300: void WriteCSR(DMACChan *chan, uint32 data);
301: void WriteCCR(DMACChan *chan, uint32 data, uint8 up);
302: void WriteGCR(uint8 data);
303:
1.1.1.6 root 304: // 割り込み信号線の状態を変更
305: void ChangeInterrupt();
306:
1.1.1.11 root 307: // 転送
308: void StartTransfer(DMACChan *chan);
309: void AbortTransfer(DMACChan *chan);
310: DMACChan *SelectChannel();
311:
1.1.1.10 root 312: // 転送イベントコールバック
313: void StartCallback(Event& ev);
1.1.1.11 root 314: void TransferCallback(Event& ev);
1.1.1.10 root 315:
1.1.1.13 root 316: // ログ出力
1.1.1.14 root 317: void TransferLog(DMACChan *, uint op, busaddr addr, busdata r, uint64 data);
1.1.1.13 root 318:
1.1.1.10 root 319: // 転送中エラー
1.1.1.14 root 320: void TransferError(DMACChan *, uint op, busdata r, uint32 data);
1.1.1.10 root 321:
1.1.1.11 root 322: // エラー発生
323: void Error(DMACChan *chan, uint8 errcode);
1.1.1.10 root 324:
1.1.1.11 root 325: void AssertACK(DMACChan *);
326: void NegateACK(DMACChan *);
1.1.1.10 root 327:
1.1.1.11 root 328: // レジスタ
329: std::array<DMACChan, 4> channel {};
330: uint8 gcr;
331:
1.1.1.13 root 332: // ユーザ空間制御
333: std::array<bool, 2048> useraccess {};
334:
1.1.1.12 root 335: ADPCMDevice *adpcm {};
336: FDCDevice *fdc {};
337: InterruptDevice *interrupt {};
338: MainbusDevice *mainbus {};
339:
1.1.1.11 root 340: Event event { this };
1.1.1.2 root 341:
1.1.1.15! root 342: Monitor *monitor {};
1.1.1.8 root 343:
1.1.1.2 root 344: static const char * const errnames[];
1.1.1.14 root 345: static const char * const regname1[0x40];
346: static const char * const regname2[0x20];
347: static const char * const seqname[SEQ_MAX];
1.1 root 348: };
1.1.1.2 root 349:
1.1.1.12 root 350: static inline DMACDevice *GetDMACDevice() {
351: return Object::GetObject<DMACDevice>(OBJ_DMAC);
352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.