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

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