--- nono/vm/spc.h 2026/04/29 17:04:28 1.1 +++ nono/vm/spc.h 2026/04/29 17:04:32 1.1.1.3 @@ -6,9 +6,10 @@ #pragma once #include "device.h" -#include "scsi.h" +#include "scsidev.h" #include "scheduler.h" #include "fixedqueue.h" +#include "vm.h" struct SPC { @@ -44,7 +45,7 @@ struct SPC static const int SCTL_INTR_EN = 0x01; // Interrupt Enable // SCMD レジスタ - // RST は読み出し時に GetRST() から生成。 + // 全ビットを保持。 uint8 scmd; static const int SCMD_CMD_MASK = 0xe0; // Command code static const int SCMD_RST_OUT = 0x10; // RST Out @@ -65,7 +66,6 @@ struct SPC static const int INTS_RESET_COND = 0x01; // Reset Condition // PSNS レジスタ - // REQ, ACK, ATN は今のところ保持? uint8 psns; static const int PSNS_REQ = 0x80; static const int PSNS_ACK = 0x40; @@ -123,20 +123,13 @@ struct SPC uint8 mbc() const { return tc & 15; } - - // Set/Reset ACK/REQ 内部状態 - bool ackreq; }; class SPCDevice : public SCSIHostDevice { typedef SCSIHostDevice inherited; - private: - // X680x0 では $E96000〜 - // LUNA では $E100_0000〜 - public: - SPCDevice(uint32); + SPCDevice(); virtual ~SPCDevice(); virtual bool Init(); @@ -144,20 +137,25 @@ class SPCDevice : public SCSIHostDevice virtual void ResetSoft(); void Reset(); - virtual uint64 Read8(uint32 addr); - virtual uint64 Read16(uint32 addr); - virtual uint64 Write8(uint32 addr, uint32 data); - virtual uint64 Write16(uint32 addr, uint32 data); - virtual uint64 Peek8(uint32 addr); virtual bool MonitorUpdate(); - // イベントコールバック - void BusFreeCallback(int); - void SelectionCompleteCallback(int); - void SelectionFailedCallback(int); + // SCSIBus コールバック + + // バスフリーになった (全員に通知される) + virtual void BusFreeCB(int id); + + // ターゲットがセレクションに応答した (イニシエータのみ通知される) + virtual void SelectionAckCB(); - // ターゲットがバスフリーフェーズに移行した - virtual void BusRelease(); + // 情報転送フェーズで REQ を立てた (イニシエータのみ通知される) + virtual void TransferReqCB(); + + protected: + // BusIO インタフェース + static const uint32 NPORT = 16; + uint64 Read(uint32 addr); + uint64 Write(uint32 addr, uint32 data); + uint64 Peek(uint32 addr); private: void MonitorReg(int x, int y, uint32 reg, const char * const *names); @@ -173,6 +171,8 @@ class SPCDevice : public SCSIHostDevice // INTS レジスタへの書き込み void WriteINTS(uint32); + // 表示のための前回値 + uint32 prev_ints {}; // INTS 設定 void SetINTS(uint32); @@ -182,21 +182,43 @@ class SPCDevice : public SCSIHostDevice // SSTS レジスタ値の取得 uint32 GetSSTS() const; + // 表示のための前回値 + uint32 prev_ssts {}; // PCTL レジスタ値の取得 uint32 GetPCTL() const; + // DREG レジスタアクセス + uint64 ReadDREG(); + uint64 WriteDREG(uint32 data); + // バスフリーフェーズに移行する void BusFree(); + // 直近のバスフリーフェーズになった時刻 + // (アービトレーション/セレクション開始時に使う) + uint64 last_busfree_time {}; + // バスをリリースする + void BusRelease(); // Select コマンド実行 void SelectCommand(); + void Arbitration1(int code); + void Arbitration2(int code); + void Selection1(int code); + void SelectionTimeout(int code); + + // SetATN コマンド実行 + void SetATNCommand(); + // セレクションフェーズで ATN を立てる + bool set_atn_in_selection = false; // Transfer コマンド実行 void TransferCommand(); - - // DREG へのデータの充填 - void EnqueueToDREG(); + void TransferCommandStart(int code); + void HardwareTransfer(int code); + void TransferComplete(); + // Transfer コマンド実行中なら true + bool transfer_command_running = false; // SCSI コマンド void ExecCommand(); @@ -204,24 +226,15 @@ class SPCDevice : public SCSIHostDevice // レジスタ struct SPC spc {}; - uint32 regbase = 0; // レジスタの先頭アドレス - int regstride = 0; // レジスタ間の距離 + // VM 種別 + vmtype_t vmtype {}; // SPC に入力されるクロック周期 [nsec] int t_CLF = 0; - // 現在のフェーズ - uint phase = 0; - - // Command フェーズで受け取ったコマンド列 - std::vector cmds {}; - - // Data{In,Out} フェーズのバッファ - uint8 *dataptr = NULL; - uint datalen = 0; - // イベント Event event {}; + Event event_tc {}; }; -extern SPCDevice *gSPC; +extern std::unique_ptr gSPC;