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