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