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