|
|
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: // SPC (MB89352)
9: //
10:
1.1 root 11: #pragma once
12:
13: #include "device.h"
14: #include "fixedqueue.h"
1.1.1.17 root 15: #include "mainapp.h"
1.1.1.18 root 16: #include "scsi.h"
17: #include "scsibus.h"
1.1 root 18:
1.1.1.14 root 19: class InterruptDevice;
1.1.1.18 root 20: class SCSIDomain;
1.1.1.16 root 21: class SCSIHostDevice;
1.1.1.14 root 22:
1.1 root 23: struct SPC
24: {
1.1.1.16 root 25: static const uint BDID = 0x0; // $E96021 RW $E100_0000
26: static const uint SCTL = 0x1; // $E96023 RW $E100_0004
27: static const uint SCMD = 0x2; // $E96025 RW $E100_0008
28: static const uint TMOD = 0x3; // (MB89352 にはない)
29: static const uint INTS = 0x4; // $E96029 RW $E100_0010
30: static const uint PSNS = 0x5; // $E9602B R- $E100_0014
31: static const uint SDGC = 0x5; // $E9602B -W $E100_0014
32: static const uint SSTS = 0x6; // $E9602D R- $E100_0018
33: static const uint SERR = 0x7; // $E9602F R- $E100_001C
34: static const uint PCTL = 0x8; // $E96031 RW $E100_0020
35: static const uint MBC = 0x9; // $E96033 R- $E100_0024
36: static const uint DREG = 0xa; // $E96035 RW $E100_0028
37: static const uint TEMP = 0xb; // $E96037 RW $E100_002C
38: static const uint TCH = 0xc; // $E96039 RW $E100_0030
39: static const uint TCM = 0xd; // $E9603B RW $E100_0034
40: static const uint TCL = 0xe; // $E9603D RW $E100_0038
41: static const uint EXBF = 0xf; // (MB89352 にはない)
1.1 root 42:
43:
44: // SCTL レジスタ
45: // 全ビットを保持。
46: uint8 sctl;
1.1.1.16 root 47: static const uint SCTL_RESET = 0x80; // Reset & Disable
48: static const uint SCTL_CTL_RESET = 0x40; // Control Reset
49: static const uint SCTL_DIAG_MODE = 0x20; // Diag Mode
50: static const uint SCTL_ARBIT_EN = 0x10; // Arbitration Enable
51: static const uint SCTL_PARITY_EN = 0x08; // Parity Enable
52: static const uint SCTL_SEL_EN = 0x04; // Select Enable
53: static const uint SCTL_RESEL_EN = 0x02; // Reselect Enable
54: static const uint SCTL_INTR_EN = 0x01; // Interrupt Enable
1.1 root 55:
56: // SCMD レジスタ
1.1.1.2 root 57: // 全ビットを保持。
1.1 root 58: uint8 scmd;
1.1.1.16 root 59: static const uint SCMD_CMD_MASK = 0xe0; // Command code
60: static const uint SCMD_RST_OUT = 0x10; // RST Out
61: static const uint SCMD_INTERCEPT = 0x08; // Intersept Transfer
62: static const uint SCMD_PROGRAM = 0x04; // Program Transfer
63: static const uint SCMD_TERM_MODE = 0x01; // Termination Mode
1.1 root 64:
65: // INTS レジスタ
1.1.1.7 root 66: //
67: // 内部変数 ints は割り込み状態を一度に判別するため SERR レジスタの
68: // xfer ビット(SERR_XFER_OUT) もここの bit8 に含めている。
69: // 残りの下位8ビットは INTS と同じ。
70: //
1.1.1.19 root 71: // b8 b7 b6 b5 b4 b3 b2 b1 b0
72: // +----+----+----+----+----+----+----+----+
1.1.1.7 root 73: // INTS |SEL |RESL|DIS |CMPL|SERV|TOUT|HERR|REST|
1.1.1.19 root 74: // +----+----+----+----+----+----+----+----+
1.1.1.7 root 75: //
1.1.1.19 root 76: // +----+----+----+----+----+----+----+----+----+
77: // ints変数 |xfer|SEL |RESL|DIS |CMPL|SERV|TOUT|HERR|REST|
78: // +----+----+----+----+----+----+----+----+----+
1.1.1.7 root 79: uint16 ints;
1.1.1.16 root 80: static const uint INTS_SELECTED = 0x80; // Selected
81: static const uint INTS_RESELECTED = 0x40; // Reselected
82: static const uint INTS_DISCONNECTED = 0x20; // Disconnected
83: static const uint INTS_COMPLETE = 0x10; // Command Complete
84: static const uint INTS_SERV_REQ = 0x08; // Service Required
85: static const uint INTS_TIMEOUT = 0x04; // Time Out
86: static const uint INTS_HARD_ERR = 0x02; // SPC Hard Error
87: static const uint INTS_RESET_COND = 0x01; // Reset Condition
1.1 root 88:
1.1.1.16 root 89: static const uint INTS_XFER_OUT = 0x100; // SERR_XFER_OUT
1.1.1.7 root 90:
91: // 割り込みマスク (INTS_RESET_COND はノンマスカブル割り込み)
92: uint16 ints_mask;
1.1.1.16 root 93: static const uint INTS_ENABLE_MASK = 0x01ff;
94: static const uint INTS_DISABLE_MASK = 0x0001;
1.1.1.7 root 95:
1.1 root 96: // PSNS レジスタ
97: uint8 psns;
1.1.1.16 root 98: static const uint PSNS_REQ = 0x80;
99: static const uint PSNS_ACK = 0x40;
100: static const uint PSNS_ATN = 0x20;
101: static const uint PSNS_SEL = 0x10;
102: static const uint PSNS_BSY = 0x08;
103: static const uint PSNS_MSG = 0x04;
104: static const uint PSNS_CD = 0x02;
105: static const uint PSNS_IO = 0x01;
1.1 root 106:
107: // SDGC レジスタ
108: uint8 sdgc;
1.1.1.16 root 109: static const uint SDGC_XFER_ENABLE = 0x20;
1.1 root 110:
111: // SSTS レジスタ
112: // 上位4ビットを保持。下位4ビットは読み出し時に生成。
113: uint8 ssts;
1.1.1.16 root 114: static const uint SSTS_CONN_INIT = 0x80; // Connected (Initiator)
115: static const uint SSTS_CONN_TARG = 0x40; // Connected (Target)
116: static const uint SSTS_SPC_BUSY = 0x20; // SPC Busy
117: static const uint SSTS_IN_PROGRESS = 0x10; // Transfer in Progress
118: static const uint SSTS_RST_IN = 0x08; // SCSI RST In
119: static const uint SSTS_TC_ZERO = 0x04; // TC=0
120: static const uint SSTS_DREG_FULL = 0x02; // DREG Status (Full)
121: static const uint SSTS_DREG_EMPTY = 0x01; // DREG Status (Empty)
1.1 root 122:
123: // SERR レジスタ
1.1.1.7 root 124: // XFER_OUT 以外の4つの有効ビットを保持。
125: // XFER_OUT は ints が担当している。
1.1 root 126: uint8 serr;
1.1.1.16 root 127: static const uint SERR_DATAERR_SCSI = 0x80; // Data Error: SCSI
128: static const uint SERR_DATAERR_SPC = 0x40; // Data Error: SPC
129: static const uint SERR_XFER_OUT = 0x20; // Xfer Out
130: static const uint SERR_TC_PARITY_ERR= 0x08; // TC Parity Error
131: static const uint SERR_SHORT_XFER = 0x02; // Short Transfer Period
1.1 root 132:
133: // PCTL レジスタ
1.1.1.11 root 134: // BusFree INT Enable は独立して保持。
135: // MSG, CD, IO の3ビットは pctl_out で保持。
1.1 root 136: bool busfree_intr_enable;
1.1.1.11 root 137: uint8 pctl_out;
1.1.1.16 root 138: static const uint PCTL_MASK = 0x87; // 書き込みマスク
139: static const uint PCTL_BFINT_EN = 0x80; // BusFree INT Enable
140: static const uint PCTL_MSG = 0x04;
141: static const uint PCTL_CD = 0x02;
142: static const uint PCTL_IO = 0x01;
1.1 root 143:
144: FixedQueue<uint8, 8> dreg; // DREG レジスタ
145:
146: uint8 temp_in; // TEMP レジスタ (SCSI -> MPU)
147: uint8 temp_out; // TEMP レジスタ (MPU -> SCSI)
148: uint32 tc; // TC
149:
150: uint32 GetTCL() const { return tc & 0x0000ff; } // TCL
151:
152: // MBC (内部の読み込み専用レジスタ)
153: // TC の下位4ビットが読めるらしい
154: uint8 mbc() const {
155: return tc & 15;
156: }
157: };
158:
1.1.1.16 root 159: class SPCDevice : public IODevice
1.1 root 160: {
1.1.1.16 root 161: using inherited = IODevice;
1.1 root 162: public:
1.1.1.3 root 163: SPCDevice();
1.1.1.15 root 164: ~SPCDevice() override;
1.1 root 165:
1.1.1.18 root 166: void SetLogLevel(int loglevel_) override;
1.1.1.16 root 167: bool Create() override;
1.1.1.4 root 168: bool Init() override;
1.1.1.12 root 169: void ResetHard(bool poweron) override;
1.1 root 170:
1.1.1.18 root 171: SCSIDomain *GetDomain() const noexcept { return domain.get(); }
1.1 root 172:
1.1.1.8 root 173: // BusIO インタフェース
174: // (内蔵 ROM からのアクセス用に特別に public にしてある)
1.1.1.16 root 175: busdata WritePort(uint32 offset, uint32 data);
1.1.1.3 root 176: protected:
177: static const uint32 NPORT = 16;
1.1.1.16 root 178: busdata ReadPort(uint32 offset);
179: busdata PeekPort(uint32 offset);
180: bool PokePort(uint32 offset, uint32 data);
1.1.1.3 root 181:
1.1 root 182: private:
1.1.1.20! root 183: DECLARE_MONITOR_SCREEN(MonitorScreen);
1.1.1.10 root 184:
1.1.1.5 root 185: void MonitorReg(TextScreen&,
186: int x, int y, uint32 reg, const char * const *names);
1.1 root 187:
1.1.1.16 root 188: // バスフリーになった (SCSIHostDevice からのコールバック)
189: void BusFreeCallback(uint id);
190:
191: // ターゲットがセレクションに応答した (SCSIHostDevice からのコールバック)
192: void SelectionAckCallback();
193:
194: // 情報転送フェーズで REQ を立てた (SCSIHostDevice からのコールバック)
195: void TransferReqCallback();
196:
1.1 root 197: // SCTL レジスタへの書き込み
198: void WriteSCTL(uint32);
1.1.1.7 root 199: // 割り込みマスクの再構成
200: void MakeIntsMask();
1.1 root 201:
202: // SCMD レジスタへの書き込み
203: void WriteSCMD(uint32);
204:
205: // INTS レジスタへの書き込み
206: void WriteINTS(uint32);
1.1.1.3 root 207: // 表示のための前回値
208: uint32 prev_ints {};
1.1 root 209:
210: // INTS 設定
211: void SetINTS(uint32);
1.1.1.7 root 212: // INTS レジスタ値の取得
213: uint32 GetINTS() const;
214: // 割り込み信号線の状態を変える
215: void ChangeInterrupt();
1.1 root 216:
217: // PSNS レジスタ値の取得
218: uint32 GetPSNS() const;
219:
220: // SSTS レジスタ値の取得
221: uint32 GetSSTS() const;
1.1.1.3 root 222: // 表示のための前回値
223: uint32 prev_ssts {};
1.1 root 224:
1.1.1.7 root 225: // SERR レジスタ値の取得
226: uint32 GetSERR() const;
227:
1.1.1.11 root 228: // PCTL レジスタへの書き込み
229: void WritePCTL(uint32);
1.1 root 230: // PCTL レジスタ値の取得
231: uint32 GetPCTL() const;
232:
1.1.1.3 root 233: // DREG レジスタアクセス
1.1.1.15 root 234: busdata ReadDREG();
235: busdata WriteDREG(uint32 data);
1.1.1.3 root 236:
1.1 root 237: // バスフリーフェーズに移行する
238: void BusFree();
1.1.1.2 root 239: // 直近のバスフリーフェーズになった時刻
240: // (アービトレーション/セレクション開始時に使う)
241: uint64 last_busfree_time {};
242: // バスをリリースする
243: void BusRelease();
1.1 root 244:
245: // Select コマンド実行
246: void SelectCommand();
1.1.1.19 root 247: void Arbitration1(Event *);
248: void Arbitration2(Event *);
249: void Selection1(Event *);
250: void SelectionTimeout(Event *);
1.1.1.2 root 251:
252: // SetATN コマンド実行
253: void SetATNCommand();
254: // セレクションフェーズで ATN を立てる
1.1.1.6 root 255: bool set_atn_in_selection {};
1.1 root 256:
257: // Transfer コマンド実行
258: void TransferCommand();
1.1.1.19 root 259: void HardwareTransfer(Event *);
1.1.1.3 root 260: void TransferComplete();
1.1.1.2 root 261: // Transfer コマンド実行中なら true
1.1.1.6 root 262: bool transfer_command_running {};
1.1 root 263:
264: // SCSI コマンド
265: void ExecCommand();
266:
1.1.1.18 root 267: //
268: // 信号線制御
269: // (ソースコード的なショートカットのため)
270: //
271: bool GetRST() const { return bus->GetRST(); }
272: void AssertRST() { bus->AssertRST(); }
273: void NegateRST() { bus->NegateRST(); }
274: bool GetREQ() const { return bus->GetREQ(); }
275: void AssertREQ() { bus->AssertREQ(); }
276: void NegateREQ() { bus->NegateREQ(); }
277: bool GetACK() const { return bus->GetACK(); }
278: void AssertACK() { bus->AssertACK(); }
279: void NegateACK() { bus->NegateACK(); }
280: bool GetATN() const { return bus->GetATN(); }
281: void AssertATN() { bus->AssertATN(); }
282: void NegateATN() { bus->NegateATN(); }
283: uint8 GetSEL() const { return bus->GetSEL(); }
284: void AssertSEL() { bus->AssertSEL(myid); }
285: void NegateSEL() { bus->NegateSEL(myid); }
286: uint8 GetBSY() const { return bus->GetBSY(); }
287: void AssertBSY() { bus->AssertBSY(myid); }
288: void NegateBSY() { bus->NegateBSY(myid); }
289: bool GetMSG() const { return bus->GetMSG(); }
290: bool GetCD() const { return bus->GetCD(); }
291: bool GetIO() const { return bus->GetIO(); }
292: SCSI::XferPhase GetXfer() const { return bus->GetXfer(); }
293: void SetXfer(uint8 val) { bus->SetXfer(val); }
294: SCSI::Phase GetPhase() const { return bus->GetPhase(); }
295: uint8 GetData() const { return bus->GetData(); }
296: void SetData(uint8 val) const { bus->SetData(val); }
297:
1.1 root 298: // レジスタ
299: struct SPC spc {};
300:
1.1.1.3 root 301: // VM 種別
1.1.1.13 root 302: VMType vmtype {};
1.1 root 303:
1.1.1.16 root 304: // イニシエータの SCSI ID (参照箇所が多いのでコピー)
305: uint myid {};
306:
1.1 root 307: // SPC に入力されるクロック周期 [nsec]
1.1.1.16 root 308: uint64 t_CLF {};
1.1.1.6 root 309:
310: // アクセスウェイト
1.1.1.15 root 311: busdata read_wait {};
312: busdata write_wait {};
1.1.1.6 root 313:
1.1.1.16 root 314: // モニタ表示用
315: uint32 baseaddr {};
316: uint32 regoffset {};
317:
1.1.1.7 root 318: // 割り込み信号線の接続先デバイス
319: InterruptDevice *interrupt {};
320:
1.1 root 321: // イベント
1.1.1.19 root 322: Event *phase_event {};
323: Event *timer_event {};
1.1.1.16 root 324:
1.1.1.18 root 325: // SCSI 管理
326: std::unique_ptr<SCSIDomain> domain /*{}*/;
327:
328: // SCSI ホストアダプタ
329: SCSIHostDevice *host {};
330:
331: // SCSI バス
332: std::unique_ptr<SCSIBus> bus /*{}*/;
1.1.1.10 root 333:
1.1.1.17 root 334: Monitor *monitor {};
1.1 root 335: };
336:
1.1.1.20! root 337: inline SPCDevice *GetSPCDevice() {
! 338: return Object::GetObject<SPCDevice>(OBJ_SPC0);
1.1.1.14 root 339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.