|
|
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.1.8 ! root 142: // SCSIBus を取得 (UI からインジケータ表示用)
! 143: std::shared_ptr<SCSIBus> GetSCSIBus() const { return scsibus; }
! 144:
1.1 root 145: protected:
1.1.1.2 root 146: // 設定ファイルに使われるこのホストデバイスを示す接頭語を設定する
147: // (ここで設定項目を Add するので、継承クラスのコンストラクタから呼ぶこと)
148: void SetConfigName(const char *name);
149:
1.1 root 150: // 設定ファイルに使われるこのホストデバイスを示す接頭語。
151: // ("spc0" とか)
1.1.1.5 root 152: const char *config_name {};
1.1 root 153:
154: // SCSI バス (とターゲットオブジェクト)
155: //
156: // ホストデバイスなのでバスオブジェクト(SCSIBus *scsibus)と、このバスに
157: // 繋がるターゲットデバイスのオブジェクト(SCSITarget *target[]) を所有
158: // (unique_ptr) している。これはオブジェクト同士の所有関係の話。
159: // ホストは SCSIDevice を継承しているので target[] にホスト自身は含めない。
160: //
161: // それとは別に SCSI バスと SCSI デバイスの仮想的な接続関係があり、
162: // こっちはすべて所有権のないただのポインタで相互にリンクする。
163: // これが scsibus->device[] と SCSIDevice::bus の相互リンク。
164: //
165: // こんな感じ。
166: // SCSIHostDevice
167: // +-------------------------------------+
168: // | scsibus target[0] |
169: // +--- || ----+ +---------- | -+
170: // || |SCSIDevice| |
171: // ID7 ||<----> bus | |
172: // || +----------+ |
173: // || |
174: // || SCSIHD(SCSIDevice) |
175: // || +----------+ |
176: // ID0 ||<----> bus |<----------+
177: // || +----------+ own
178: //
1.1.1.8 ! root 179: std::shared_ptr<SCSIBus> scsibus {};
1.1.1.5 root 180: std::unique_ptr<SCSITarget> target[8] {};
1.1 root 181: };
182:
183: //
184: // ターゲットデバイスの共通部分。
185: //
186: class SCSITarget : public SCSIDevice
187: {
1.1.1.3 root 188: using inherited = SCSIDevice;
1.1 root 189: friend class SCSICmdModeSelect6;
190: public:
191: SCSITarget(SCSIHostDevice *h, int id, std::vector<uint8>& inq);
1.1.1.6 root 192: virtual ~SCSITarget() override;
1.1 root 193:
1.1.1.8 ! root 194: bool PowerOn() override;
! 195:
1.1 root 196: // Inquiry 応答データ
1.1.1.5 root 197: std::vector<uint8> inquiry_data {};
1.1 root 198:
199: // 現在のコマンド列を返す (モニタ用)
200: std::vector<uint8> GetCmdSeq() const { return cmdseq; }
201:
1.1.1.2 root 202: // 論理ブロック長
203: uint32 GetBlocksize() const { return blocksize; }
204: void SetBlocksize(uint32 val) { blocksize = val; }
205:
1.1.1.4 root 206: // センスキーと ASC/ASCQ
207: uint8 sensekey {};
208: uint16 senseasc {};
209:
210: // センスキーをクリア
211: void ClearSense() {
212: sensekey = 0;
213: senseasc = 0;
214: }
215:
1.1 root 216: // SCSIBus コールバック
217:
1.1.1.4 root 218: // バスリセットされた (全員に通知される)
219: void BusResetCB() override;
220:
1.1 root 221: // セレクションで選択された (ターゲットのみ通知される)
1.1.1.3 root 222: void SelectionCB() override;
1.1 root 223:
224: // 情報転送フェーズを開始する (ターゲットのみ通知される)
1.1.1.3 root 225: void StartTransferCB() override;
1.1 root 226:
227: // 情報転送フェーズで1バイト送受信が進んだ (ターゲットのみ通知される)
1.1.1.3 root 228: void TransferCB() override;
1.1 root 229:
230: // 情報転送フェーズ(マニュアル転送)で ACK を下げた (ターゲットのみ通知)
1.1.1.3 root 231: void TransferAckCB() override;
1.1 root 232:
233: protected:
234: // ホスト
1.1.1.5 root 235: SCSIHostDevice *host {};
1.1 root 236:
237: // コマンド
238: std::vector<uint8> cmdseq {};
239: // このコマンドの長さ。
240: // cmdseq の1バイト目で決まるやつのことで、受信目標バイト数。
241: // 今何バイト受信しているかは cmdseq.size()。
1.1.1.5 root 242: int cmdlen {};
1.1 root 243:
244: // SCSI コマンドのディスパッチャ
245: virtual void DispatchCmd();
246:
247: // 現在実行中の SCSI コマンド
1.1.1.5 root 248: // SCSICmd は *.cpp のみで完結していて宣言がヘッダにないので
249: // 一様初期化構文 {} が使えない。
1.1 root 250: std::unique_ptr<SCSICmd> cmd;
251:
252: // 現在のフェーズでの転送カウント。
253: // IN と OUT でカウント方向が違うことに注意。
1.1.1.5 root 254: uint32 bytecount {};
1.1 root 255:
256: // 現在処理中のバイトが(各)フェーズの最終バイトなら true
1.1.1.5 root 257: bool lastbyte {};
1.1 root 258:
259: // 論理ブロック長 (ModeSelect コマンドでホストから指定される)
260: // XXX: LUNA88K で ROM がたぶんやる。。。
261: uint32 blocksize = 512;
262: };
263:
264: //
265: // SCSI HD
266: //
267: class SCSIHD : public SCSITarget
268: {
1.1.1.3 root 269: using inherited = SCSITarget;
1.1 root 270: friend class SCSICmdRead6;
271: friend class SCSICmdWrite6;
272: friend class SCSICmdReadCapacity;
273: friend class SCSICmdRead10;
1.1.1.7 root 274: friend class SCSICmdWrite10;
1.1 root 275: public:
276: SCSIHD(SCSIHostDevice *h, int id);
1.1.1.6 root 277: virtual ~SCSIHD() override;
1.1 root 278:
1.1.1.3 root 279: bool Init() override;
280: void DispatchCmd() override;
1.1 root 281:
1.1.1.2 root 282: // このディスクをディスクイメージだと思うとして (いや実際そうだけど)
283: // 先頭から start バイト目から len バイト読み出して返す。
284: // 単位はセクタではなくバイトなことに注意。
285: // (エミュレータ特権アクセス)
286: bool PeekImage(void *buf, uint32 start, uint32 len) const;
287:
1.1.1.5 root 288: // ディスクイメージ長を取得
289: off_t GetSize() const { return file.GetMemSize(); }
290:
1.1 root 291: private:
1.1.1.3 root 292: MappedFile file {};
293: uint8 *mem {};
1.1.1.5 root 294: bool writeprotect {};
295: uint64 seektime {};
1.1.1.3 root 296:
1.1 root 297: static std::vector<uint8> inquiry_data;
298: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.