|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 [email protected]
4: //
5:
6: // SCSI デバイス共通部分
7:
8: #pragma once
9:
10: #include "scsibus.h"
11:
12: // IODevice (SPCDevice の親になるため)
13: // |
14: // v
15: // SCSIDevice (SCSI デバイスとしての共通部分)
16: // |
17: // +------+---------+
18: // v v
19: // SCSIHostDevice SCSITarget (SCSI ホスト/ターゲットとしての共通部分)
20: // | |
21: // v v
22: // SPCDevice SCSIHD (各デバイス、各ターゲット固有部分)
23:
24: class SCSICmd;
25:
26: //
27: // SCSI デバイスとしての共通部分。
28: // これ自体は IODevice ではないが SCSI ホストアダプタがこれを継承するため。
29: //
30: class SCSIDevice : public IODevice
31: {
32: public:
33: SCSIDevice();
34: virtual ~SCSIDevice();
35:
36: // バスに接続 (SCSIBus::Attach から呼ばれる)
37: void Attach(SCSIBus *bus_, int id) {
38: bus = bus_;
39: myid = id;
40: }
41:
42: //
43: // 信号線制御
44: // (ソースコード的なショートカットのため)
45: //
46: bool GetRST() const { return bus->GetRST(); }
47: void AssertRST() { bus->AssertRST(); }
48: void NegateRST() { bus->NegateRST(); }
49: bool GetREQ() const { return bus->GetREQ(); }
50: void AssertREQ() { bus->AssertREQ(); }
51: void NegateREQ() { bus->NegateREQ(); }
52: bool GetACK() const { return bus->GetACK(); }
53: void AssertACK() { bus->AssertACK(); }
54: void NegateACK() { bus->NegateACK(); }
55: bool GetATN() const { return bus->GetATN(); }
56: void AssertATN() { bus->AssertATN(); }
57: void NegateATN() { bus->NegateATN(); }
58: uint8 GetSEL() const { return bus->GetSEL(); }
59: void AssertSEL() { bus->AssertSEL(myid); }
60: void NegateSEL() { bus->NegateSEL(myid); }
61: uint8 GetBSY() const { return bus->GetBSY(); }
62: void AssertBSY() { bus->AssertBSY(myid); }
63: void NegateBSY() { bus->NegateBSY(myid); }
64: bool GetMSG() const { return bus->GetMSG(); }
65: bool GetCD() const { return bus->GetCD(); }
66: bool GetIO() const { return bus->GetIO(); }
67: SCSI::XferPhase GetXfer() const { return bus->GetXfer(); }
68: void SetXfer(uint8 val) { bus->SetXfer(val); }
69: SCSI::Phase GetPhase() const { return bus->GetPhase(); }
70: uint8 GetData() const { return bus->GetData(); }
71: void SetData(uint8 val) const { bus->SetData(val); }
72:
73: //
74: // SCSIBus コールバック
75: //
76:
77: // バスリセットされた (全員に通知される)
78: virtual void BusResetCB() { }
79:
80: // バスフリーになった (全員に通知される)
81: virtual void BusFreeCB(int id) { }
82:
83: // セレクションで選択された (ターゲットのみ通知される)
84: virtual void SelectionCB() { }
85:
86: // ターゲットがセレクションに応答した (イニシエータのみ通知される)
87: virtual void SelectionAckCB() { }
88:
89: // 情報転送フェーズを開始する (ターゲットのみ通知される)
90: virtual void StartTransferCB() { }
91:
92: // 情報転送フェーズで REQ を立てた (イニシエータのみ通知される)
93: virtual void TransferReqCB() { }
94:
95: // 情報転送フェーズで1バイト送受信が進んだ (ターゲットのみ通知される)
96: virtual void TransferCB() { }
97:
98: // 情報転送フェーズ(マニュアル転送)で ACK を下げた (ターゲットのみ通知)
99: virtual void TransferAckCB() { }
100:
101: protected:
102: // 自身の ID
103: uint myid;
104:
105: // 自身が繋がっているバスへのポインタ。
106: // (イニシエータ自身も含めて) 所有していない。
107: SCSIBus *bus;
108: };
109:
110: //
111: // ホストデバイスの共通部分。
112: //
113: class SCSIHostDevice : public SCSIDevice
114: {
115: public:
116: SCSIHostDevice();
117: virtual ~SCSIHostDevice();
118:
119: virtual bool Create();
120: virtual bool Init();
121:
122: // 設定ファイル上のこのホストデバイスを示す接頭語を返す
123: const char *GetConfigName() const { return config_name; }
124:
125: // バスフリーになった (全員に通知される)
126: virtual void BusFreeCB(int id);
127:
128: protected:
129: // 設定ファイルに使われるこのホストデバイスを示す接頭語。
130: // ("spc0" とか)
131: const char *config_name = NULL;
132:
133: // SCSI バス (とターゲットオブジェクト)
134: //
135: // ホストデバイスなのでバスオブジェクト(SCSIBus *scsibus)と、このバスに
136: // 繋がるターゲットデバイスのオブジェクト(SCSITarget *target[]) を所有
137: // (unique_ptr) している。これはオブジェクト同士の所有関係の話。
138: // ホストは SCSIDevice を継承しているので target[] にホスト自身は含めない。
139: //
140: // それとは別に SCSI バスと SCSI デバイスの仮想的な接続関係があり、
141: // こっちはすべて所有権のないただのポインタで相互にリンクする。
142: // これが scsibus->device[] と SCSIDevice::bus の相互リンク。
143: //
144: // こんな感じ。
145: // SCSIHostDevice
146: // +-------------------------------------+
147: // | scsibus target[0] |
148: // +--- || ----+ +---------- | -+
149: // || |SCSIDevice| |
150: // ID7 ||<----> bus | |
151: // || +----------+ |
152: // || |
153: // || SCSIHD(SCSIDevice) |
154: // || +----------+ |
155: // ID0 ||<----> bus |<----------+
156: // || +----------+ own
157: //
158: std::unique_ptr<SCSIBus> scsibus;
159: std::unique_ptr<SCSITarget> target[8];
160: };
161:
162: //
163: // ターゲットデバイスの共通部分。
164: //
165: class SCSITarget : public SCSIDevice
166: {
167: typedef SCSIDevice inherited;
168: friend class SCSICmdModeSelect6;
169: public:
170: SCSITarget(SCSIHostDevice *h, int id, std::vector<uint8>& inq);
171: virtual ~SCSITarget();
172:
173: // デバイス種別を返す (主にデバッグ表示用)
174: SCSI::DevType GetDevType() const { return devtype; }
175:
176: // Inquiry 応答データ
177: std::vector<uint8> inquiry_data;
178:
179: // 現在のコマンド列を返す (モニタ用)
180: std::vector<uint8> GetCmdSeq() const { return cmdseq; }
181:
182: // SCSIBus コールバック
183:
184: // セレクションで選択された (ターゲットのみ通知される)
185: virtual void SelectionCB();
186:
187: // 情報転送フェーズを開始する (ターゲットのみ通知される)
188: virtual void StartTransferCB();
189:
190: // 情報転送フェーズで1バイト送受信が進んだ (ターゲットのみ通知される)
191: virtual void TransferCB();
192:
193: // 情報転送フェーズ(マニュアル転送)で ACK を下げた (ターゲットのみ通知)
194: virtual void TransferAckCB();
195:
196: protected:
197: // デバイス種別
198: SCSI::DevType devtype;
199: // ホスト
200: SCSIHostDevice *host;
201:
202: // コマンド
203: std::vector<uint8> cmdseq {};
204: // このコマンドの長さ。
205: // cmdseq の1バイト目で決まるやつのことで、受信目標バイト数。
206: // 今何バイト受信しているかは cmdseq.size()。
207: int cmdlen;
208:
209: // SCSI コマンドのディスパッチャ
210: virtual void DispatchCmd();
211:
212: // 現在実行中の SCSI コマンド
213: std::unique_ptr<SCSICmd> cmd;
214:
215: // 現在のフェーズでの転送カウント。
216: // IN と OUT でカウント方向が違うことに注意。
217: uint32 bytecount = 0;
218:
219: // 現在処理中のバイトが(各)フェーズの最終バイトなら true
220: bool lastbyte = false;
221:
222: // 論理ブロック長 (ModeSelect コマンドでホストから指定される)
223: // XXX: LUNA88K で ROM がたぶんやる。。。
224: uint32 blocksize = 512;
225: };
226:
227: //
228: // SCSI HD
229: //
230: class SCSIHD : public SCSITarget
231: {
232: typedef SCSITarget inherited;
233: friend class SCSICmdRead6;
234: friend class SCSICmdWrite6;
235: friend class SCSICmdReadCapacity;
236: friend class SCSICmdRead10;
237: public:
238: SCSIHD(SCSIHostDevice *h, int id);
239: virtual ~SCSIHD();
240:
241: virtual bool Init();
242: virtual void DispatchCmd();
243:
244: private:
245: int fd = 0;
246: uint8 *mem = NULL;
247: size_t memlen = 0;
248: bool writeprotect = false;
249:
250: static std::vector<uint8> inquiry_data;
251: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.