|
|
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.11 root 15: #include "fixedqueue.h"
1.1.1.9 root 16: #include <array>
1.1 root 17:
1.1.1.12 root 18: class ADPCMDevice;
19: class FDCDevice;
20: class InterruptDevice;
21: class MainbusDevice;
1.1.1.16 root 22: class Syncer;
1.1.1.12 root 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
1.1.1.18 root 108: static const uint32 CHAIN_DISABLED = 0; // Chain operation is disabled
109: static const uint32 CHAIN_reserved = 1; // (Undefined, reserved)
1.1.1.11 root 110: static const uint32 CHAIN_ARRAY = 2; // Array Chaining
1.1.1.18 root 111: static const uint32 CHAIN_LINKARRAY = 3; // Linked Array Chaining
1.1.1.11 root 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: // 各チャンネル
1.1.1.18 root 149: class DMACChan : public Device
1.1.1.11 root 150: {
1.1.1.18 root 151: using inherited = Device;
1.1.1.11 root 152: public:
1.1.1.18 root 153: DMACChan(int ch_, const char *desc_);
154: ~DMACChan() override;
155:
1.1.1.11 root 156: // 二次変数など
157: int ch; // チャンネル番号
158: const char *desc; // チャンネルの用途(モニタ表示用)
159: uint8 priority; // 現在の実効プライオリティ
160: bool req; // REQ#n 信号
161:
162: // レジスタ
163:
164: // CSR
165: uint8 csr; // COC,BTC,NDT,ERR を保持
166: bool active; // ACT
167: bool pcl_pin; // PCL 信号線の状態 (High が true)
168: bool pcl_prev; // 前回の PCL の状態 (High が true)
169: uint8 GetCSR() const;
170: bool IsINTR() const { // CSR の割り込み要因が立っていれば true
171: // XXX PCT は未対応
172: return csr;
173: }
174:
175: uint8 cer;
176:
177: // DCR
178: uint xrm;
179: uint dtyp;
180: uint dps;
181: uint dcr_pcl;
182: uint8 GetDCR() const;
183: void SetDCR(uint8);
184: uint GetXRM() const { return xrm; }
185: uint GetDTYP() const { return dtyp; }
186: uint GetDPS() const { return dps; }
187: uint GetPCL() const { return dcr_pcl; }
188:
189: // OCR
190: uint dir;
191: uint size;
192: uint chain;
193: uint reqg;
194: uint8 GetOCR() const;
195: void SetOCR(uint8);
196: uint32 GetDIR() const { return dir; }
197: uint32 GetSIZE() const { return size; }
198: uint32 GetCHAIN() const { return chain; }
199: uint32 GetREQG() const { return reqg; }
200: bool IsChain() const { return GetCHAIN() & 0x02; }
201: bool IsSingleAddress() const { return GetREQG() & 0x02; }
202:
203: // SCR
204: // XXX 名前が衝突してるのは後からなんとかする
205: uint scr_mac;
206: uint scr_dac;
207: uint8 GetSCR() const;
208: void SetSCR(uint8);
209: uint32 GetMAC() const { return scr_mac; }
210: uint32 GetDAC() const { return scr_dac; }
211: int mac;
212: int dac;
213:
214: // CCR
215: bool str;
216: bool cnt;
217: bool hlt;
218: bool sab;
219: bool int_enable;
220: uint8 GetCCR() const;
221: void SetCCR(uint8);
222:
223: uint16 mtc;
224: uint32 mar;
225: uint32 dar;
226: uint16 btc;
227: uint32 bar;
228: uint8 niv;
229: uint8 eiv;
230: uint8 cpr;
1.1.1.13 root 231: busaddr mfc;
232: busaddr dfc;
233: busaddr bfc;
1.1.1.11 root 234: void SetNIV(uint8);
235: void SetEIV(uint8);
236: void SetMFC(uint8);
237: void SetCPR(uint8);
238: void SetDFC(uint8);
239: void SetBFC(uint8);
240:
241: // 転送シーケンス
1.1.1.14 root 242: std::vector<uint> seq {};
1.1.1.11 root 243: int seq_index {};
244:
245: // 転送リトライカウンタ。
246: // 実際には (SPC からの) DTACK を待つのだが、
247: // 待つのは大変なのでこちらでポーリングしている。
1.1.1.14 root 248: uint retry {};
1.1.1.11 root 249:
250: // 転送中データ
251: FixedQueue<uint8, 2> data;
1.1 root 252: };
253:
1.1.1.8 root 254: class DMACDevice : public IODevice
1.1 root 255: {
1.1.1.3 root 256: using inherited = IODevice;
1.1 root 257:
1.1.1.14 root 258: static const uint32 baseaddr = 0xe84000;
1.1 root 259:
1.1.1.11 root 260: // 転送シーケンス
261: enum {
262: NOP = 0,
263: RD_M8,
264: RD_M16,
265: RD_D8,
266: RD_D16,
267: WR_M8,
268: WR_M16,
269: WR_D8,
270: WR_D16,
1.1.1.14 root 271: SEQ_MAX,
1.1.1.11 root 272: };
273:
1.1 root 274: public:
275: DMACDevice();
1.1.1.13 root 276: ~DMACDevice() override;
1.1 root 277:
1.1.1.12 root 278: bool Init() override;
1.1.1.10 root 279: void ResetHard(bool poweron) override;
1.1.1.2 root 280:
1.1.1.14 root 281: busdata Read(busaddr addr) override;
282: busdata Write(busaddr addr, uint32 data) override;
283: busdata Peek1(uint32 addr) override;
1.1.1.11 root 284:
285: // 外部デバイスが REQ 信号を操作する
1.1.1.14 root 286: void AssertREQ(uint ch);
287: void NegateREQ(uint ch);
1.1.1.2 root 288:
1.1.1.6 root 289: // 割り込みアクノリッジ
1.1.1.13 root 290: busdata InterruptAcknowledge();
1.1.1.6 root 291:
1.1.1.13 root 292: // ユーザ空間制御
293: void SetUdevice(uint32 start, uint32 end, bool accessible);
1.1.1.3 root 294:
1.1 root 295: private:
1.1.1.19! root 296: DECLARE_MONITOR_SCREEN(MonitorScreen);
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.14 root 301: busdata WriteByte(DMACChan *chan, uint32 n, uint32 data);
302: busdata WriteWord(DMACChan *chan, uint32 n, uint32 data);
303:
1.1.1.11 root 304: // チャンネル操作
305: void WriteCSR(DMACChan *chan, uint32 data);
306: void WriteCCR(DMACChan *chan, uint32 data, uint8 up);
307: void WriteGCR(uint8 data);
308:
1.1.1.16 root 309: // ACT ビットの状態を変更
310: void ChangeACT(DMACChan *, bool);
311:
1.1.1.6 root 312: // 割り込み信号線の状態を変更
313: void ChangeInterrupt();
314:
1.1.1.11 root 315: // 転送
316: void StartTransfer(DMACChan *chan);
317: void AbortTransfer(DMACChan *chan);
1.1.1.18 root 318: std::string MakeStartLog(DMACChan *chan);
319: bool LoadLinkArray(DMACChan *chan);
1.1.1.11 root 320: DMACChan *SelectChannel();
321:
1.1.1.10 root 322: // 転送イベントコールバック
1.1.1.17 root 323: void StartCallback(Event *);
324: void TransferCallback(Event *);
1.1.1.10 root 325:
1.1.1.13 root 326: // ログ出力
1.1.1.14 root 327: void TransferLog(DMACChan *, uint op, busaddr addr, busdata r, uint64 data);
1.1.1.13 root 328:
1.1.1.10 root 329: // 転送中エラー
1.1.1.14 root 330: void TransferError(DMACChan *, uint op, busdata r, uint32 data);
1.1.1.10 root 331:
1.1.1.11 root 332: // エラー発生
333: void Error(DMACChan *chan, uint8 errcode);
1.1.1.10 root 334:
1.1.1.11 root 335: void AssertACK(DMACChan *);
336: void NegateACK(DMACChan *);
1.1.1.10 root 337:
1.1.1.18 root 338: // メインメモリアクセス
339: busdata ReadMem(busaddr addr);
340: busdata ReadMem4(busaddr addr);
341: busdata WriteMem(busaddr addr, uint32 data);
342:
1.1.1.11 root 343: // レジスタ
1.1.1.18 root 344: std::array<std::unique_ptr<DMACChan>, 4> channels {};
1.1.1.11 root 345: uint8 gcr;
346:
1.1.1.13 root 347: // ユーザ空間制御
348: std::array<bool, 2048> useraccess {};
349:
1.1.1.12 root 350: ADPCMDevice *adpcm {};
351: FDCDevice *fdc {};
352: InterruptDevice *interrupt {};
353: MainbusDevice *mainbus {};
1.1.1.16 root 354: Syncer *syncer {};
1.1.1.12 root 355:
1.1.1.17 root 356: Event *event {};
1.1.1.2 root 357:
1.1.1.15 root 358: Monitor *monitor {};
1.1.1.8 root 359:
1.1.1.2 root 360: static const char * const errnames[];
1.1.1.14 root 361: static const char * const regname1[0x40];
362: static const char * const regname2[0x20];
363: static const char * const seqname[SEQ_MAX];
1.1 root 364: };
1.1.1.2 root 365:
1.1.1.19! root 366: inline DMACDevice *GetDMACDevice() {
1.1.1.12 root 367: return Object::GetObject<DMACDevice>(OBJ_DMAC);
368: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.