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