Annotation of nono/vm/scsibus.h, revision 1.1.1.13

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.7   root        7: //
1.1       root        8: // SCSI バス
1.1.1.7   root        9: //
1.1       root       10: 
1.1.1.9   root       11: #pragma once
                     12: 
                     13: #include "scsi.h"
1.1.1.11  root       14: #include <array>
1.1.1.9   root       15: 
                     16: class SCSIDevice;
                     17: class SCSIDisk;
1.1.1.11  root       18: class SCSIDomain;
1.1.1.9   root       19: class SCSIHostDevice;
                     20: class SCSITarget;
1.1       root       21: 
                     22: //
                     23: // SCSI バス
                     24: //
                     25: class SCSIBus : public Device
                     26: {
1.1.1.6   root       27:        using inherited = Device;
1.1.1.9   root       28: 
                     29:  public:
                     30:        // (1<<id) が1つだけ立ててあるビットマップから ID を返す。
                     31:        // ビットが立っていなければ -1 を返す? 複数立ってたら?
                     32:        static inline int DecodeID(uint32 mask)
                     33:        {
                     34:                mask &= 0xff;
                     35:                if (mask == 0)
                     36:                        return -1;
                     37:                return 31 - __builtin_clz(mask);
                     38:        }
                     39: 
1.1       root       40:  public:
1.1.1.11  root       41:        explicit SCSIBus(SCSIDomain *);
1.1.1.8   root       42:        ~SCSIBus() override;
1.1       root       43: 
1.1.1.9   root       44:        bool Init() override;
1.1.1.7   root       45:        void ResetHard(bool poweron) override;
1.1.1.3   root       46: 
1.1.1.11  root       47:        SCSIDomain *GetDomain() const noexcept { return domain; }
                     48: 
                     49:        // デバイス情報を更新する。
                     50:        void Refresh();
1.1       root       51: 
                     52:        // 信号線の操作
                     53:        bool GetRST() const { return rst; }
                     54:        void AssertRST();
                     55:        void NegateRST();
                     56:        bool GetREQ() const { return req; }
                     57:        void AssertREQ();
                     58:        void NegateREQ();
                     59:        bool GetACK() const { return ack; }
                     60:        void AssertACK();
                     61:        void NegateACK();
                     62:        bool GetATN() const { return atn; }
                     63:        void AssertATN();
                     64:        void NegateATN();
                     65:        uint8 GetSEL() const { return sel; }
                     66:        void AssertSEL(uint id);
                     67:        void NegateSEL(uint id);
                     68:        uint8 GetBSY() const { return bsy; }
                     69:        void AssertBSY(uint id);
                     70:        void NegateBSY(uint id);
                     71:        bool GetMSG() const     { return (xfer & SCSI::MSG); }
                     72:        bool GetCD() const      { return (xfer & SCSI::CD); }
                     73:        bool GetIO() const      { return (xfer & SCSI::IO); }
                     74: 
                     75:        // MSG,CD,IO で示されるビットを val で指定した状態に変更する。
                     76:        void SetXfer(uint8 val);
                     77: 
                     78:        // 現在の情報転送フェーズ(の信号線の状態) を返す。
                     79:        // 現在のフェーズが Transfer の時のみ戻り値の内容は有効。
                     80:        SCSI::XferPhase GetXfer() const { return (SCSI::XferPhase)xfer; }
                     81: 
                     82:        uint8 GetData() const { return data; }
                     83:        void SetData(uint8 val) { data = val; }
                     84: 
                     85:        // 現在のフェーズを返す
                     86:        SCSI::Phase GetPhase() const { return phase; }
                     87:        // フェーズを変更する
                     88:        void SetPhase(SCSI::Phase val) { phase = val; }
                     89:        // 現在のフェーズ名を返す
                     90:        const char *GetPhaseName() const { return SCSI::GetPhaseName(phase); }
                     91: 
                     92:        // 現在選択中のターゲットを返す、なければ NULL を返す。(モニタ用)
1.1.1.11  root       93:        const SCSIDevice *GetSelectedTarget() const {
                     94:                if (__predict_true(0 <= target_id && target_id < 8)) {
                     95:                        return device[target_id];
1.1       root       96:                }
                     97:                return NULL;
                     98:        }
                     99: 
1.1.1.3   root      100:        // 次の REQ アサートの前に指定のウェイトを入れる
                    101:        // (シークタイムなどを簡易的に再現するため)。
                    102:        // ウェイトは一度適用されると 0 に戻る。
1.1.1.13! root      103:        void SetOneshotReqWait(uint64 tsec) { req_wait += tsec; }
1.1.1.3   root      104: 
1.1       root      105:  private:
1.1.1.9   root      106:        void BusFree(uint id);
1.1.1.12  root      107:        void SelectionStart(Event *);
                    108:        void Selected(Event *);
                    109:        void SelectionAck(Event *);
                    110:        void StartTransfer(Event *);
                    111:        void TransferReq(Event *);
1.1       root      112: 
                    113:        // 現在のフェーズ
                    114:        SCSI::Phase phase {};
                    115: 
                    116:        // SEL, BSY は同時に複数が重畳出来るので、アサートしたデバイスがそれぞれ
                    117:        // 自身の ID を立てる。ネゲートは 0 かどうかで判断する。
                    118:        // 現在の実装では実際には同時に立つことはないけど。
                    119:        bool rst {};
                    120:        bool req {};
                    121:        bool ack {};
                    122:        bool atn {};
                    123:        uint8 sel {};
                    124:        uint8 bsy {};
                    125:        uint8 xfer {};  // MSG,CD,IO
                    126:        uint8 data {};
                    127:        // bool parity; 未実装
                    128: 
                    129:        // 前回 ACK を立てた時刻。
                    130:        // 転送速度をここで律速させている。
1.1.1.3   root      131:        uint64 last_req_time {};
                    132: 
1.1.1.13! root      133:        // 次の REQ アサートに入れるウェイト [tsec]
1.1.1.3   root      134:        uint64 req_wait {};
1.1       root      135: 
                    136:        // 実際のバスではそんなことはないが、ここではバスがイニシエータと
                    137:        // ターゲットの ID を把握している。どちらも非選択状態なら -1。
                    138:        int init_id {};
                    139:        int target_id {};
                    140: 
1.1.1.11  root      141:        // SCSI 管理
                    142:        SCSIDomain *domain {};
1.1.1.9   root      143: 
1.1.1.11  root      144:        // 接続されているデバイス (イニシエータも含む) へのポインタ。
                    145:        std::array<SCSIDevice *, 8> device {};
1.1.1.9   root      146: 
1.1       root      147:        // イベント
1.1.1.12  root      148:        Event *event {};
1.1.1.9   root      149: };

unix.superglobalmegacorp.com

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