File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / scsitarget.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:04:28 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v001, HEAD
nono 0.0.1

//
// nono
// Copyright (C) 2018 [email protected]
//

#pragma once

#include "device.h"
#include "scsi.h"

// 前方参照 (scsitarget.cpp 内だけで使われている)
// friend class に書くクラス名は前方参照なくても大丈夫らしい。
class SCSICmd;

class SCSITarget : public Device
{
	typedef Device inherited;
	friend class SCSICmdModeSelect6;
	friend class SCSICmdRead6;
	friend class SCSICmdWrite6;
	friend class SCSICmdRead10;
 public:
	SCSITarget(SCSIHostDevice *host, int id, SCSI::DevType type);
	virtual ~SCSITarget();

	// SCSI デバイス種別を取得
	SCSI::DevType GetDevType() const { return devtype; }

	void Selected();
	void Ack();

	// コマンドフェーズの処理。
	void ExecCommand(const std::vector<uint8>& cmds);

	// デバイス固有のコマンドの処理。(派生クラスで用意)
	virtual SCSICmd *ExecDeviceCommand();

	// データインフェーズを開始。
	uint ExecDataIn(const uint8 **ptr);

	// データアウトフェーズを開始。
	uint ExecDataOut(uint8 **ptr);

	// ステータスバイトを取得 (およびデータアウトフェーズ完了処理)。
	uint8 GetStatusByte();

	// メッセージバイトを取得。
	uint8 GetMessageByte();

 protected:
	SCSIHostDevice *host = NULL;	// ホストアダプタ
	SCSI::DevType devtype {};		// デバイス種別
	int ID = 0;						// 自分の SCSI ID

	// SCSI バス信号は SCSIHost が管理
	uint8 GetDATA() { return host->GetDATA(); }
	void SetDATA(uint8 val) { host->SetDATA(val); }

	bool GetACK() const { return host->GetACK(); }
	void SetACK(bool val) { host->SetACK(val); }

	bool GetREQ() const { return host->GetREQ(); }
	void SetREQ(bool val) { host->SetREQ(val); }

	bool GetSEL() const { return host->GetSEL(); }
	void AssertSEL(int id) { host->AssertSEL(id); }
	void NegateSEL(int id) { host->NegateSEL(id); }

	bool GetBSY() const { return host->GetBSY(); }
	void AssertBSY(int id) { host->AssertBSY(id); }
	void NegateBSY(int id) { host->NegateBSY(id); }

	bool GetMSG() const { return host->GetMSG(); }
	void SetMSG(bool val) { host->SetMSG(val); }

	bool GetCD() const { return host->GetCD(); }
	void SetCD(bool val) { host->SetCD(val); }

	bool GetIO() const { return host->GetIO(); }
	void SetIO(bool val) { host->SetIO(val); }

	bool GetATN() const { return host->GetATN(); }

	void BusFreePhase();
	void DataOutPhase();
	void DataInPhase();
	void CommandPhase();
	void StatusPhase();
	void MsgOutPhase();
	void MsgInPhase();

	uint phase = 0;				// ターゲットの状態
	uint nextphase = 0;			// ATN による MsgOut の次の本来のフェーズ
	// ターゲットの現在のフェーズを取得
	uint GetPhase() const { return phase; }
	// ターゲットのフェーズを newphase に移行
	void SetPhase(uint newphase);

	// コマンド
	std::vector<uint8> cmds {};
	SCSICmd *cmd = NULL;

	uint8 lastdata = 0;
	uint8 lastmsg = 0;			// 前回の MsgOut のメッセージ

	// 論理ブロック長 (ModeSelect コマンドでホストから指定される)
	uint32 blocksize = 0;
};

// SCSI HD
class SCSIHD : public SCSITarget
{
	typedef SCSITarget inherited;
	friend class SCSICmdRead6;
	friend class SCSICmdWrite6;
	friend class SCSICmdReadCapacity;
	friend class SCSICmdRead10;
 public:
	SCSIHD(SCSIHostDevice *host, int id);
	virtual ~SCSIHD();

	virtual bool Init();

	// デバイス固有のコマンドの処理。
	virtual SCSICmd *ExecDeviceCommand();

 private:
	int fd = 0;
	uint8 *mem = NULL;
	size_t memlen = 0;
	bool writeprotect = false;

	static const uint8 inquiry_data[36];
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.