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

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: };

unix.superglobalmegacorp.com

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