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