|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2018 [email protected]
4: //
5:
6: #pragma once
7:
8: #include "device.h"
9:
10: class SCSI
11: {
12: public:
13: // デバイス種別
14: enum DevType {
15: None = 0,
16: HD = 1,
17: };
18:
19: // フェーズは、バスフェーズと転送フェーズを一緒くたで扱う。
20: // 0から7までは転送フェーズを表しているのでこの順序を守ること。
21: // 8以上はバスフェーズを表している。
22: struct Phase { // MSG CD IO
23: static const uint DataOut = 0x00; // 0 0 0
24: static const uint DataIn = 0x01; // 0 0 1
25: static const uint Command = 0x02; // 0 1 0
26: static const uint Status = 0x03; // 0 1 1
27: static const uint MsgOut = 0x06; // 1 1 0
28: static const uint MsgIn = 0x07; // 1 1 1
29:
30: static const uint BusFree = 8;
31: static const uint Arbitration = 9;
32: static const uint Selection = 10;
33: static const uint Reselection = 11;
34:
35: static const uint MAX = 12; // 最大値 +1 にすること
36: };
37:
38: // コマンド。
39: // ダイレクトアクセスデバイスのコマンドを元にしている。
40: // シーケンシャルアクセスデバイスでは 0x01 が Rewind だったり
41: // 同じコードで違うコマンドのようだが、とりあえずそれは放置。
42: struct Command {
43: // Group0
44: static const uint TestUnitReady = 0x00; // 共通
45: static const uint RezeroUnit = 0x01;
46: static const uint RequestSense = 0x03; // 共通
47: static const uint FormatUnit = 0x04;
48: static const uint ReassignBlocks = 0x07;
49: static const uint Read6 = 0x08;
50: static const uint Write6 = 0x0a;
51: static const uint Seek6 = 0x0b;
52: static const uint Inquiry = 0x12; // 共通
53: static const uint ModeSelect6 = 0x15; // 共通
54: static const uint Reserve = 0x16;
55: static const uint Release = 0x17;
56: static const uint Copy = 0x18; // 共通
57: static const uint ModeSense6 = 0x1a;
58: static const uint StartStopUnit = 0x1b;
59: static const uint ReceiveDiagnosticResults = 0x1c; // 共通
60: static const uint SendDiagnostic = 0x1d; // 共通
61: static const uint PreventAllowMediumRemoval = 0x1e;
62: // Group1
63: static const uint ReadCapacity = 0x25;
64: static const uint Read10 = 0x28;
65: static const uint Write10 = 0x2a;
66: static const uint Seek10 = 0x2b;
67: // Group1
68: static const uint WriteAndVerify10 = 0x2e;
69: static const uint Verify10 = 0x2f;
70: static const uint SearchDataHigh10 = 0x30;
71: static const uint SearchDataEqual10 = 0x31;
72: static const uint SearchDataLow10 = 0x32;
73: static const uint SetLimits = 0x33;
74: static const uint PreFetch = 0x34;
75: static const uint SynchronizeCache = 0x35;
76: static const uint LockUnlockCache = 0x36;
77: static const uint ReadDefectData10 = 0x37;
78: static const uint Compare = 0x39; // 共通
79: static const uint CopyAndVerify = 0x3a; // 共通
80: static const uint WriteBuffer = 0x3b; // 共通
81: static const uint ReadBuffer = 0x3c; // 共通
82: static const uint ReadLong = 0x3e;
83: static const uint WriteLong = 0x3f;
84: // Group2
85: static const uint ChangeDefinition = 0x40;
86: static const uint WriteSame = 0x41;
87: static const uint LogSelect = 0x4c; // 共通
88: static const uint LogSense = 0x4d; // 共通
89: static const uint ModeSelect10 = 0x55; // 共通
90: static const uint ModeSense10 = 0x5a; // 共通
91: static const uint MAX = 0x5b; // 最大値+1にすること
92: };
93:
94: // ステータスバイト
95: struct StatusByte {
96: static const uint8 Good = (0x00 << 1);
97: static const uint8 CheckCondition = (0x01 << 1);
98: static const uint8 ConditionMet = (0x02 << 1);
99: static const uint8 Busy = (0x04 << 1);
100: static const uint8 Intermediate = (0x08 << 1);
101: static const uint8 IntermediateCondMet = (0x0a << 1);
102: static const uint8 ReservationConflict = (0x0c << 1);
103: static const uint8 CommandTerminated = (0x11 << 1);
104: static const uint8 QueueFull = (0x14 << 1);
105: };
106:
107: // メッセージバイト
108: struct MsgByte {
109: static const uint8 CommandComplete = 0x00;
110: static const uint8 ExtendMessage = 0x01;
111: static const uint8 SaveDataPointer = 0x02;
112: static const uint8 RestorePointers = 0x03;
113: static const uint8 Disconnect = 0x04;
114: static const uint8 InitiatorDetectedError = 0x05;
115: static const uint8 Abort = 0x06;
116: static const uint8 MessageReject = 0x07;
117: static const uint8 NoOperation = 0x08;
118: static const uint8 MessageParityError = 0x09;
119: static const uint8 LinkedCommandComplete = 0x0a;
120: static const uint8 LinkedCommandCompleteWithFlag = 0x0b;
121: static const uint8 BusDeviceReset = 0x0c;
122: static const uint8 AbortTag = 0x0d;
123: static const uint8 ClearQueue = 0x0e;
124: static const uint8 InitiateRecovery = 0x0f;
125: static const uint8 ReleaseRecovery = 0x10;
126: static const uint8 TerminateIOProcess = 0x11;
127: static const uint8 SimpleQueueTag = 0x20;
128: static const uint8 HeadOfQueueTag = 0x21;
129: static const uint8 OrderedQueueTag = 0x22;
130: static const uint8 IgnoreWideResidue = 0x23;
131: static const uint8 Identify = 0x80; // 0x80..0xff
132: };
133:
134: // Mode Select(6) ヘッダ
135: struct ModeParamHdr {
136: uint8 mode_param_len; // ヘッダ以降のバイト数
137: uint8 media_type;
138: uint8 device_specific_param;
139: uint8 block_desc_len; // 0 か 8の倍数
140: } __packed;
141:
142: // Mode Select(6) ブロックディスクリプタ
143: struct BlockDesc {
144: uint8 density_code;
145: uint8 block_cnt[3]; // ブロック数
146: uint8 reserved;
147: uint8 block_size[3]; // 論理ブロック長 (バイト)
148: } __packed;
149:
150: // フェーズ名を返す。
151: static const char *GetPhaseName(uint);
152:
153: // SCSI コマンド名を返す。
154: static const char *GetCommandName(uint8);
155:
156: private:
157: static const char * const phasename[Phase::MAX];
158: static const char * const commandname[Command::MAX];
159: };
160:
161: class SCSIHostDevice : public IODevice
162: {
163: typedef IODevice inherited;
164: public:
165: SCSIHostDevice();
166: virtual ~SCSIHostDevice();
167:
168: virtual bool Create();
169:
170: // このホストデバイスを示す接頭語を取得する
171: const char *GetConfigName() const { return config_name; }
172:
173: // ログ識別子を取得する
174: const std::string& GetLogName() const { return logname; }
175:
176: // 自身の SCSI ID (0..7)
177: int myid = 0;
178:
179: // SCSI ターゲット。[0] が ID0, …
180: // 未接続とイニシエータは NULL。
181: SCSITarget *target[8] {};
182:
183: // Select されているターゲット ID
184: // 選択されていない状態では -1
185: int tgtid = 0;
186:
187: // Bus Phase
188:
189: // バスフェーズが変化した時刻
190: uint64 BusPhaseTime = 0;
191:
192: // 各バスフェーズへ遷移する
193: void B_BusFree(int id);
194:
195: bool Arbitration(int id);
196: bool ArbitrationAck(int id);
197:
198: void InitiatorSelection(int targetid);
199: void TargetSelectionAck(int targetid);
200: void InitiatorSelectionAck();
201:
202: void TargetReselection(int targetid, int initiatorID);
203: void InitiatorReselectionAck();
204: void TargetReselectionAck(int targetid);
205: void InitiatorReselectionAck2();
206:
207: #if 0
208: // Xfer Phase
209: SCSI::XferPhase GetXferPhase() const { return xfer_phase; }
210:
211: // 各転送フェーズへ遷移する
212: void X_DataOut();
213: void X_DataIn();
214: void X_Command();
215: void X_Status();
216: void X_MsgOut();
217: void X_MsgIn();
218: #endif
219:
220: uint8 DATA = 0;
221: uint8 GetDATA() const { return DATA; }
222: void SetDATA(uint8 data);
223:
224: // 信号線はいずれも true でアサート
225: bool REQ = false; // REQ 信号
226: bool GetREQ() const { return REQ; }
227: void SetREQ(bool val);
228:
229: bool ACK = false; // ACK 信号
230: bool GetACK() const { return ACK; }
231: void SetACK(bool val);
232:
233: // RST も本来は OR-tied だが、ここではあまり意味がないので bool にする。
234: bool RST = false; // RST 信号
235: bool GetRST() const { return RST; }
236: void SetRST(bool val);
237:
238: uint8 SEL = false; // SEL 信号
239: bool GetSEL() const { return SEL != 0; }
240: void AssertSEL(int id);
241: void NegateSEL(int id);
242:
243: uint8 BSY = false; // BSY 信号
244: bool GetBSY() const { return BSY != 0; }
245: void AssertBSY(int id);
246: void NegateBSY(int id);
247:
248: bool MSG = false; // MSG 信号
249: bool GetMSG() const { return MSG; }
250: void SetMSG(bool val);
251:
252: bool CD = false; // CD 信号
253: bool GetCD() const { return CD; }
254: void SetCD(bool val);
255:
256: bool IO = false; // IO 信号
257: bool GetIO() const { return IO; }
258: void SetIO(bool val);
259:
260: bool ATN = false; // ATN 信号
261: bool GetATN() const { return ATN; }
262: void SetATN(bool val);
263:
264: // バスフリーフェーズなら true を返す
265: bool IsBusFree() const {
266: return (GetSEL() == false && GetBSY() == false);
267: }
268:
269: // ターゲットがバスフリーフェーズに移行した
270: virtual void BusRelease() { }
271:
272: protected:
273: // 設定ファイルに使われるこのホストデバイスを示す接頭語。
274: // ("spc0" とか)
275: const char *config_name = NULL;
276:
277: #if 0
278: SCSI::BusPhase bus_phase;
279: SCSI::XferPhase xfer_phase;
280: #endif
281: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.