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