--- nono/vm/scsibus.cpp 2026/04/29 17:04:36 1.1.1.3 +++ nono/vm/scsibus.cpp 2026/04/29 17:04:42 1.1.1.4 @@ -34,6 +34,20 @@ SCSIBus::~SCSIBus() { } +// リセット +void +SCSIBus::ResetHard() +{ + // ここでのイベントは実際にはイニシエータかターゲットのどちらかが + // 時間を伴う処理をしている最中であることを示しているものなので、 + // イニシエータがリセットされたこととバスの動作とは本来関係ないのだが + // ここでは特にイニシエータに次のバイトを転送させる、という目的で + // タイマーイベントが使われており、本体をリセットしたのに入れ違いで + // イニシエータの転送処理が呼び出されてしまうというような事故を + // 防ぐためにもここでタイマーを停止する。 + event.Stop(); +} + // このバスにデバイスを接続する (初期化時に使う) bool SCSIBus::Attach(SCSIDevice *dev, int id) @@ -298,6 +312,11 @@ SCSIBus::AssertREQ() if (now < last_req_time + 1_usec) { after = (last_req_time + 1_usec) - now; } + // ウェイトが指示されていれば入れる (シークタイムなど) + if (req_wait != 0) { + after += req_wait; + req_wait = 0; + } CallAfter(TransferReq, "SCSIBus AssertREQ", after); } else { // 転送フェーズでないのに上げることはないと思うけど @@ -310,7 +329,7 @@ SCSIBus::AssertREQ() // ターゲットが REQ を立てようとして所定時間経ったので REQ を立てて // イニシエータの TransferReqCB を呼び出すところ。 void -SCSIBus::TransferReq(int dummy) +SCSIBus::TransferReq(Event& ev) { putlog(4, "AssertREQ"); req = true; @@ -430,7 +449,7 @@ SCSIBus::BusFree(int id) // セレクションフェーズ開始。 void -SCSIBus::SelectionStart() +SCSIBus::SelectionStart(Event& ev) { // この時点でデータバスには自身の ID と相手の ID が立っているはず。 // 一方 sel は SEL 信号線を立てた人のビットを持っているので、 @@ -460,7 +479,7 @@ SCSIBus::SelectionStart() // SelectionStart() にてターゲットが選択されて規定時間経ったので // そろそろターゲットが BSY を立てる頃に呼ばれるコールバック。 void -SCSIBus::Selected(int dummy) +SCSIBus::Selected(Event& ev) { // ターゲットに通知。ターゲットがいることは確定している。 assert(device[target_id]); @@ -468,9 +487,9 @@ SCSIBus::Selected(int dummy) } // ターゲットが BSY を立てて規定時間経ったので -// そろそろイニシエータが SEL を下げることに呼ばれるコールバック。 +// そろそろイニシエータが SEL を下げる頃に呼ばれるコールバック。 void -SCSIBus::SelectionAck(int dummy) +SCSIBus::SelectionAck(Event& ev) { // イニシエータに通知。 assert(device[init_id]); @@ -480,7 +499,7 @@ SCSIBus::SelectionAck(int dummy) // 情報転送フェーズ開始を通知する。 // BSY を上げて情報転送フェーズに移行したところで呼ばれる。 void -SCSIBus::StartTransfer(int dummy) +SCSIBus::StartTransfer(Event& ev) { SetPhase(SCSI::Phase::Transfer);