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