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