|
|
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: // 可能性のあるものも処理できる。
1.1.1.17! root 60: // 継承クラスの Create() は Device::Create() を呼ぶ必要はない。
1.1.1.14 root 61: // putmsg() は使えない。
1.1 root 62: //
1.1.1.17! root 63: // 3. EarlyInit() ... ログ出力の初期化
! 64: // ここですべての Device に対してログ出力のための変数を初期化する。
! 65: // ただし putmsg() が使えるのは 4. 以降。
! 66: // これは override しない。
! 67: //
! 68: // 4. 設定とログの締め切り。
! 69: // これ以降 gConfig の変更は出来ない。
! 70: // またログの割り当てを受ける Object 由来のオブジェクトはすべて出揃って
! 71: // いる必要がある。
! 72: // 4.1 この時点で gConfig の内容は確定したので、--show-config を行う。
! 73: // 4.2 ParseLogopt() ... -L オプションの処理。
! 74: //
! 75: // 5. Create2() ... 動的コンストラクションその2
! 76: // 作成にあたってログ出力をしたいホストドライバのためのフェーズ。
! 77: // ログは既存のものから従属するしか出来ない。
! 78: // putmsg() は使える。
! 79: // EarlyInit() は Create2() のループ後に改めて呼ばれる。
1.1 root 80: //
1.1.1.17! root 81: // 6. ParseMonitors() ... -M オプションの処理
! 82: // (GUI 版のみ) この時点で Monitor はすべて登録されている必要がある。
1.1.1.10 root 83: //
1.1.1.17! root 84: // 7. Init() ... 初期化
1.1.1.13 root 85: // この時点で Object 由来のオブジェクトはすべて出揃っているため、他の
1.1.1.17! root 86: // Object はすべてアクセス可能。
! 87: // 継承クラスは Device::Init() を呼ぶ必要はないが、子クラスが親クラスの
! 88: // Init() を呼ぶことを要求することはあるかもしれない。
1.1.1.12 root 89: // gConfig の設定項目のうち内容によってエラー終了する可能性があるものは
1.1.1.14 root 90: // ここまでに処理する。
1.1.1.15 root 91: // 複数のオブジェクトが同じ設定項目を処理しないようにすること (複数で
92: // 別々に読んでその際の範囲チェックに齟齬が発生するとかを避けるため)。
1.1.1.13 root 93: // Object 同士は完全に相互アクセス可能だが、Init() 自身の依存関係
94: // (A::Init() で設定した値を B::Init() が参照する必要があるケース) に
95: // ついては vm.cpp (などコンテナデバイス) 内のコンストラクタの順序で
96: // 手動調整すること (循環参照不可)。
1.1.1.12 root 97: //
1.1.1.17! root 98: // 8. StartThread() ... スレッド起動
1.1 root 99: //
1.1.1.17! root 100: // 9. Apply() ... 動的設定の適用
1.1 root 101: // 実行中に変更可能なパラメータもここで一度適用する。
1.1.1.12 root 102: // ここで適用するのは実行中に変更可能なパラメータのみ。
103: // 適用内容を表示したい時は putlog(1) が妥当か。
1.1 root 104: //
1.1.1.17! root 105: // 10. ResetHard(true) ... 電源オン
! 106:
! 107: // ログの初期化。
! 108: void EarlyInit();
1.1 root 109:
110: // 動的コンストラクション。
1.1.1.12 root 111: // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
112: // 系でエラーメッセージを表示して false を返すこと。
1.1 root 113: virtual bool Create();
114:
1.1.1.17! root 115: // 動的コンストラクションその2。
! 116: // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
! 117: // 系でエラーメッセージを表示して false を返すこと。
! 118: // putmsg() は使える。
! 119: virtual bool Create2();
! 120:
1.1 root 121: // 初期化。
1.1.1.12 root 122: // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
123: // 系でエラーメッセージを表示して false を返すこと。
1.1 root 124: virtual bool Init();
125:
126: // 現在の設定を VM に反映させる。
1.1.1.12 root 127: // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
128: // 系でエラーメッセージを表示して false を返すこと。
1.1 root 129: // といっても false が返されたらどうするんだろうか。
130: virtual bool Apply();
131:
1.1.1.12 root 132: // 電源オンもしくはリセット。
133: // true なら電源オン、false ならリセット。
1.1.1.8 root 134: // このデバイスがどのタイミングでリセットされるかは VM による。
135: // X68030 なら vm_x68k.cpp 内のコメント参照。
136: // LUNA は詳細不明。
1.1.1.12 root 137: virtual void ResetHard(bool poweron);
138:
139: // 電源オフ
140: virtual void PowerOff();
141:
142: // ログ出力
143: void putlogn(const char *fmt, ...) const override __printflike(2, 3);
1.1.1.13 root 144:
145: protected:
146: // ログに時刻と PPC を出すために必要
1.1.1.16 root 147: MainMPUDevice *mpu {};
1.1.1.13 root 148: Scheduler *scheduler {};
1.1 root 149: };
150:
151: class IODevice : public Device
152: {
1.1.1.4 root 153: using inherited = Device;
1.1 root 154: protected:
1.1.1.16 root 155: explicit IODevice(uint objid_);
1.1 root 156: public:
1.1.1.15 root 157: ~IODevice() override;
1.1 root 158:
159: public:
1.1.1.16 root 160: // メイン CPU からのデバイスの読み込み。
161: // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
162: // busdata.Size にはポートサイズ (応答バイト数) を返す。
163: // 戻り値 busdata.Data は下詰めし、不要な上位バイトはクリアして返すこと。
164: virtual busdata Read(busaddr addr);
165:
166: // メイン CPU からのデバイスへの書き込み。
167: // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
168: // data は Size バイト分が下詰めされており、上位の不要バイトはクリア済み。
169: // 戻り値の busdata.Size にはポートサイズを返すこと。
170: virtual busdata Write(busaddr addr, uint32 data);
171:
172: // メイン CPU からのバーストアクセス。
173: // addr (16バイト境界) からの 16 バイトを転送してウェイトと OK を返す。
174: // dst/src の uint32 はホストエンディアン。
175: // バースト転送をサポートしてなければ BusData::BusErr を返す。
176: virtual busdata ReadBurst16(busaddr addr, uint32 *dst);
177: virtual busdata WriteBurst16(busaddr addr, const uint32 *src);
178:
179: // XP からのデバイスの読み込み。
180: // 戻り値は busdata.Data の1バイトと必要なら Wait。他は使用しない。
181: virtual busdata Read1(uint32 addr);
182:
183: // XP からのデバイスへの書き込み。
184: // data は1バイト。
185: // 戻り値は busdata.Wait のみ。他は使用しない。
186: virtual busdata Write1(uint32 addr, uint32 data);
1.1.1.13 root 187:
1.1.1.16 root 188: // Peek1() はデバッガアクセスで読み込んだ値を (uint32) で返す。
1.1.1.13 root 189: // バイトアクセスした時に読める値ではなく、現在このアドレスに見えている
1.1.1.16 root 190: // であろう値。バスエラーなら BusData::BusErr を返す。
191: virtual busdata Peek1(uint32 addr);
1.1 root 192:
1.1.1.16 root 193: // Poke1() はデバッガからこのアドレス(メモリ)へ書き込む。
1.1.1.13 root 194: // メモリでない領域 (レジスタなど) は書き込み不可。
1.1.1.15 root 195: // data が (int32 で) 非負なら data の下位8ビットを書き込む。
196: // 書き込めれば true、書き込めなければ false を返す。
1.1.1.13 root 197: // data が (int32 で) 負なら addr への書き込み可否の問い合わせで、
1.1.1.15 root 198: // 書き込み可能なら true、書き込み不可能なら false を返す。
1.1.1.16 root 199: virtual bool Poke1(uint32 addr, uint32 data);
1.1 root 200: };
201:
202: class BusErrDevice : public IODevice
203: {
1.1.1.4 root 204: using inherited = IODevice;
1.1 root 205: public:
206: BusErrDevice();
1.1.1.15 root 207: ~BusErrDevice() override;
1.1 root 208:
209: public:
1.1.1.16 root 210: busdata Read(busaddr addr) override;
211: busdata Write(busaddr addr, uint32 data) override;
212: busdata Peek1(uint32 addr) override;
1.1 root 213: };
214:
215: // 何もしないデバイス。
216: // 読み込むと全域で 0xff が読めて、書き込んでも何も起きない。
1.1.1.10 root 217: class NopIODevice : public IODevice
1.1 root 218: {
1.1.1.4 root 219: using inherited = IODevice;
1.1 root 220: public:
1.1.1.10 root 221: NopIODevice();
1.1.1.15 root 222: ~NopIODevice() override;
1.1 root 223:
224: public:
1.1.1.16 root 225: busdata Read(busaddr addr) override;
226: busdata Write(busaddr addr, uint32 data) override;
227: busdata Read1(uint32 addr) override;
228: busdata Write1(uint32 addr, uint32 data) override;
229: busdata Peek1(uint32 addr) override;
1.1 root 230: };
231:
1.1.1.13 root 232: static inline BusErrDevice *GetBusErrDevice() {
233: return Object::GetObject<BusErrDevice>(OBJ_BUSERR);
234: }
235: static inline NopIODevice *GetNopIODevice() {
236: return Object::GetObject<NopIODevice>(OBJ_NOPIO);
237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.