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