|
|
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.