--- nono/vm/scsibus.h 2026/04/29 17:04:36 1.1.1.2 +++ nono/vm/scsibus.h 2026/04/29 17:05:33 1.1.1.10 @@ -4,13 +4,9 @@ // Licensed under nono-license.txt // +// // SCSI バス - -#pragma once - -#include "device.h" -#include "scheduler.h" -#include "scsi.h" +// // フェーズ遷移についてのメモ。 // @@ -96,18 +92,44 @@ // TransferReqCB <-〜〜〜 Event 〜〜〜〜〜〜〜〜〜〜〜〜+ // +#pragma once + +#include "event.h" +#include "scsi.h" + +class SCSIDevice; +class SCSIDisk; +class SCSIHostDevice; +class SCSITarget; // // SCSI バス // class SCSIBus : public Device { + using inherited = Device; + + public: + // (1<& GetConnectedDevices() const { + return connected_devices; + } + + // ターゲットデバイス取得 (ROM エミュレーション/UI用) + SCSITarget *GetTarget(int id) const { return target[id].get(); } + // 現在選択中のターゲットを返す、なければ NULL を返す。(モニタ用) - SCSIDevice *GetConnectedTarget() const { + SCSITarget *GetSelectedTarget() const { if (0 <= target_id && target_id < 8) { - return device[target_id]; + return target[target_id].get(); } return NULL; } + // 次の REQ アサートの前に指定のウェイトを入れる + // (シークタイムなどを簡易的に再現するため)。 + // ウェイトは一度適用されると 0 に戻る。 + void SetOneshotReqWait(uint64 nsec) { req_wait += nsec; } + private: - void BusFree(int id); - void SelectionStart(); - void Selected(int code); - void SelectionAck(int code); - void StartTransfer(int code); - void TransferReq(int code); + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + + // connected_devices を更新する。 + void MakeConnectedDevices(); + + void BusFree(uint id); + void SelectionStart(Event& ev); + void Selected(Event& ev); + void SelectionAck(Event& ev); + void StartTransfer(Event& ev); + void TransferReq(Event& ev); // 現在のフェーズ SCSI::Phase phase {}; @@ -183,28 +229,35 @@ class SCSIBus : public Device // 前回 ACK を立てた時刻。 // 転送速度をここで律速させている。 - uint64 last_req_time = 0; + uint64 last_req_time {}; + + // 次の REQ アサートに入れるウェイト [nsec] + uint64 req_wait {}; + + // 設定ファイルに使われるこのホストデバイスを示す接頭語。 + // ("spc0" とか) + const char *config_name {}; // 実際のバスではそんなことはないが、ここではバスがイニシエータと // ターゲットの ID を把握している。どちらも非選択状態なら -1。 int init_id {}; int target_id {}; - // SCSI デバイス(イニシエータも含む)。非接続なら NULL + // SCSI ターゲット (所有)。イニシエータは含まない。 + std::unique_ptr target[8] /*{}*/; + + // SCSI デバイス(イニシエータも含む)。非接続なら NULL。 // 所有権を持たない。 SCSIDevice *device[8] {}; + // 接続中のデバイス(イニシエータ含む)を ID 順に並べたリスト。 + std::vector connected_devices {}; + + // 親(イニシエータ) + SCSIHostDevice *parent {}; + // イベント - Event event {}; -}; + Event event { this }; -// (1<