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

1.1       root        1: //
                      2: // nono
1.1.1.4   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: // デバイスの基本クラスなど
                      9: //
                     10: 
1.1       root       11: #pragma once
                     12: 
                     13: #include "object.h"
                     14: 
                     15: #if BYTE_ORDER == LITTLE_ENDIAN
                     16: #define HB(addr)       ((addr) ^ 1)
                     17: #define HLB(addr)      ((addr) ^ 3)
                     18: #define HLW(addr)      ((addr) ^ 2)
                     19: #else
                     20: #define HB(addr)       (addr)
1.1.1.5   root       21: #define HLB(addr)      (addr)
                     22: #define HLW(addr)      (addr)
1.1       root       23: #endif
                     24: 
1.1.1.13! root       25: // 前方参照
        !            26: class MPUDevice;
        !            27: class Scheduler;
        !            28: class SCSIDevice;
        !            29: class SCSIDisk;
        !            30: class SCSITarget;
        !            31: 
1.1       root       32: class Device : public Object
                     33: {
1.1.1.4   root       34:        using inherited = Object;
1.1       root       35:  protected:
1.1.1.13! root       36:        Device(int objid_);
1.1       root       37:  public:
1.1.1.7   root       38:        virtual ~Device() override;
1.1       root       39: 
                     40:  public:
                     41:        // 初期化は以下の手順で行う。
                     42:        // 1. コンストラクタ
                     43:        //      メンバ変数の初期値代入などを行う。失敗するケースは考慮していない。
1.1.1.4   root       44:        //      gConfig の内部変数の追加はここ(か2.の動的コンストラクション)で
                     45:        //      行うこと。この時点ですでに gConfig の設定内容の参照は可能だが、
                     46:        //      エラーが出るものはここではなく Init() で処理すること。
1.1.1.12  root       47:        //      putmsg() は使えない。
1.1       root       48:        //
                     49:        // 2. Create() ... 動的コンストラクション
                     50:        //      必要なら設定ファイルによって可変なオブジェクトのコンストラクトを行う。
1.1.1.12  root       51:        //      例えば SCSI ドライブなどが該当する。ここでも gConfig の参照および
                     52:        //      内部変数の登録は可能、putmsg() は使えない。
1.1       root       53:        //
                     54:        // 3. parse_logopt() ... -L オプションの処理
1.1.1.12  root       55:        //      この時点でログの割り当てを受ける Object 由来のオブジェクトはすべて
                     56:        //      出揃っている必要がある。
1.1.1.4   root       57:        //      またここで --show-config も行うため、この時点で gConfig の内容は確定し
                     58:        //      以降 gConfig の変更は出来ない。
1.1       root       59:        //
1.1.1.12  root       60:        // (4.) ParseMonitors() ... -M オプションの処理
1.1.1.10  root       61:        //      (GUI 版のみ) この時点で Monitor がすべて登録されている必要がある。
                     62:        //
1.1.1.12  root       63:        // 5. Init() ... 初期化
1.1.1.13! root       64:        //      この時点で Object 由来のオブジェクトはすべて出揃っているため、他の
        !            65:        //      Object はすべてアクセス可能。また、ログレベルも確定しているのでこれ
        !            66:        //      以降 putmsg() は使える。
        !            67:        //      基底クラスの Device::Init() がログ出力に必要なメンバ変数を初期化して
        !            68:        //      いるため、派生クラスで Init() を用意した場合は必ず inherited::Init()
        !            69:        //      を呼ぶこと。
1.1.1.12  root       70:        //      gConfig の設定項目のうち内容によってエラー終了する可能性があるものは
                     71:        //      ここで処理する。
1.1.1.13! root       72:        //      Object 同士は完全に相互アクセス可能だが、Init() 自身の依存関係
        !            73:        //      (A::Init() で設定した値を B::Init() が参照する必要があるケース) に
        !            74:        //      ついては vm.cpp (などコンテナデバイス) 内のコンストラクタの順序で
        !            75:        //      手動調整すること (循環参照不可)。
1.1.1.12  root       76:        //      ホストデバイスの個別ドライバはここで起動する。本来 Create() で行いたい
                     77:        //      ところだが、ネットワークドライバの選択などは複雑なので putmsg() を
                     78:        //      使いたい。そうするとここまで遅延せざるを得ない。そのため 3. を過ぎて
                     79:        //      からオブジェクトが増えることになるが、個別ドライバは新たなログ名を
                     80:        //      増やさず、ホストドライバのログレベルを継承するため、ぎりぎり大丈夫。
                     81:        //      スレッドはまだ起動していない。
                     82:        //
                     83:        // 6. StartThread() ... スレッド起動
1.1       root       84:        //
1.1.1.12  root       85:        // 7. Apply() ... 動的設定の適用
1.1       root       86:        //      実行中に変更可能なパラメータもここで一度適用する。
1.1.1.12  root       87:        //      ここで適用するのは実行中に変更可能なパラメータのみ。
                     88:        //      適用内容を表示したい時は putlog(1) が妥当か。
1.1       root       89:        //
1.1.1.12  root       90:        // 8. ResetHard(true) ... 電源オン
1.1       root       91: 
                     92:        // 動的コンストラクション。
1.1.1.12  root       93:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                     94:        // 系でエラーメッセージを表示して false を返すこと。
1.1       root       95:        virtual bool Create();
                     96: 
                     97:        // 初期化。
1.1.1.12  root       98:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                     99:        // 系でエラーメッセージを表示して false を返すこと。
1.1       root      100:        virtual bool Init();
                    101: 
                    102:        // 現在の設定を VM に反映させる。
1.1.1.12  root      103:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                    104:        // 系でエラーメッセージを表示して false を返すこと。
1.1       root      105:        // といっても false が返されたらどうするんだろうか。
                    106:        virtual bool Apply();
                    107: 
1.1.1.12  root      108:        // 電源オンもしくはリセット。
                    109:        // true なら電源オン、false ならリセット。
1.1.1.8   root      110:        // このデバイスがどのタイミングでリセットされるかは VM による。
                    111:        // X68030 なら vm_x68k.cpp 内のコメント参照。
                    112:        // LUNA は詳細不明。
1.1.1.12  root      113:        virtual void ResetHard(bool poweron);
                    114: 
                    115:        // 電源オフ
                    116:        virtual void PowerOff();
                    117: 
                    118:        // ログ出力
                    119:        void putlogn(const char *fmt, ...) const override __printflike(2, 3);
1.1.1.13! root      120: 
        !           121:  protected:
        !           122:        // ログに時刻と PPC を出すために必要
        !           123:        MPUDevice *mpu {};
        !           124:        Scheduler *scheduler {};
1.1       root      125: };
                    126: 
                    127: class IODevice : public Device
                    128: {
1.1.1.4   root      129:        using inherited = Device;
1.1       root      130:  protected:
1.1.1.13! root      131:        IODevice(int objid_);
1.1       root      132:  public:
1.1.1.7   root      133:        virtual ~IODevice() override;
1.1       root      134: 
1.1.1.13! root      135:        bool Init() override;
        !           136: 
1.1       root      137:  public:
                    138:        // アクセス関数。
                    139:        // Read*() は読み込んだ値を (uint32) で返す。
                    140:        // Write*() は書き込めたら 0 を返す。
                    141:        // いずれもバスエラーなら (uint64)-1 を返す。
                    142:        virtual uint64 Read8(uint32 addr);
                    143:        virtual uint64 Read16(uint32 addr);
                    144:        virtual uint64 Read32(uint32 addr);
                    145:        virtual uint64 Write8(uint32 addr, uint32 data);
                    146:        virtual uint64 Write16(uint32 addr, uint32 data);
                    147:        virtual uint64 Write32(uint32 addr, uint32 data);
1.1.1.13! root      148: 
        !           149:        // Peek8() はデバッガアクセスで読み込んだ値を (uint32) で返す。
        !           150:        // バイトアクセスした時に読める値ではなく、現在このアドレスに見えている
        !           151:        // であろう値。バスエラーなら (uint64)-1 を返す。
1.1       root      152:        virtual uint64 Peek8(uint32 addr);
                    153: 
1.1.1.13! root      154:        // Poke8() はデバッガからこのアドレス(メモリ)へ書き込む。
        !           155:        // メモリでない領域 (レジスタなど) は書き込み不可。
        !           156:        // data が (int32 で) 非負なら data (の下位8ビット)を書き込む。
        !           157:        // 書き込めれば 0、書き込めなければ (uint64)-1 を返す。
        !           158:        // data が (int32 で) 負なら addr への書き込み可否の問い合わせで、
        !           159:        // 書き込み可能なら 0、書き込み不可能なら (uint64)-1 を返す。
        !           160:        virtual uint64 Poke8(uint32 addr, uint32 data);
        !           161: 
        !           162:  protected:
        !           163:        // BusIO インタフェース。
        !           164:        // BusIO を経由するデバイスはほとんどが Poke 不可なので、
        !           165:        // ベースクラスに用意しておく。
        !           166:        virtual uint64 Poke(uint32 addr, uint32 data);
        !           167: };
        !           168: 
        !           169: // コンテナデバイス (複数の IODevice を格納するデバイス)。
        !           170: class IOContainerDevice : public IODevice
        !           171: {
        !           172:        using inherited = IODevice;
        !           173:  protected:
        !           174:        IOContainerDevice(int objid_);
        !           175:  public:
        !           176:        virtual ~IOContainerDevice() override;
        !           177: 
        !           178:        // このアドレスを担当する IODevice を再帰的に探して返す。
        !           179:        IODevice *FindDevice(uint32 addr) const;
1.1       root      180: 
1.1.1.13! root      181:  protected:
        !           182:        // このアドレスを担当する次段の IODevice を返す。
        !           183:        virtual IODevice *GetDevice(uint32 addr) const = 0;
1.1       root      184: };
                    185: 
                    186: class BusErrDevice : public IODevice
                    187: {
1.1.1.4   root      188:        using inherited = IODevice;
1.1       root      189:  public:
                    190:        BusErrDevice();
1.1.1.7   root      191:        virtual ~BusErrDevice() override;
1.1       root      192: 
                    193:  public:
1.1.1.4   root      194:        uint64 Read8(uint32 addr) override;
                    195:        uint64 Read16(uint32 addr) override;
                    196:        uint64 Read32(uint32 addr) override;
                    197:        uint64 Write8(uint32 addr, uint32 data) override;
                    198:        uint64 Write16(uint32 addr, uint32 data) override;
                    199:        uint64 Write32(uint32 addr, uint32 data) override;
                    200:        uint64 Peek8(uint32 addr) override;
1.1       root      201: };
                    202: 
                    203: // 何もしないデバイス。
                    204: // 読み込むと全域で 0xff が読めて、書き込んでも何も起きない。
1.1.1.10  root      205: class NopIODevice : public IODevice
1.1       root      206: {
1.1.1.4   root      207:        using inherited = IODevice;
1.1       root      208:  public:
1.1.1.10  root      209:        NopIODevice();
                    210:        virtual ~NopIODevice() override;
1.1       root      211: 
                    212:  public:
1.1.1.4   root      213:        uint64 Read8(uint32 addr) override;
1.1.1.8   root      214:        uint64 Read16(uint32 addr) override;
                    215:        uint64 Read32(uint32 addr) override;
1.1.1.4   root      216:        uint64 Write8(uint32 addr, uint32 data) override;
1.1.1.8   root      217:        uint64 Write16(uint32 addr, uint32 data) override;
                    218:        uint64 Write32(uint32 addr, uint32 data) override;
1.1.1.4   root      219:        uint64 Peek8(uint32 addr) override;
1.1       root      220: };
                    221: 
1.1.1.13! root      222: static inline BusErrDevice *GetBusErrDevice() {
        !           223:        return Object::GetObject<BusErrDevice>(OBJ_BUSERR);
        !           224: }
        !           225: static inline NopIODevice *GetNopIODevice() {
        !           226:        return Object::GetObject<NopIODevice>(OBJ_NOPIO);
        !           227: }

unix.superglobalmegacorp.com

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