|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2021 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: // SCSI コマンド
8:
9: #pragma once
10:
11: #include "scsi.h"
12: #include <functional>
13: #include <vector>
14:
15: // READ/WRITE は多すぎるのでログを省略したい場合に定義。
16: //#define NO_READWRITE_LOG
17:
18: class SCSITarget;
19:
20: //
21: // SCSI コマンドの基本クラス
22: // (黙って成功するコマンドとしても使用可能)
23: //
24: class SCSICmd
25: {
26: public:
27: SCSICmd(SCSITarget *parent_);
28: virtual ~SCSICmd();
29:
30: // 転送バッファと転送バイト数。
31: // IN (ターゲットが送出側)なら、各フェーズ開始までに送出バイト数分の
32: // バッファを buf に用意すること。recvbytes は操作不要。
33: //
34: // OUT(ターゲットが受信側)なら、各フェーズ開始前までに受信バイト数を
35: // recvbytes にセットすること。buf は操作不要。
36: // なお parent は OUT(受信)フェーズ中にこの recvbytes を変更しない。
37: std::vector<uint8> buf;
38: uint32 recvbytes;
39:
40: // このコマンドの動作時間 [nsec]
41: // シークタイムとかを簡易的に再現するため、次フェーズ遷移時の最初の
42: // REQ アサートを引き延ばすために使う。
43: // 主にコマンドフェーズで使うことになると思う。
44: uint64 optime {};
45:
46: // 以下いずれも戻り値は遷移先のフェーズ。
47:
48: // コマンドフェーズを処理する。
49: // コマンドが確定したところで呼ばれる。戻り値に遷移先フェーズを返すこと。
50: // また、コマンド開始時に各自で ClearSense() を呼ぶこと。センスというか
51: // CA 状態は次のコマンド実行でクリアされるが (ネクサスはとりあえず無視)、
52: // RequestSense の場合は現在保持しているセンス情報をホストに返すので、
53: // つまり RequestSense 以外のコマンドが全員各自でクリアする必要がある。
54: virtual SCSI::XferPhase Command(std::vector<uint8>& cmdseq);
55:
56: // データインフェーズを完了する。
57: virtual SCSI::XferPhase DoneDataIn() {
58: return SCSI::XferPhase::Status;
59: }
60:
61: // データアウトフェーズを完了する。
62: virtual SCSI::XferPhase DoneDataOut() {
63: return SCSI::XferPhase::Status;
64: }
65:
66: // ステータスフェーズを開始する。
67: void BeginStatus() {
68: buf.clear();
69: buf.push_back(status_byte);
70: }
71:
72: // ステータスフェーズを完了する。
73: virtual SCSI::XferPhase DoneStatus() {
74: return SCSI::XferPhase::MsgIn;
75: }
76:
77: // メッセージインフェーズを開始する。
78: // デフォルトでは Command Complete を返す実装を用意しておく。
79: virtual void BeginMsgIn() {
80: buf.clear();
81: buf.push_back((uint8)SCSI::MsgByte::CommandComplete);
82: }
83:
84: // メッセージインフェーズを完了する。
85: virtual SCSI::XferPhase DoneMsgIn() {
86: return SCSI::XferPhase::End;
87: }
88:
89: // メッセージアウトフェーズを開始する。
90: virtual void BeginMsgOut() { }
91:
92: // メッセージアウトフェーズを完了する。
93: virtual SCSI::XferPhase DoneMsgOut() {
94: return SCSI::XferPhase::End;
95: }
96:
97: protected:
98: // このコマンドを実行しているターゲットデバイス。
99: SCSITarget *parent;
100:
101: // ステータスバイト (デフォルトは 0 = Good)
102: uint8 status_byte {};
103: };
104:
105: //
106: // SCSI コマンド: サポートしていないコマンド
107: //
108: class SCSICmdNotSupportedCommand : public SCSICmd
109: {
110: using inherited = SCSICmd;
111: public:
112: SCSICmdNotSupportedCommand(SCSITarget *);
113: virtual ~SCSICmdNotSupportedCommand() override;
114:
115: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
116: };
117:
118: //
119: // SCSI コマンド 0x03 RequestSense (共通)
120: //
121: class SCSICmdRequestSense : public SCSICmd
122: {
123: using inherited = SCSICmd;
124: public:
125: SCSICmdRequestSense(SCSITarget *);
126: virtual ~SCSICmdRequestSense() override;
127:
128: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
129: };
130:
131: //
132: // SCSI コマンド 0x08 Read(6) (DA / CD-ROM)
133: // 0x28 Read(10) (DA / CD-ROM)
134: //
135: class SCSICmdRead : public SCSICmd
136: {
137: using inherited = SCSICmd;
138: public:
139: SCSICmdRead(SCSIDisk *);
140: virtual ~SCSICmdRead() override;
141:
142: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
143:
144: private:
145: SCSIDisk *disk {};
146: };
147:
148: //
149: // SCSI コマンド 0x0a Write(6) (DA / CD-ROM)
150: // 0x2a Write(10) (DA / CD-ROM)
151: //
152: class SCSICmdWrite : public SCSICmd
153: {
154: using inherited = SCSICmd;
155: public:
156: SCSICmdWrite(SCSIDisk *);
157: virtual ~SCSICmdWrite() override;
158:
159: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
160: SCSI::XferPhase DoneDataOut() override;
161:
162: private:
163: uint8 cmd {};
164: SCSIDisk *disk {};
165: uint32 lba {};
166: uint32 blks {};
167: };
168:
169: //
170: // SCSI コマンド 0x12 Inquiry (共通)
171: //
172: class SCSICmdInquiry : public SCSICmd
173: {
174: using inherited = SCSICmd;
175: public:
176: SCSICmdInquiry(SCSITarget *);
177: virtual ~SCSICmdInquiry() override;
178:
179: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
180: };
181:
182: //
183: // SCSI コマンド 0x15 ModeSelect(6) (共通)
184: // 0x55 ModeSelect(10) (共通)
185: //
186: class SCSICmdModeSelect : public SCSICmd
187: {
188: using inherited = SCSICmd;
189: public:
190: SCSICmdModeSelect(SCSITarget *);
191: virtual ~SCSICmdModeSelect() override;
192:
193: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
194: SCSI::XferPhase DoneDataOut() override;
195:
196: private:
197: uint8 cmd {};
198: };
199:
200: //
201: // SCSI コマンド 0x1a ModeSense(6) (共通)
202: // 0x5a ModeSense(10) (共通)
203: //
204: class SCSICmdModeSense : public SCSICmd
205: {
206: using inherited = SCSICmd;
207: public:
208: SCSICmdModeSense(SCSITarget *);
209: virtual ~SCSICmdModeSense() override;
210:
211: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
212:
213: private:
214: using PageFunc = std::function<int(void)>;
215:
216: // Page Control
217: enum PC {
218: Current = 0x00, // 現在値
219: Changeable = 0x01, // 変更可能値
220: Default = 0x02, // デフォルト値
221: Saved = 0x03, // セーブ値
222: };
223: // ページ処理関数の戻り値 (この値は大小比較する)
224: enum ModePageResult {
225: NotImplemented = -1, // 未実装や知らないページ
226: Failed = 0, // 対応しない/出来ないと分かっているページ
227: Success = 1, // 成功
228: };
229:
230: // 個別ページ処理
231: int AddNotSupportedPage();
232: int AddEmptyPage();
233: int AddCachingPage();
234:
235: // ページ処理関数のため
236: uint pagecode {};
237: PC pc {};
238:
239: // ログ用の文字列
240: std::string log {};
241: };
242:
243: //
244: // SCSI コマンド 0x1b StartStopUnit (DA / CD-ROM)
245: //
246: class SCSICmdStartStopUnit : public SCSICmd
247: {
248: using inherited = SCSICmd;
249: public:
250: SCSICmdStartStopUnit(SCSIDisk *);
251: virtual ~SCSICmdStartStopUnit() override;
252:
253: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
254:
255: private:
256: SCSIDisk *disk {};
257: };
258:
259: //
260: // SCSI コマンド 0x1e PreventAllowMediumRemoval (DA / CD-ROM)
261: //
262: class SCSICmdPreventAllowMediumRemoval : public SCSICmd
263: {
264: using inherited = SCSICmd;
265: public:
266: SCSICmdPreventAllowMediumRemoval(SCSIDisk *);
267: virtual ~SCSICmdPreventAllowMediumRemoval() override;
268:
269: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
270:
271: private:
272: SCSIDisk *disk {};
273: };
274:
275: //
276: // SCSI コマンド 0x25 ReadCapacity (DA)
277: // 0x25 Read CDROM Capacity (CD-ROM)
278: // (ここでは ReadCapacity として同一視する)
279: //
280: class SCSICmdReadCapacity : public SCSICmd
281: {
282: using inherited = SCSICmd;
283: public:
284: SCSICmdReadCapacity(SCSIDisk *);
285: virtual ~SCSICmdReadCapacity() override;
286:
287: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
288:
289: private:
290: SCSIDisk *disk {};
291: };
292:
293: //
294: // SCSI コマンド 0x43 ReadTOC (CD-ROM)
295: //
296: class SCSICmdReadTOC : public SCSICmd
297: {
298: using inherited = SCSICmd;
299: public:
300: SCSICmdReadTOC(SCSIDisk *);
301: virtual ~SCSICmdReadTOC() override;
302:
303: SCSI::XferPhase Command(std::vector<uint8>& cmdseq) override;
304:
305: private:
306: SCSIDisk *disk {};
307: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.