--- nono/vm/scsi.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/scsi.h 2026/04/29 17:04:29 1.1.1.2 @@ -7,32 +7,76 @@ #include "device.h" +// このクラスは SCSI プロトコル上の定数などだけを持つ。 class SCSI { public: - // デバイス種別 - enum DevType { - None = 0, - HD = 1, + static const uint IO = 0x01; + static const uint CD = 0x02; + static const uint MSG = 0x04; + static const uint BSY = 0x08; + static const uint SEL = 0x10; + + // SCSI のフェーズを表す。 + // フェーズは概ね BSY と SEL の状態遷移によって決まる。 + // 情報転送フェーズの内訳は XferPhase 側で区別する。 + enum Phase { + BusFree = 0, + Arbitration = 1, + Selection = 2, + Reselection = 3, + Transfer = 4, }; - // フェーズは、バスフェーズと転送フェーズを一緒くたで扱う。 - // 0から7までは転送フェーズを表しているのでこの順序を守ること。 - // 8以上はバスフェーズを表している。 - struct Phase { // MSG CD IO - static const uint DataOut = 0x00; // 0 0 0 - static const uint DataIn = 0x01; // 0 0 1 - static const uint Command = 0x02; // 0 1 0 - static const uint Status = 0x03; // 0 1 1 - static const uint MsgOut = 0x06; // 1 1 0 - static const uint MsgIn = 0x07; // 1 1 1 - - static const uint BusFree = 8; - static const uint Arbitration = 9; - static const uint Selection = 10; - static const uint Reselection = 11; + // 情報転送フェーズを表す。 + // この値は MSG,CD,IO で表現できる値をそのまま流用して表現する。 + enum XferPhase { // MSG CD IO + DataOut = 0, // 0 0 0 + DataIn = 1, // 0 0 1 + Command = 2, // 0 1 0 + Status = 3, // 0 1 1 + MsgOut = 6, // 1 1 0 + MsgIn = 7, // 1 1 1 - static const uint MAX = 12; // 最大値 +1 にすること + End = -1, // SCSICmd 内でフェーズ遷移を表現するために使う + }; + + // フェーズ文字列を返す + static const char * const GetPhaseName(int phase) { + return GetPhaseName((Phase)phase); + } + static const char * const GetPhaseName(Phase phase) { + switch (phase) { + case BusFree: return "BusFree"; + case Arbitration: return "Arbitration"; + case Selection: return "Selection"; + case Reselection: return "Reselection"; + case Transfer: return "Transfer"; + } + return "Phase?"; + } + + // 情報転送フェーズ文字列を返す + static const char * const GetXferPhaseName(int xfer) { + return GetXferPhaseName((XferPhase)xfer); + } + static const char * const GetXferPhaseName(XferPhase xfer) { + switch (xfer) { + case DataOut: return "DataOut"; + case DataIn: return "DataIn"; + case Command: return "Command"; + case Status: return "Status"; + case MsgOut: return "MsgOut"; + case MsgIn: return "MsgIn"; + case End: return "End"; + } + return "XferPhase?"; + } + + // デバイス種別 + enum DevType { + None = 0, + HD, }; // コマンド。 @@ -147,135 +191,9 @@ class SCSI uint8 block_size[3]; // 論理ブロック長 (バイト) } __packed; - // フェーズ名を返す。 - static const char *GetPhaseName(uint); - - // SCSI コマンド名を返す。 - static const char *GetCommandName(uint8); + // SCSI コマンド名を返す + static const char *GetCommandName(uint8 cmd); private: - static const char * const phasename[Phase::MAX]; static const char * const commandname[Command::MAX]; }; - -class SCSIHostDevice : public IODevice -{ - typedef IODevice inherited; - public: - SCSIHostDevice(); - virtual ~SCSIHostDevice(); - - virtual bool Create(); - - // このホストデバイスを示す接頭語を取得する - const char *GetConfigName() const { return config_name; } - - // ログ識別子を取得する - const std::string& GetLogName() const { return logname; } - - // 自身の SCSI ID (0..7) - int myid = 0; - - // SCSI ターゲット。[0] が ID0, … - // 未接続とイニシエータは NULL。 - SCSITarget *target[8] {}; - - // Select されているターゲット ID - // 選択されていない状態では -1 - int tgtid = 0; - - // Bus Phase - - // バスフェーズが変化した時刻 - uint64 BusPhaseTime = 0; - - // 各バスフェーズへ遷移する - void B_BusFree(int id); - - bool Arbitration(int id); - bool ArbitrationAck(int id); - - void InitiatorSelection(int targetid); - void TargetSelectionAck(int targetid); - void InitiatorSelectionAck(); - - void TargetReselection(int targetid, int initiatorID); - void InitiatorReselectionAck(); - void TargetReselectionAck(int targetid); - void InitiatorReselectionAck2(); - -#if 0 - // Xfer Phase - SCSI::XferPhase GetXferPhase() const { return xfer_phase; } - - // 各転送フェーズへ遷移する - void X_DataOut(); - void X_DataIn(); - void X_Command(); - void X_Status(); - void X_MsgOut(); - void X_MsgIn(); -#endif - - uint8 DATA = 0; - uint8 GetDATA() const { return DATA; } - void SetDATA(uint8 data); - - // 信号線はいずれも true でアサート - bool REQ = false; // REQ 信号 - bool GetREQ() const { return REQ; } - void SetREQ(bool val); - - bool ACK = false; // ACK 信号 - bool GetACK() const { return ACK; } - void SetACK(bool val); - - // RST も本来は OR-tied だが、ここではあまり意味がないので bool にする。 - bool RST = false; // RST 信号 - bool GetRST() const { return RST; } - void SetRST(bool val); - - uint8 SEL = false; // SEL 信号 - bool GetSEL() const { return SEL != 0; } - void AssertSEL(int id); - void NegateSEL(int id); - - uint8 BSY = false; // BSY 信号 - bool GetBSY() const { return BSY != 0; } - void AssertBSY(int id); - void NegateBSY(int id); - - bool MSG = false; // MSG 信号 - bool GetMSG() const { return MSG; } - void SetMSG(bool val); - - bool CD = false; // CD 信号 - bool GetCD() const { return CD; } - void SetCD(bool val); - - bool IO = false; // IO 信号 - bool GetIO() const { return IO; } - void SetIO(bool val); - - bool ATN = false; // ATN 信号 - bool GetATN() const { return ATN; } - void SetATN(bool val); - - // バスフリーフェーズなら true を返す - bool IsBusFree() const { - return (GetSEL() == false && GetBSY() == false); - } - - // ターゲットがバスフリーフェーズに移行した - virtual void BusRelease() { } - - protected: - // 設定ファイルに使われるこのホストデバイスを示す接頭語。 - // ("spc0" とか) - const char *config_name = NULL; - -#if 0 - SCSI::BusPhase bus_phase; - SCSI::XferPhase xfer_phase; -#endif -};