|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.