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