|
|
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.1.19! root 15: #include "nono.h"
1.1 root 16:
17: #if BYTE_ORDER == LITTLE_ENDIAN
18: #define HB(addr) ((addr) ^ 1)
19: #define HLB(addr) ((addr) ^ 3)
20: #define HLW(addr) ((addr) ^ 2)
21: #else
22: #define HB(addr) (addr)
1.1.1.5 root 23: #define HLB(addr) (addr)
24: #define HLW(addr) (addr)
1.1 root 25: #endif
26:
1.1.1.15 root 27: // デバイスを作成して代入するマクロ。
28: // …だったが今となってはあまり意味がなくなっている。
29: #define NEWDV(NAME, NEW_CTOR) do { \
30: __CONCAT(p,NAME).reset(NEW_CTOR); \
1.1.1.16 root 31: assert((bool)__CONCAT(p,NAME)); \
1.1.1.15 root 32: } while (0)
33:
1.1.1.13 root 34: // 前方参照
1.1.1.18 root 35: class Device;
36: class Event;
1.1.1.16 root 37: class MainMPUDevice;
1.1.1.13 root 38: class Scheduler;
39:
1.1.1.18 root 40: using EventCallback_t = void (Device::*)(Event *);
41:
1.1 root 42: class Device : public Object
43: {
1.1.1.4 root 44: using inherited = Object;
1.1 root 45: protected:
1.1.1.16 root 46: explicit Device(uint objid_);
1.1 root 47: public:
1.1.1.15 root 48: ~Device() override;
1.1 root 49:
50: public:
51: // 初期化は以下の手順で行う。
52: // 1. コンストラクタ
53: // メンバ変数の初期値代入などを行う。失敗するケースは考慮していない。
1.1.1.4 root 54: // gConfig の内部変数の追加はここ(か2.の動的コンストラクション)で
55: // 行うこと。この時点ですでに gConfig の設定内容の参照は可能だが、
1.1.1.14 root 56: // エラーが出るものはここではなく Create() か Init() で処理すること。
1.1.1.12 root 57: // putmsg() は使えない。
1.1 root 58: //
59: // 2. Create() ... 動的コンストラクション
60: // 必要なら設定ファイルによって可変なオブジェクトのコンストラクトを行う。
1.1.1.14 root 61: // 例えば SCSI ドライブなどが該当する。Create() で作成したインスタンスの
62: // Create() もこのフェーズで呼ばれる。
63: // ここでも gConfig の参照および内部変数の登録は可能、エラー終了する
64: // 可能性のあるものも処理できる。
1.1.1.17 root 65: // 継承クラスの Create() は Device::Create() を呼ぶ必要はない。
1.1.1.14 root 66: // putmsg() は使えない。
1.1 root 67: //
1.1.1.17 root 68: // 3. EarlyInit() ... ログ出力の初期化
69: // ここですべての Device に対してログ出力のための変数を初期化する。
70: // ただし putmsg() が使えるのは 4. 以降。
71: // これは override しない。
72: //
73: // 4. 設定とログの締め切り。
74: // これ以降 gConfig の変更は出来ない。
75: // またログの割り当てを受ける Object 由来のオブジェクトはすべて出揃って
76: // いる必要がある。
77: // 4.1 この時点で gConfig の内容は確定したので、--show-config を行う。
78: // 4.2 ParseLogopt() ... -L オプションの処理。
79: //
80: // 5. Create2() ... 動的コンストラクションその2
81: // 作成にあたってログ出力をしたいホストドライバのためのフェーズ。
82: // ログは既存のものから従属するしか出来ない。
83: // putmsg() は使える。
84: // EarlyInit() は Create2() のループ後に改めて呼ばれる。
1.1 root 85: //
1.1.1.17 root 86: // 6. ParseMonitors() ... -M オプションの処理
87: // (GUI 版のみ) この時点で Monitor はすべて登録されている必要がある。
1.1.1.10 root 88: //
1.1.1.17 root 89: // 7. Init() ... 初期化
1.1.1.13 root 90: // この時点で Object 由来のオブジェクトはすべて出揃っているため、他の
1.1.1.17 root 91: // Object はすべてアクセス可能。
92: // 継承クラスは Device::Init() を呼ぶ必要はないが、子クラスが親クラスの
93: // Init() を呼ぶことを要求することはあるかもしれない。
1.1.1.12 root 94: // gConfig の設定項目のうち内容によってエラー終了する可能性があるものは
1.1.1.14 root 95: // ここまでに処理する。
1.1.1.15 root 96: // 複数のオブジェクトが同じ設定項目を処理しないようにすること (複数で
97: // 別々に読んでその際の範囲チェックに齟齬が発生するとかを避けるため)。
1.1.1.13 root 98: // Object 同士は完全に相互アクセス可能だが、Init() 自身の依存関係
99: // (A::Init() で設定した値を B::Init() が参照する必要があるケース) に
100: // ついては vm.cpp (などコンテナデバイス) 内のコンストラクタの順序で
101: // 手動調整すること (循環参照不可)。
1.1.1.12 root 102: //
1.1.1.17 root 103: // 8. StartThread() ... スレッド起動
1.1 root 104: //
1.1.1.18 root 105: // 9. ResetHard(true) ... 電源オン
1.1.1.17 root 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:
1.1.1.12 root 126: // 電源オンもしくはリセット。
127: // true なら電源オン、false ならリセット。
1.1.1.8 root 128: // このデバイスがどのタイミングでリセットされるかは VM による。
129: // X68030 なら vm_x68k.cpp 内のコメント参照。
130: // LUNA は詳細不明。
1.1.1.12 root 131: virtual void ResetHard(bool poweron);
132:
133: // 電源オフ
134: virtual void PowerOff();
135:
136: // ログ出力
137: void putlogn(const char *fmt, ...) const override __printflike(2, 3);
1.1.1.13 root 138:
139: protected:
140: // ログに時刻と PPC を出すために必要
1.1.1.16 root 141: MainMPUDevice *mpu {};
1.1.1.13 root 142: Scheduler *scheduler {};
1.1 root 143: };
144:
145: class IODevice : public Device
146: {
1.1.1.4 root 147: using inherited = Device;
1.1 root 148: protected:
1.1.1.16 root 149: explicit IODevice(uint objid_);
1.1 root 150: public:
1.1.1.15 root 151: ~IODevice() override;
1.1 root 152:
153: public:
1.1.1.16 root 154: // メイン CPU からのデバイスの読み込み。
155: // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
156: // busdata.Size にはポートサイズ (応答バイト数) を返す。
157: // 戻り値 busdata.Data は下詰めし、不要な上位バイトはクリアして返すこと。
158: virtual busdata Read(busaddr addr);
159:
160: // メイン CPU からのデバイスへの書き込み。
161: // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
162: // data は Size バイト分が下詰めされており、上位の不要バイトはクリア済み。
163: // 戻り値の busdata.Size にはポートサイズを返すこと。
164: virtual busdata Write(busaddr addr, uint32 data);
165:
166: // メイン CPU からのバーストアクセス。
167: // addr (16バイト境界) からの 16 バイトを転送してウェイトと OK を返す。
168: // dst/src の uint32 はホストエンディアン。
169: // バースト転送をサポートしてなければ BusData::BusErr を返す。
170: virtual busdata ReadBurst16(busaddr addr, uint32 *dst);
171: virtual busdata WriteBurst16(busaddr addr, const uint32 *src);
172:
173: // XP からのデバイスの読み込み。
174: // 戻り値は busdata.Data の1バイトと必要なら Wait。他は使用しない。
175: virtual busdata Read1(uint32 addr);
176:
177: // XP からのデバイスへの書き込み。
178: // data は1バイト。
179: // 戻り値は busdata.Wait のみ。他は使用しない。
180: virtual busdata Write1(uint32 addr, uint32 data);
1.1.1.13 root 181:
1.1.1.16 root 182: // Peek1() はデバッガアクセスで読み込んだ値を (uint32) で返す。
1.1.1.13 root 183: // バイトアクセスした時に読める値ではなく、現在このアドレスに見えている
1.1.1.16 root 184: // であろう値。バスエラーなら BusData::BusErr を返す。
185: virtual busdata Peek1(uint32 addr);
1.1 root 186:
1.1.1.16 root 187: // Poke1() はデバッガからこのアドレス(メモリ)へ書き込む。
1.1.1.13 root 188: // メモリでない領域 (レジスタなど) は書き込み不可。
1.1.1.15 root 189: // data が (int32 で) 非負なら data の下位8ビットを書き込む。
190: // 書き込めれば true、書き込めなければ false を返す。
1.1.1.13 root 191: // data が (int32 で) 負なら addr への書き込み可否の問い合わせで、
1.1.1.15 root 192: // 書き込み可能なら true、書き込み不可能なら false を返す。
1.1.1.16 root 193: virtual bool Poke1(uint32 addr, uint32 data);
1.1 root 194: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.