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