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