Annotation of nono/vm/scsidev.h, revision 1.1.1.20

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: 
1.1.1.12  root        7: //
                      8: // SCSI デバイス
                      9: //
1.1       root       10: 
1.1.1.17  root       11: // Device                 Device
                     12: //    |                     |
                     13: //    v                     v
                     14: // IODevice             SCSIDevice         (SCSI デバイスとしての共通部分)
                     15: //    |                     |
                     16: //    v               +-----+------+
                     17: // SPCDevice          v             v
                     18: //      .scsi -> SCSIHostDevice SCSITarget (SCSI ホスト/ターゲットの共通部分)
                     19: //                                  |
                     20: //                                  v
                     21: //                               SCSIDisk  (各デバイス、各ターゲット固有部分)
1.1       root       22: 
1.1.1.12  root       23: #pragma once
                     24: 
                     25: #include "diskimage.h"
                     26: #include "message.h"
                     27: #include "scsibus.h"
                     28: #include "scsicmd.h"
                     29: 
1.1.1.18  root       30: class SCSIDomain;
                     31: 
1.1       root       32: //
                     33: // SCSI デバイスとしての共通部分。
                     34: //
1.1.1.17  root       35: class SCSIDevice : public Device
1.1       root       36: {
1.1.1.17  root       37:        using inherited = Device;
1.1       root       38:  public:
1.1.1.17  root       39:        explicit SCSIDevice(uint objid_);
1.1.1.16  root       40:        ~SCSIDevice() override;
1.1       root       41: 
1.1.1.5   root       42:        // SCSI ID を返す
1.1.1.17  root       43:        uint GetMyID() const { return myid; }
1.1.1.5   root       44: 
                     45:        // デバイス種別を返す (主にデバッグ表示用)
                     46:        SCSI::DevType GetDevType() const { return devtype; }
                     47: 
1.1.1.18  root       48:        // バスに接続する。
                     49:        void Attach(SCSIBus *bus_);
                     50: 
1.1.1.17  root       51:        // 自身が接続しているバスを返す。
                     52:        // イニシエータがバスに接続するのは VM 実行後なことに注意。
                     53:        SCSIBus *GetBus() const { return bus; }
                     54: 
1.1       root       55:        //
                     56:        // 信号線制御
                     57:        // (ソースコード的なショートカットのため)
                     58:        //
                     59:        bool GetRST() const                             { return bus->GetRST(); }
                     60:        void AssertRST()                                { bus->AssertRST(); }
                     61:        void NegateRST()                                { bus->NegateRST(); }
                     62:        bool GetREQ() const                             { return bus->GetREQ(); }
                     63:        void AssertREQ()                                { bus->AssertREQ(); }
                     64:        void NegateREQ()                                { bus->NegateREQ(); }
                     65:        bool GetACK() const                             { return bus->GetACK(); }
                     66:        void AssertACK()                                { bus->AssertACK(); }
                     67:        void NegateACK()                                { bus->NegateACK(); }
                     68:        bool GetATN() const                             { return bus->GetATN(); }
                     69:        void AssertATN()                                { bus->AssertATN(); }
                     70:        void NegateATN()                                { bus->NegateATN(); }
                     71:        uint8 GetSEL() const                    { return bus->GetSEL(); }
                     72:        void AssertSEL()                                { bus->AssertSEL(myid); }
                     73:        void NegateSEL()                                { bus->NegateSEL(myid); }
                     74:        uint8 GetBSY() const                    { return bus->GetBSY(); }
                     75:        void AssertBSY()                                { bus->AssertBSY(myid); }
                     76:        void NegateBSY()                                { bus->NegateBSY(myid); }
                     77:        bool GetMSG() const                             { return bus->GetMSG(); }
                     78:        bool GetCD() const                              { return bus->GetCD(); }
                     79:        bool GetIO() const                              { return bus->GetIO(); }
                     80:        SCSI::XferPhase GetXfer() const { return bus->GetXfer(); }
                     81:        void SetXfer(uint8 val)                 { bus->SetXfer(val); }
                     82:        SCSI::Phase GetPhase() const    { return bus->GetPhase(); }
                     83:        uint8 GetData() const                   { return bus->GetData(); }
                     84:        void SetData(uint8 val) const   { bus->SetData(val); }
                     85: 
                     86:        //
1.1.1.17  root       87:        // SCSIBus から呼ばれる
1.1       root       88:        //
                     89: 
                     90:        // バスリセットされた (全員に通知される)
1.1.1.17  root       91:        virtual void OnBusReset() { }
1.1       root       92: 
                     93:        // バスフリーになった (全員に通知される)
1.1.1.17  root       94:        virtual void OnBusFree(uint id) { }
1.1       root       95: 
                     96:        // セレクションで選択された (ターゲットのみ通知される)
1.1.1.17  root       97:        virtual void OnSelected() { }
1.1       root       98: 
                     99:        // ターゲットがセレクションに応答した (イニシエータのみ通知される)
1.1.1.17  root      100:        virtual void OnSelectionAck() { }
1.1       root      101: 
                    102:        // 情報転送フェーズを開始する (ターゲットのみ通知される)
1.1.1.17  root      103:        virtual void OnStartTransfer() { }
1.1       root      104: 
                    105:        // 情報転送フェーズで REQ を立てた (イニシエータのみ通知される)
1.1.1.17  root      106:        virtual void OnTransferReq() { }
1.1       root      107: 
                    108:        // 情報転送フェーズで1バイト送受信が進んだ (ターゲットのみ通知される)
1.1.1.17  root      109:        virtual void OnTransfer() { }
1.1       root      110: 
                    111:        // 情報転送フェーズ(マニュアル転送)で ACK を下げた (ターゲットのみ通知)
1.1.1.17  root      112:        virtual void OnTransferAck() { }
1.1       root      113: 
                    114:  protected:
                    115:        // 自身の ID
1.1.1.5   root      116:        uint myid {};
                    117: 
                    118:        // デバイス種別
                    119:        SCSI::DevType devtype {};
1.1       root      120: 
1.1.1.18  root      121:        // あれば自身が繋がっているバスへのポインタ。
                    122:        // (イニシエータ自身も含めて) 所有ではない。
1.1.1.5   root      123:        SCSIBus *bus {};
1.1.1.18  root      124: 
                    125:        // 自身を管理しているドメイン(親) へのポインタ。
                    126:        SCSIDomain *domain {};
1.1       root      127: };
                    128: 
                    129: //
                    130: // ホストデバイスの共通部分。
1.1.1.17  root      131: // イニシエータもしくは HBA (ホストバスアダプタ) に相当する部分。
1.1       root      132: //
                    133: class SCSIHostDevice : public SCSIDevice
                    134: {
1.1.1.9   root      135:        using inherited = SCSIDevice;
1.1.1.17  root      136: 
1.1       root      137:  public:
1.1.1.17  root      138:        using SCSIHostCallback_t = void (Device::*)();
                    139:        using BusFreeCallback_t = void (Device::*)(uint);
                    140: #define ToSCSIHostCallback(f)  \
                    141:        static_cast<SCSIHostDevice::SCSIHostCallback_t>(f)
                    142: #define ToBusFreeCallback(f)   \
                    143:        static_cast<SCSIHostDevice::BusFreeCallback_t>(f)
                    144: 
                    145:  public:
1.1.1.18  root      146:        SCSIHostDevice(SCSIDomain *domain_, IODevice *parent_);
1.1.1.16  root      147:        ~SCSIHostDevice() override;
1.1       root      148: 
1.1.1.18  root      149:        // SCSI ID を設定する。(SCSIDomain からのみ呼ぶこと)
                    150:        void SetID(uint myid_);
1.1       root      151: 
1.1.1.18  root      152:        // SCSIBus からのコールバック関数を設定する。
                    153:        void SetBusCallback(
1.1.1.17  root      154:                BusFreeCallback_t busfree_,
                    155:                SCSIHostCallback_t selack_,
                    156:                SCSIHostCallback_t xferreq_);
1.1       root      157: 
1.1.1.17  root      158:  private:
                    159:        // SCSIBus から呼ばれる
1.1.1.10  root      160: 
1.1.1.17  root      161:        // バスフリーになった (SCSIBus から全員に通知される)
                    162:        void OnBusFree(uint id) override;
                    163:        // ターゲットがセレクションに応答した (SCSIBus から呼ばれる)
                    164:        void OnSelectionAck() override;
                    165:        // 情報転送フェーズで REQ を立てた (イニシエータのみ通知される)
                    166:        void OnTransferReq() override;
1.1.1.8   root      167: 
1.1.1.17  root      168:        // 親クラス(コントローラ) へのコールバック。
1.1.1.10  root      169: 
1.1.1.17  root      170:        // バスフリーを通知する
                    171:        BusFreeCallback_t BusFreeCallback {};
                    172:        // ターゲットがセレクションに応答したことを通知する
                    173:        SCSIHostCallback_t SelectionAckCallback {};
                    174:        // 転送フェーズでターゲットが REQ を立てたことを通知する
                    175:        SCSIHostCallback_t TransferReqCallback {};
1.1       root      176: 
1.1.1.17  root      177:        // コントローラデバイス。
                    178:        IODevice *parent {};
1.1       root      179: };
                    180: 
                    181: //
                    182: // ターゲットデバイスの共通部分。
                    183: //
                    184: class SCSITarget : public SCSIDevice
                    185: {
1.1.1.3   root      186:        using inherited = SCSIDevice;
1.1       root      187:  public:
1.1.1.18  root      188:        SCSITarget(SCSIDomain *, uint id);
1.1.1.16  root      189:        ~SCSITarget() override;
1.1       root      190: 
1.1.1.12  root      191:        void ResetHard(bool poweron) override;
1.1.1.8   root      192: 
1.1.1.10  root      193:        // Inquiry データを返す (Cmd から呼ばれる)
1.1.1.17  root      194:        virtual bool Inquiry(std::vector<uint8>& buf, uint lun) = 0;
1.1       root      195: 
                    196:        // 現在のコマンド列を返す (モニタ用)
                    197:        std::vector<uint8> GetCmdSeq() const { return cmdseq; }
                    198: 
1.1.1.18  root      199:        // コマンド列から SCSICmd を選択する。
                    200:        // (VirtIOSCSI と ROM30 エミュレーションから使う)
1.1.1.13  root      201:        SCSICmd *SelectCommand(const std::vector<uint8>& cmdseq_);
                    202: 
1.1.1.2   root      203:        // 論理ブロック長
                    204:        uint32 GetBlocksize() const { return blocksize; }
                    205:        void SetBlocksize(uint32 val) { blocksize = val; }
                    206: 
1.1.1.10  root      207:        // ModeSense コマンドのデバイス固有パラメータを返す
                    208:        virtual uint8 GetDeviceSpecificParam() const { return 0; }
                    209: 
1.1.1.18  root      210:        // センスキー
1.1.1.4   root      211:        uint8  sensekey {};
1.1.1.18  root      212:        // 上位バイトが ASC、下位バイトが ASCQ
1.1.1.4   root      213:        uint16 senseasc {};
                    214: 
                    215:        // センスキーをクリア
                    216:        void ClearSense() {
                    217:                sensekey = 0;
                    218:                senseasc = 0;
                    219:        }
                    220: 
1.1.1.17  root      221:        // SCSIBus から呼ばれる
1.1       root      222: 
1.1.1.4   root      223:        // バスリセットされた (全員に通知される)
1.1.1.17  root      224:        void OnBusReset() override;
1.1.1.4   root      225: 
1.1       root      226:        // セレクションで選択された (ターゲットのみ通知される)
1.1.1.17  root      227:        void OnSelected() override;
1.1       root      228: 
                    229:        // 情報転送フェーズを開始する (ターゲットのみ通知される)
1.1.1.17  root      230:        void OnStartTransfer() override;
1.1       root      231: 
                    232:        // 情報転送フェーズで1バイト送受信が進んだ (ターゲットのみ通知される)
1.1.1.17  root      233:        void OnTransfer() override;
1.1       root      234: 
                    235:        // 情報転送フェーズ(マニュアル転送)で ACK を下げた (ターゲットのみ通知)
1.1.1.17  root      236:        void OnTransferAck() override;
1.1       root      237: 
                    238:  protected:
1.1.1.18  root      239:        // SCSI コマンドを選択する。内部用。
                    240:        void SelectCommand();
                    241: 
1.1.1.12  root      242:        // SCSI コマンドのディスパッチャ
                    243:        virtual void DispatchCmd();
                    244: 
1.1       root      245:        // コマンド
                    246:        std::vector<uint8> cmdseq {};
1.1.1.12  root      247: 
1.1       root      248:        // このコマンドの長さ。
                    249:        // cmdseq の1バイト目で決まるやつのことで、受信目標バイト数。
                    250:        // 今何バイト受信しているかは cmdseq.size()。
1.1.1.17  root      251:        uint cmdlen {};
1.1       root      252: 
                    253:        // 現在実行中の SCSI コマンド
1.1.1.10  root      254:        std::unique_ptr<SCSICmd> cmd {};
1.1       root      255: 
1.1.1.19  root      256:        // コマンド前のメッセージアウトフェーズ。
                    257:        std::vector<uint8> msgseq {};
                    258: 
1.1       root      259:        // 現在のフェーズでの転送カウント。
                    260:        // IN と OUT でカウント方向が違うことに注意。
1.1.1.5   root      261:        uint32 bytecount {};
1.1       root      262: 
                    263:        // 現在処理中のバイトが(各)フェーズの最終バイトなら true
1.1.1.5   root      264:        bool lastbyte {};
1.1       root      265: 
1.1.1.10  root      266:        // 論理ブロック長
                    267:        uint32 blocksize {};
1.1       root      268: };
                    269: 
                    270: //
1.1.1.10  root      271: // SCSI Disk (HD,CD,...)
1.1       root      272: //
1.1.1.10  root      273: class SCSIDisk : public SCSITarget
1.1       root      274: {
1.1.1.3   root      275:        using inherited = SCSITarget;
1.1       root      276:  public:
1.1.1.10  root      277:        // メディアへの書き込みモード
                    278:        //
                    279:        // Device       Media   Ignore
                    280:        // RO           (RO)    *               ReadOnly
                    281:        // RW           RO              *               WriteProtect
                    282:        // RW           RW              no              Writeable
                    283:        // RW           RW              yes             WriteIgnore
                    284:        enum class RW {
                    285:                ReadOnly                = 2,    // 読み込み専用デバイス
                    286:                WriteProtect    = 1,    // 書き込み禁止メディア
                    287:                Writeable               = 0,    // 書き込み可能
                    288:                WriteIgnore             = -1,   // 書き込み可能メディアで書き込みを無視
                    289:        };
                    290: 
                    291:  public:
1.1.1.18  root      292:        SCSIDisk(SCSIDomain *, uint id, SCSI::DevType type);
1.1.1.16  root      293:        ~SCSIDisk() override;
1.1       root      294: 
1.1.1.3   root      295:        bool Init() override;
1.1.1.12  root      296:        void ResetHard(bool poweron) override;
1.1.1.10  root      297: 
1.1.1.3   root      298:        void DispatchCmd() override;
1.1.1.17  root      299:        bool Inquiry(std::vector<uint8>& buf, uint lun) override;
1.1.1.10  root      300: 
                    301:        // ModeSense コマンドのデバイス固有パラメータを返す
                    302:        uint8 GetDeviceSpecificParam() const override;
                    303: 
                    304:        // buf にデータを読み込む。
                    305:        // 単位はセクタではなくバイトなことに注意。
                    306:        bool Read(std::vector<uint8>& buf, uint64 start);
                    307: 
                    308:        // buf のデータを書き込む。
                    309:        // 単位はセクタではなくバイトなことに注意。
                    310:        bool Write(const std::vector<uint8>& buf, uint64 start);
1.1       root      311: 
1.1.1.10  root      312:        // このデバイスのバイトサイズ
                    313:        off_t GetSize() const;
                    314: 
                    315:        // このデバイスをディスクイメージだと思うとして (いや実際そうだけど)
1.1.1.2   root      316:        // 先頭から start バイト目から len バイト読み出して返す。
                    317:        // 単位はセクタではなくバイトなことに注意。
                    318:        // (エミュレータ特権アクセス)
1.1.1.10  root      319:        bool Peek(void *buf, uint64 start, uint32 len) const;
                    320: 
1.1.1.20! root      321:        // シーク時間[tsec]
1.1.1.10  root      322:        uint64 GetSeekTime() const { return seektime; }
                    323: 
                    324:        // リムーバブルデバイスなら true
                    325:        bool IsRemovableDevice() const { return removable_device; }
                    326: 
                    327:        // 書き込み可能デバイスなら true
                    328:        bool IsWriteableDevice() const { return writeable_device; }
                    329: 
                    330:        // メディアが入っていれば true
                    331:        bool IsMediumLoaded() const { return medium_loaded; }
1.1.1.2   root      332: 
1.1.1.10  root      333:        // メディアの書き込みモードを返す
                    334:        RW GetWriteMode() const { return write_mode; }
1.1.1.12  root      335:        // メディアの書き込みモードを文字列で返す (モニタ用)
                    336:        const char *GetWriteModeStr() const;
1.1.1.5   root      337: 
1.1.1.10  root      338:        // メディア(ディスク)イメージを開く/閉じる。(同一スレッドから呼ぶこと)
                    339:        bool LoadDisk(const std::string& path_);
                    340:        void UnloadDisk(bool force = false);
                    341: 
                    342:        // メディア(ディスク)イメージを開く/閉じる。(UI スレッドから呼ぶ)
                    343:        void LoadDiskUI(const std::string& path_);
                    344:        void UnloadDiskUI(bool force);
                    345: 
                    346:        // メディアの取り出し可否
                    347:        bool IsMediumRemovalPrevented() const { return medium_removal_prevented; }
                    348:        bool IsMediumRemovalAllowed() const  { return !medium_removal_prevented; }
                    349:        void PreventMediumRemoval(bool val);
                    350: 
1.1.1.19  root      351:        // 現在ロードされているイメージファイルのフルパスを返す
1.1.1.10  root      352:        const std::string& GetPathName() const { return pathname; }
                    353: 
1.1.1.17  root      354:        // SCSIBus から呼ばれる
1.1.1.10  root      355: 
                    356:        // バスリセットされた (全員に通知される)
1.1.1.17  root      357:        void OnBusReset() override;
1.1.1.9   root      358: 
1.1       root      359:  private:
1.1.1.10  root      360:        // ディスクイメージを閉じる (内部用)
                    361:        bool UnloadDisk_internal();
                    362: 
                    363:        // ディスク状態をクリアする
                    364:        void Clear();
                    365: 
                    366:        // メディア状態変更を UI に通知する
                    367:        void MediaChanged() const;
                    368: 
                    369:        // メディア挿入/排出コールバック
1.1.1.16  root      370:        void LoadMessage(MessageID, uint32);
                    371:        void UnloadMessage(MessageID, uint32);
1.1.1.10  root      372: 
                    373:        // イメージファイルのフルパス
                    374:        std::string pathname {};
                    375:        // 新しいイメージファイルのフルパス (UIから)
                    376:        std::string new_pathname {};
                    377: 
                    378:        // イメージファイル
1.1.1.11  root      379:        DiskImage image {};
1.1.1.10  root      380: 
                    381:        bool removable_device {};       // リムーバブルデバイスなら true
                    382:        bool writeable_device {};       // 書き込み可能なデバイスなら true
                    383:        bool write_ignore {};           // 書き込み無視オプション
                    384:        bool medium_loaded {};          // メディアが挿入されていれば true
                    385: 
                    386:        // メディアの書き込みモード
                    387:        RW write_mode {};
                    388: 
                    389:        // メディアの取り出しを禁止するなら true。
                    390:        // XXX Bus Device Reset メッセージでも解除できるがメッセージは未実装
                    391:        bool medium_removal_prevented {};
                    392: 
1.1.1.5   root      393:        uint64 seektime {};
1.1       root      394: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.