--- nono/vm/scsi.cpp 2026/04/29 17:04:28 1.1 +++ nono/vm/scsi.cpp 2026/04/29 17:04:36 1.1.1.3 @@ -1,26 +1,12 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // // SCSI // -#include "scsi.h" -#include "scheduler.h" -#include "scsitarget.h" -#include "mystring.h" -#include "configfile.h" - -// フェーズ名を返す。 -const char * -SCSI::GetPhaseName(uint phase) -{ - if (phase < countof(phasename)) { - return phasename[phase]; - } else { - return NULL; - } -} +#include "scsibus.h" // cmd に対応するコマンド名を返す。 const char * @@ -33,24 +19,6 @@ SCSI::GetCommandName(uint8 cmd) } } -// フェーズ名 -/*static*/ const char * const -SCSI::phasename[Phase::MAX] = -{ - "DataOut", // 0 - "DataIn", // 1 - "Command", // 2 - "Status", // 3 - "4?", // 4 - "5?", // 5 - "MsgOut", // 6 - "MsgIn", // 7 - "BusFree", // 8 - "Arbitration", // 9 - "Selection", // 10 - "Reselection", // 11 -}; - // コマンド名 /*static*/ const char * const SCSI::commandname[Command::MAX] = @@ -151,321 +119,3 @@ SCSI::commandname[Command::MAX] = NULL, // 59 "ModeSense(10)", // 5a }; - -// -// SCSI ホストデバイス (基本クラス) -// - -// コンストラクタ -SCSIHostDevice::SCSIHostDevice() -{ -} - -// デストラクタ -SCSIHostDevice::~SCSIHostDevice() -{ -} - -// SCSI デバイスオブジェクトの生成 -bool -SCSIHostDevice::Create() -{ - for (int id = 0; id < 8; id++) { - const std::string key = string_format("%s_id%d_devtype", - GetConfigName(), id); - int devtype = gConfig->ReadInt(key); - switch (devtype) { - default: - case SCSI::None: - target[id] = NULL; - break; - case SCSI::HD: - target[id] = new SCSIHD(this, id); - break; - } - } - return true; -} - -// SCSIHostDevice クラスに書いてあるけど -// このへんは SCSI バスの挙動。 - -// 各バスフェーズへ遷移する - -// バスフリーフェーズへ遷移する。 -// 基本的にターゲットが使用する。 -void -SCSIHostDevice::B_BusFree(int id) -{ - if (!IsBusFree()) { - // バスフリーに変化した時刻を記録 - BusPhaseTime = gScheduler->GetVirtTime(); - } - NegateSEL(id); - NegateBSY(id); - SetMSG(false); - SetCD(false); - SetIO(false); - SetATN(false); - SetREQ(false); - SetACK(false); - SetDATA(0); - putlog(3, "BusFree"); -} - -// アービトレーションフェーズを起動する。 -// id はアービトレーションを行おうとしているデバイスの ID。 -// バスフリー状態で呼び出すこと。 -bool -SCSIHostDevice::Arbitration(int id) -{ - assert(IsBusFree()); - - AssertBSY(id); - SetDATA(1 << id); - - putlog(3, "Arbitration invoked by ID=%d", id); - return true; -} - -// アービトレーションフェーズの完了確認。 -// id はアービトレーションを行おうとしているデバイスの ID。 -bool -SCSIHostDevice::ArbitrationAck(int id) -{ - // 自分より上位の ID がいればアービトレーション失敗なのだが、 - // ここでは複数のデバイスが同時にアービトレーションフェーズに入ることは - // ないので、アービトレーションは必ず成功するとする。 - if (0 && GetDATA() > (1 << id)) { - NegateBSY(id); - putlog(3, "Arbitration loose ID=%d", id); - return false; - } - AssertSEL(id); - return true; -} - -// イニシエータによるセレクションフェーズの起動。 -void -SCSIHostDevice::InitiatorSelection(int targetid) -{ - NegateBSY(myid); - SetDATA((1 << myid) | (1 << targetid)); - AssertSEL(myid); -} - -// (イニシエータによる)セレクションへのターゲットの応答。 -void -SCSIHostDevice::TargetSelectionAck(int targetid) -{ - assert(GetDATA() & (1 << targetid)); - - // targetid がセレクトされた - AssertBSY(targetid); - tgtid = targetid; - putlog(3, "Target selected ID=%d", targetid); -} - -void -SCSIHostDevice::InitiatorSelectionAck() -{ - NegateSEL(myid); -} - -// リセレクションフェーズ - -void -SCSIHostDevice::TargetReselection(int targetid, int initiatorID) -{ - SetIO(true); - SetDATA((1 << initiatorID) | (1 << targetid)); - NegateBSY(targetid); -} - -int -BitToID(int x) -{ - return 31 - __builtin_clz(x); -} - -void -SCSIHostDevice::InitiatorReselectionAck() -{ - tgtid = BitToID(GetDATA() & ~(1 << myid)); - AssertBSY(myid); -} - -void -SCSIHostDevice::TargetReselectionAck(int targetid) -{ - AssertBSY(targetid); - NegateSEL(targetid); - target[targetid]->Selected(); -} - -void -SCSIHostDevice::InitiatorReselectionAck2() -{ - NegateBSY(myid); -} - -//////// - -// データバスに data をセット -void -SCSIHostDevice::SetDATA(uint8 data) -{ - DATA = data; - putlog(3, "BUS DATA = $%02x", DATA); -} - -// REQ 信号線をセット -void -SCSIHostDevice::SetREQ(bool val) -{ - // 同じなら何もしない - if (REQ == val) { - return; - } - - REQ = val; - putlog(4, "BUS REQ = %d", REQ); -} - -// ACK 信号線をセット -void -SCSIHostDevice::SetACK(bool val) -{ - // 同じなら何もしない - if (ACK == val) { - return; - } - - ACK = val; - putlog(4, "BUS ACK = %d", ACK); -} - -// RST 信号線をセット -void -SCSIHostDevice::SetRST(bool val) -{ - // 同じなら何もしない - if (RST == val) { - return; - } - - RST = val; - putlog(3, "BUS RST = %d", RST); -} - -// SEL 信号線をアサート -void -SCSIHostDevice::AssertSEL(int id) -{ - // 同じなら何もしない - if (SEL & (1 << id)) { - return; - } - - SEL |= 1 << id; - putlog(3, "BUS SEL = %02x", SEL); -} - -// SEL 信号線をネゲート -void -SCSIHostDevice::NegateSEL(int id) -{ - // 同じなら何もしない - if ((SEL & (1 << id)) == 0) { - return; - } - - SEL &= ~(1 << id); - putlog(3, "BUS SEL = %02x", SEL); -} - -// BSY 信号線をアサート -void -SCSIHostDevice::AssertBSY(int id) -{ - // 同じなら何もしない - if (BSY & (1 << id)) { - return; - } - - BSY |= 1 << id; - putlog(3, "BUS BSY = %02x", BSY); -} - -// BSY 信号線をネゲート -void -SCSIHostDevice::NegateBSY(int id) -{ - // 同じなら何もしない - if ((BSY & (1 << id)) == 0) { - return; - } - - BSY &= ~(1 << id); - putlog(3, "BUS BSY = %02x", BSY); -} - -// MSG 信号線をセット -void -SCSIHostDevice::SetMSG(bool val) -{ - // 同じなら何もしない - if (MSG == val) { - return; - } - - MSG = val; - putlog(3, "BUS MSG = %d", MSG); -} - -// C/D 信号線をセット -void -SCSIHostDevice::SetCD(bool val) -{ - // 同じなら何もしない - if (CD == val) { - return; - } - - CD = val; - static const char *cdstr[] = { - "Data", - "Ctrl", - }; - putlog(3, "BUS CD = %d(%s)", CD, cdstr[CD]); -} - -// I/O 信号線をセット -void -SCSIHostDevice::SetIO(bool val) -{ - // 同じなら何もしない - if (IO == val) { - return; - } - - IO = val; - static const char *iostr[] = { - "Out", - "In", - }; - putlog(3, "BUS IO = %d(%s)", IO, iostr[IO]); -} - -// ATN 信号線をセット -void -SCSIHostDevice::SetATN(bool val) -{ - // 同じなら何もしない - if (ATN == val) { - return; - } - - ATN = val; - putlog(3, "BUS ATN = %d", ATN); -}