|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #pragma once
8:
9: #include "device.h"
10: #include "fixedqueue.h"
1.1.1.4 root 11: #include "scheduler.h"
12: #include "scsidev.h"
1.1.1.3 root 13: #include "vm.h"
1.1 root 14:
15: struct SPC
16: {
17: static const int BDID = 0x0; // $E96021 RW $E100_0000
18: static const int SCTL = 0x1; // $E96023 RW $E100_0004
19: static const int SCMD = 0x2; // $E96025 RW $E100_0008
20: static const int TMOD = 0x3; // (MB89352 にはない)
21: static const int INTS = 0x4; // $E96029 RW $E100_0010
22: static const int PSNS = 0x5; // $E9602B R- $E100_0014
23: static const int SDGC = 0x5; // $E9602B -W $E100_0014
24: static const int SSTS = 0x6; // $E9602D R- $E100_0018
25: static const int SERR = 0x7; // $E9602F R- $E100_001C
26: static const int PCTL = 0x8; // $E96031 RW $E100_0020
27: static const int MBC = 0x9; // $E96033 R- $E100_0024
28: static const int DREG = 0xa; // $E96035 RW $E100_0028
29: static const int TEMP = 0xb; // $E96037 RW $E100_002C
30: static const int TCH = 0xc; // $E96039 RW $E100_0030
31: static const int TCM = 0xd; // $E9603B RW $E100_0034
32: static const int TCL = 0xe; // $E9603D RW $E100_0038
33: static const int EXBF = 0xf; // (MB89352 にはない)
34:
35:
36: // SCTL レジスタ
37: // 全ビットを保持。
38: uint8 sctl;
39: static const int SCTL_RESET = 0x80; // Reset & Disable
40: static const int SCTL_CTL_RESET = 0x40; // Control Reset
41: static const int SCTL_DIAG_MODE = 0x20; // Diag Mode
42: static const int SCTL_ARBIT_EN = 0x10; // Arbitration Enable
43: static const int SCTL_PARITY_EN = 0x08; // Parity Enable
44: static const int SCTL_SEL_EN = 0x04; // Select Enable
45: static const int SCTL_RESEL_EN = 0x02; // Reselect Enable
46: static const int SCTL_INTR_EN = 0x01; // Interrupt Enable
47:
48: // SCMD レジスタ
1.1.1.2 root 49: // 全ビットを保持。
1.1 root 50: uint8 scmd;
51: static const int SCMD_CMD_MASK = 0xe0; // Command code
52: static const int SCMD_RST_OUT = 0x10; // RST Out
53: static const int SCMD_INTERCEPT = 0x08; // Intersept Transfer
54: static const int SCMD_PROGRAM = 0x04; // Program Transfer
55: static const int SCMD_TERM_MODE = 0x01; // Termination Mode
56:
57: // INTS レジスタ
58: // 全ビットを保持。
59: uint8 ints;
60: static const int INTS_SELECTED = 0x80; // Selected
61: static const int INTS_RESELECTED = 0x40; // Reselected
62: static const int INTS_DISCONNECTED = 0x20; // Disconnected
63: static const int INTS_COMPLETE = 0x10; // Command Complete
64: static const int INTS_SERV_REQ = 0x08; // Service Required
65: static const int INTS_TIMEOUT = 0x04; // Time Out
66: static const int INTS_HARD_ERR = 0x02; // SPC Hard Error
67: static const int INTS_RESET_COND = 0x01; // Reset Condition
68:
69: // PSNS レジスタ
70: uint8 psns;
71: static const int PSNS_REQ = 0x80;
72: static const int PSNS_ACK = 0x40;
73: static const int PSNS_ATN = 0x20;
74: static const int PSNS_SEL = 0x10;
75: static const int PSNS_BSY = 0x08;
76: static const int PSNS_MSG = 0x04;
77: static const int PSNS_CD = 0x02;
78: static const int PSNS_IO = 0x01;
79:
80: // SDGC レジスタ
81: uint8 sdgc;
82: static const int SDGC_XFER_ENABLE = 0x20;
83:
84: // SSTS レジスタ
85: // 上位4ビットを保持。下位4ビットは読み出し時に生成。
86: uint8 ssts;
87: static const int SSTS_CONN_INIT = 0x80; // Connected (Initiator)
88: static const int SSTS_CONN_TARG = 0x40; // Connected (Target)
89: static const int SSTS_SPC_BUSY = 0x20; // SPC Busy
90: static const int SSTS_IN_PROGRESS = 0x10; // Transfer in Progress
91: static const int SSTS_RST_IN = 0x08; // SCSI RST In
92: static const int SSTS_TC_ZERO = 0x04; // TC=0
93: static const int SSTS_DREG_FULL = 0x02; // DREG Status (Full)
94: static const int SSTS_DREG_EMPTY = 0x01; // DREG Status (Empty)
95:
96: // SERR レジスタ
97: uint8 serr;
98: static const int SERR_DATAERR_SCSI = 0x80; // Data Error: SCSI
99: static const int SERR_DATAERR_SPC = 0x40; // Data Error: SPC
100: static const int SERR_XFER_OUT = 0x20; // Xfer Out
101: static const int SERR_TC_PARITY_ERR = 0x08; // TC Parity Error
102: static const int SERR_SHORT_XFER = 0x02; // Short Transfer Period
103:
104: // PCTL レジスタ
105: // ここでは BusFree INT Enable ビットだけを保持。
106: // 残りの MSG, C/D, I/O は親クラスの信号線フラグから生成。
107: bool busfree_intr_enable;
108: static const int PCTL_MASK = 0x87; // 書き込みマスク
109: static const int PCTL_BFINT_EN = 0x80; // BusFree INT Enable
110: static const int PCTL_MSG = 0x04;
111: static const int PCTL_CD = 0x02;
112: static const int PCTL_IO = 0x01;
113:
114: FixedQueue<uint8, 8> dreg; // DREG レジスタ
115:
116: uint8 temp_in; // TEMP レジスタ (SCSI -> MPU)
117: uint8 temp_out; // TEMP レジスタ (MPU -> SCSI)
118: uint32 tc; // TC
119:
120: uint32 GetTCL() const { return tc & 0x0000ff; } // TCL
121:
122: // MBC (内部の読み込み専用レジスタ)
123: // TC の下位4ビットが読めるらしい
124: uint8 mbc() const {
125: return tc & 15;
126: }
127: };
128:
129: class SPCDevice : public SCSIHostDevice
130: {
1.1.1.4 root 131: using inherited = SCSIHostDevice;
1.1 root 132: public:
1.1.1.3 root 133: SPCDevice();
1.1.1.4 root 134: ~SPCDevice() override;
1.1 root 135:
1.1.1.4 root 136: bool Init() override;
137: void ResetHard() override;
138: void ResetSoft() override;
1.1 root 139:
1.1.1.5 root 140: void MonitorUpdate(TextScreen&) override;
1.1 root 141:
1.1.1.2 root 142: // SCSIBus コールバック
143:
144: // バスフリーになった (全員に通知される)
1.1.1.4 root 145: void BusFreeCB(int id) override;
1.1 root 146:
1.1.1.2 root 147: // ターゲットがセレクションに応答した (イニシエータのみ通知される)
1.1.1.4 root 148: void SelectionAckCB() override;
1.1.1.2 root 149:
150: // 情報転送フェーズで REQ を立てた (イニシエータのみ通知される)
1.1.1.4 root 151: void TransferReqCB() override;
1.1 root 152:
1.1.1.3 root 153: protected:
154: // BusIO インタフェース
155: static const uint32 NPORT = 16;
156: uint64 Read(uint32 addr);
157: uint64 Write(uint32 addr, uint32 data);
158: uint64 Peek(uint32 addr);
159:
1.1 root 160: private:
1.1.1.4 root 161: void Reset();
162:
1.1.1.5 root 163: void MonitorReg(TextScreen&,
164: int x, int y, uint32 reg, const char * const *names);
1.1 root 165:
166: // SCTL レジスタへの書き込み
167: void WriteSCTL(uint32);
168:
169: // SCMD レジスタへの書き込み
170: void WriteSCMD(uint32);
171:
172: // INTS レジスタへの書き込み
173: void WriteINTS(uint32);
1.1.1.3 root 174: // 表示のための前回値
175: uint32 prev_ints {};
1.1 root 176:
177: // INTS 設定
178: void SetINTS(uint32);
179:
180: // PSNS レジスタ値の取得
181: uint32 GetPSNS() const;
182:
183: // SSTS レジスタ値の取得
184: uint32 GetSSTS() const;
1.1.1.3 root 185: // 表示のための前回値
186: uint32 prev_ssts {};
1.1 root 187:
188: // PCTL レジスタ値の取得
189: uint32 GetPCTL() const;
190:
1.1.1.3 root 191: // DREG レジスタアクセス
192: uint64 ReadDREG();
193: uint64 WriteDREG(uint32 data);
194:
1.1 root 195: // バスフリーフェーズに移行する
196: void BusFree();
1.1.1.2 root 197: // 直近のバスフリーフェーズになった時刻
198: // (アービトレーション/セレクション開始時に使う)
199: uint64 last_busfree_time {};
200: // バスをリリースする
201: void BusRelease();
1.1 root 202:
203: // Select コマンド実行
204: void SelectCommand();
1.1.1.6 ! root 205: void Arbitration1(Event& ev);
! 206: void Arbitration2(Event& ev);
! 207: void Selection1(Event& ev);
! 208: void SelectionTimeout(Event& ev);
1.1.1.2 root 209:
210: // SetATN コマンド実行
211: void SetATNCommand();
212: // セレクションフェーズで ATN を立てる
1.1.1.6 ! root 213: bool set_atn_in_selection {};
1.1 root 214:
215: // Transfer コマンド実行
216: void TransferCommand();
1.1.1.6 ! root 217: void TransferCommandStart(Event& ev);
! 218: void HardwareTransfer(Event& ev);
1.1.1.3 root 219: void TransferComplete();
1.1.1.2 root 220: // Transfer コマンド実行中なら true
1.1.1.6 ! root 221: bool transfer_command_running {};
1.1 root 222:
223: // SCSI コマンド
224: void ExecCommand();
225:
226: // レジスタ
227: struct SPC spc {};
228:
1.1.1.3 root 229: // VM 種別
230: vmtype_t vmtype {};
1.1 root 231:
232: // SPC に入力されるクロック周期 [nsec]
1.1.1.6 ! root 233: int t_CLF {};
! 234:
! 235: // アクセスウェイト
! 236: uint32 read_wait {};
! 237: uint32 write_wait {};
! 238:
! 239: // 接続中のデバイス(イニシエータ含む)を ID 順に並べたリスト (モニタ用)
! 240: std::vector<SCSIDevice*> connected_devices {};
1.1 root 241:
242: // イベント
243: Event event {};
1.1.1.2 root 244: Event event_tc {};
1.1 root 245: };
246:
1.1.1.3 root 247: extern std::unique_ptr<SPCDevice> gSPC;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.