Moved commands from controller to disk

This commit is contained in:
Uwe Seimet 2021-08-22 12:47:45 +02:00
parent ff88ce9602
commit 43cd5263f9
5 changed files with 245 additions and 246 deletions

View File

@ -59,20 +59,20 @@ SCSIDEV::SCSIDEV() : SASIDEV()
SetUpControllerCommand(eCmdSendDiag, "CmdSendDiag", &SCSIDEV::CmdSendDiag);
SetUpControllerCommand(eCmdRemoval, "CmdRemoval", &SCSIDEV::CmdRemoval);
SetUpDeviceCommand(eCmdReadCapacity10, "CmdReadCapacity10", &Disk::ReadCapacity10);
SetUpControllerCommand(eCmdRead10, "CmdRead10", &SCSIDEV::CmdRead10);
SetUpControllerCommand(eCmdWrite10, "CmdWrite10", &SCSIDEV::CmdWrite10);
SetUpControllerCommand(eCmdVerify10, "CmdVerify10", &SCSIDEV::CmdWrite10);
SetUpDeviceCommand(eCmdRead10, "CmdRead10", &Disk::Read10);
SetUpDeviceCommand(eCmdWrite10, "CmdWrite10", &Disk::Write10);
SetUpDeviceCommand(eCmdVerify10, "CmdVerify10", &Disk::Write10);
SetUpDeviceCommand(eCmdSeek10, "CmdSeek10", &Disk::Seek10);
SetUpControllerCommand(eCmdVerify, "CmdVerify", &SCSIDEV::CmdVerify);
SetUpDeviceCommand(eCmdVerify, "CmdVerify", &Disk::Verify);
SetUpControllerCommand(eCmdSynchronizeCache, "CmdSynchronizeCache", &SCSIDEV::CmdSynchronizeCache);
SetUpControllerCommand(eCmdReadDefectData10, "CmdReadDefectData10", &SCSIDEV::CmdReadDefectData10);
SetUpControllerCommand(eCmdModeSelect10, "CmdModeSelect10", &SCSIDEV::CmdModeSelect10);
SetUpDeviceCommand(eCmdReserve10, "CmdReserve10", &Disk::Reserve10);
SetUpDeviceCommand(eCmdRelease10, "CmdRelease10", &Disk::Release10);
SetUpControllerCommand(eCmdModeSense10, "CmdModeSense10", &SCSIDEV::CmdModeSense10);
SetUpControllerCommand(eCmdRead16, "CmdRead16", &SCSIDEV::CmdRead16);
SetUpControllerCommand(eCmdWrite16, "CmdWrite16", &SCSIDEV::CmdWrite16);
SetUpControllerCommand(eCmdVerify16, "CmdVerify16", &SCSIDEV::CmdWrite16);
SetUpDeviceCommand(eCmdRead16, "CmdRead16", &Disk::Read16);
SetUpDeviceCommand(eCmdWrite16, "CmdWrite16", &Disk::Write16);
SetUpDeviceCommand(eCmdVerify16, "CmdVerify16", &Disk::Write16);
SetUpDeviceCommand(eCmdReadCapacity16, "CmdReadCapacity16", &Disk::ReadCapacity16);
SetUpDeviceCommand(eCmdReportLuns, "CmdReportLuns", &Disk::ReportLuns);
@ -588,189 +588,6 @@ void SCSIDEV::CmdRemoval()
Status();
}
//---------------------------------------------------------------------------
//
// READ(10)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdRead10()
{
// TODO Move bridge specific test
// Receive message if host bridge
if (ctrl.device->IsBridge()) {
CmdGetMessage10();
return;
}
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(record, ctrl.blocks, false)) {
return;
}
LOGTRACE("%s READ(10) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
// Command processing on drive
ctrl.length = ctrl.device->Read(ctrl.cmd, ctrl.buffer, record);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
// Set next block
ctrl.next = record + 1;
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// READ(16)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdRead16()
{
// TODO Move bridge specific test
// Receive message if host bridge
if (ctrl.device->IsBridge()) {
Error();
return;
}
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(record, ctrl.blocks, true)) {
return;
}
LOGTRACE("%s READ(16) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
// Command processing on drive
ctrl.length = ctrl.device->Read(ctrl.cmd, ctrl.buffer, record);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
// Set next block
ctrl.next = record + 1;
// Data-in Phase
DataIn();
}
//---------------------------------------------------------------------------
//
// WRITE(10)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdWrite10()
{
// TODO Move bridge specific test
// Receive message with host bridge
if (ctrl.device->IsBridge()) {
CmdSendMessage10();
return;
}
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(record, ctrl.blocks, false)) {
return;
}
LOGTRACE("%s WRITE(10) command record=%d blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (unsigned int)ctrl.blocks);
// Command processing on drive
ctrl.length = ctrl.device->WriteCheck(record);
if (ctrl.length <= 0) {
// Failure (Error)
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
return;
}
// Set next block
ctrl.next = record + 1;
// Data out phase
DataOut();
}
//---------------------------------------------------------------------------
//
// WRITE(16)
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdWrite16()
{
// TODO Move bridge specific test
// Receive message if host bridge
if (ctrl.device->IsBridge()) {
Error();
return;
}
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(record, ctrl.blocks, true)) {
return;
}
LOGTRACE("%s WRITE(16) command record=%d blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (unsigned int)ctrl.blocks);
// Command processing on drive
ctrl.length = ctrl.device->WriteCheck(record);
if (ctrl.length <= 0) {
// Failure (Error)
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
return;
}
// Set next block
ctrl.next = record + 1;
// Data out phase
DataOut();
}
//---------------------------------------------------------------------------
//
// VERIFY
//
//---------------------------------------------------------------------------
void SCSIDEV::CmdVerify()
{
// Get record number and block number
uint64_t record;
GetStartAndCount(record, ctrl.blocks, false);
LOGTRACE("%s VERIFY command record=%08X blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
// if BytChk=0
if ((ctrl.cmd[1] & 0x02) == 0) {
// Command processing on drive
ctrl.device->Seek(this);
return;
}
// Test loading
ctrl.length = ctrl.device->Read(ctrl.cmd, ctrl.buffer, record);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
// Set next block
ctrl.next = record + 1;
// Data out phase
DataOut();
}
//---------------------------------------------------------------------------
//
// SYNCHRONIZE CACHE

View File

@ -75,6 +75,9 @@ public:
void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); // Common erorr handling
void CmdGetMessage10(); // GET MESSAGE(10) command
void CmdSendMessage10(); // SEND MESSAGE(10) command
private:
void SetUpControllerCommand(scsi_command, const char*, void (SCSIDEV::*)(void));
void SetUpDeviceCommand(scsi_command, const char*, void (Disk::*)(SASIDEV *));
@ -92,9 +95,6 @@ private:
void CmdStartStop(); // START STOP UNIT command
void CmdSendDiag(); // SEND DIAGNOSTIC command
void CmdRemoval(); // PREVENT/ALLOW MEDIUM REMOVAL command
void CmdRead10(); // READ(10) command
void CmdWrite10(); // WRITE(10) command
void CmdVerify(); // VERIFY command
void CmdSynchronizeCache(); // SYNCHRONIZE CACHE command
void CmdReadDefectData10(); // READ DEFECT DATA(10) command
void CmdReadToc(); // READ TOC command
@ -104,10 +104,6 @@ private:
void CmdGetEventStatusNotification();
void CmdModeSelect10(); // MODE SELECT(10) command
void CmdModeSense10(); // MODE SENSE(10) command
void CmdRead16(); // READ(16) command
void CmdWrite16(); // WRITE(16) command
void CmdGetMessage10(); // GET MESSAGE(10) command
void CmdSendMessage10(); // SEND MESSAGE(10) command
void CmdRetrieveStats(); // DaynaPort specific command
void CmdSetIfaceMode(); // DaynaPort specific command
void CmdSetMcastAddr(); // DaynaPort specific command

View File

@ -27,18 +27,17 @@ public:
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override = 0;
virtual void ReportLuns(SASIDEV *) override = 0;
virtual bool Format(const DWORD *cdb) = 0;
// READ(6), READ(10)
virtual int Read(const DWORD *cdb, BYTE *buf, DWORD block) = 0;
// WRITE(6), WRITE(10)
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) = 0;
virtual void ReadCapacity10(SASIDEV *) = 0;
virtual void ReadCapacity16(SASIDEV *) = 0;
// TODO Uncomment as soon as there is a clean separation between controllers and devices
//virtual int Read16(const DWORD *cdb, BYTE *buf, DWORD block) = 0;
//virtual int Write16(const DWORD *cdb, BYTE *buf, DWORD block) = 0;
//virtual int Verify16(const DWORD *cdb, BYTE *buf, DWORD block) = 0;
virtual void Read10(SASIDEV *) = 0;
virtual void Read16(SASIDEV *) = 0;
virtual void Write10(SASIDEV *) = 0;
virtual void Write16(SASIDEV *) = 0;
// Implemented optional commands
// TODO uncomment
//virtual void Verify10(SASIDEV *) = 0;
//virtual void Verify16(SASIDEV *) = 0;
virtual int RequestSense(const DWORD *cdb, BYTE *buf) override = 0;
virtual int ModeSense(const DWORD *cdb, BYTE *buf) override = 0;
virtual int ModeSense10(const DWORD *cdb, BYTE *buf) override = 0;

View File

@ -25,7 +25,9 @@
#include "ctapdriver.h"
#include "cfilesystem.h"
#include "controllers/sasidev_ctrl.h"
#include "controllers/scsidev_ctrl.h"
#include "disk.h"
#include <sstream>
//===========================================================================
//
@ -350,6 +352,65 @@ BOOL DiskTrack::Read(BYTE *buf, int sec) const
return TRUE;
}
void Disk::Read10(SASIDEV *controller)
{
// TODO Move to subclass
// Receive message if host bridge
if (IsBridge()) {
((SCSIDEV *)controller)->CmdGetMessage10();
return;
}
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(controller, record, ctrl->blocks, false)) {
return;
}
LOGTRACE("%s READ(10) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks);
ctrl->length = Read(ctrl->cmd, ctrl->buffer, record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->next = record + 1;
// Data-in Phase
controller->DataIn();
}
void Disk::Read16(SASIDEV *controller)
{
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(controller, record, ctrl->blocks, true)) {
return;
}
LOGTRACE("%s READ(16) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks);
ctrl->length = ctrl->device->Read(ctrl->cmd, ctrl->buffer, record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->next = record + 1;
// Data-in Phase
controller->DataIn();
}
//---------------------------------------------------------------------------
//
// Write Sector
@ -393,6 +454,101 @@ BOOL DiskTrack::Write(const BYTE *buf, int sec)
return TRUE;
}
void Disk::Write10(SASIDEV *controller)
{
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// TODO Move to subclass
// Receive message with host bridge
if (ctrl->device->IsBridge()) {
((SCSIDEV *)controller)->CmdSendMessage10();
return;
}
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(controller, record, ctrl->blocks, false)) {
return;
}
LOGTRACE("%s WRITE(10) command record=%d blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (unsigned int)ctrl->blocks);
ctrl->length = WriteCheck(record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
return;
}
// Set next block
ctrl->next = record + 1;
// Data out phase
controller->DataOut();
}
void Disk::Write16(SASIDEV *controller)
{
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Get record number and block number
uint64_t record;
if (!GetStartAndCount(controller, record, ctrl->blocks, true)) {
return;
}
LOGTRACE("%s WRITE(16) command record=%d blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (unsigned int)ctrl->blocks);
ctrl->length = WriteCheck(record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
return;
}
// Set next block
ctrl->next = record + 1;
// Data out phase
controller->DataOut();
}
//---------------------------------------------------------------------------
//
// VERIFY
//
//---------------------------------------------------------------------------
void Disk::Verify(SASIDEV *controller)
{
SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
// Get record number and block number
uint64_t record;
GetStartAndCount(controller, record, ctrl->blocks, false);
LOGTRACE("%s VERIFY command record=%08X blocks=%d",__PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl->blocks);
// if BytChk=0
if ((ctrl->cmd[1] & 0x02) == 0) {
Seek(controller);
return;
}
// Test loading
ctrl->length = Read(ctrl->cmd, ctrl->buffer, record);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->next = record + 1;
// Data out phase
controller->DataOut();
}
//===========================================================================
//
// Disk Cache
@ -1932,43 +2088,6 @@ void Disk::ReportLuns(SASIDEV *controller)
controller->DataIn();
}
//---------------------------------------------------------------------------
//
// VERIFY
//
//---------------------------------------------------------------------------
bool Disk::Verify(const DWORD *cdb)
{
ASSERT(cdb);
ASSERT(cdb[0] == 0x2f);
// Get parameters
DWORD record = cdb[2];
record <<= 8;
record |= cdb[3];
record <<= 8;
record |= cdb[4];
record <<= 8;
record |= cdb[5];
DWORD blocks = cdb[7];
blocks <<= 8;
blocks |= cdb[8];
// Status check
if (!CheckReady()) {
return false;
}
// Parameter check
if (disk.blocks < (record + blocks)) {
SetStatusCode(STATUS_INVALIDLBA);
return false;
}
// Success
return true;
}
//---------------------------------------------------------------------------
//
// RESERVE(6)
@ -2102,6 +2221,69 @@ bool Disk::PlayAudioTrack(const DWORD *cdb)
return false;
}
//---------------------------------------------------------------------------
//
// Get start sector and sector count for a READ/WRITE(10/16) operation
//
//---------------------------------------------------------------------------
bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& count, bool rw64)
{
const SASIDEV::ctrl_t *ctrl = controller->GetWorkAddr();
start = ctrl->cmd[2];
start <<= 8;
start |= ctrl->cmd[3];
start <<= 8;
start |= ctrl->cmd[4];
start <<= 8;
start |= ctrl->cmd[5];
if (rw64) {
start <<= 8;
start |= ctrl->cmd[6];
start <<= 8;
start |= ctrl->cmd[7];
start <<= 8;
start |= ctrl->cmd[8];
start <<= 8;
start |= ctrl->cmd[9];
}
if (rw64) {
count = ctrl->cmd[10];
count <<= 8;
count |= ctrl->cmd[11];
count <<= 8;
count |= ctrl->cmd[12];
count <<= 8;
count |= ctrl->cmd[13];
}
else {
count = ctrl->cmd[7];
count <<= 8;
count |= ctrl->cmd[8];
}
// Check capacity
uint64_t capacity = GetBlockCount();
if (start > capacity || start + count > capacity) {
ostringstream s;
s << "Media capacity of " << capacity << " blocks exceeded: "
<< "Trying to read block " << start << ", block count " << ctrl->blocks;
LOGWARN("%s", s.str().c_str());
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
return false;
}
// Do not process 0 blocks
if (!count) {
LOGTRACE("NOT processing 0 blocks");
controller->Status();
return false;
}
return true;
}
int Disk::GetSectorSize() const
{
return disk.size;

View File

@ -162,9 +162,13 @@ public:
bool Rezero(const DWORD *cdb); // REZERO command
bool Format(const DWORD *cdb) override; // FORMAT UNIT command
bool Reassign(const DWORD *cdb); // REASSIGN UNIT command
virtual int Read(const DWORD *cdb, BYTE *buf, DWORD block) override; // READ command
virtual int Read(const DWORD *cdb, BYTE *buf, DWORD block); // READ command
void Read10(SASIDEV *);
void Read16(SASIDEV *);
virtual int WriteCheck(DWORD block); // WRITE check
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) override; // WRITE command
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block); // WRITE command
void Write10(SASIDEV *);
void Write16(SASIDEV *);
void Seek(SASIDEV *);
void Seek6(SASIDEV *);
void Seek10(SASIDEV *);
@ -188,13 +192,14 @@ public:
void SetConfiguredSectorSize(int);
DWORD GetBlockCount() const;
void SetBlockCount(DWORD);
// TODO Currently not called
bool Verify(const DWORD *cdb); // VERIFY command
void Verify(SASIDEV *controller); // VERIFY command
virtual int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
virtual bool PlayAudio(const DWORD *cdb); // PLAY AUDIO command
virtual bool PlayAudioMSF(const DWORD *cdb); // PLAY AUDIO MSF command
virtual bool PlayAudioTrack(const DWORD *cdb); // PLAY AUDIO TRACK command
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, bool);
protected:
// Internal processing
virtual int AddError(bool change, BYTE *buf); // Add error