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

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

unix.superglobalmegacorp.com

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