mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-23 06:30:04 +00:00
SASI FORMAT opcode fix, SASI segfault fix, added SASI INQUIRY/READ CAPACITY, 512 bytes per sector SASI drives (#724)
* Fixed opcode
* Fixed segfault
* Re-added 0x06 as additional SASI FORMAT opcode
* Added support of SASI drives with 512 bytes
* SASI LUN must always be taken from CDB and must be 0 or 1
* Fixed typo
* Fixed one more SASI segfault
* Removed duplicate code
* Updated error handling
* Updated error handling
* Logging update
* Added enum value for SPC-6
* Comment update
* Added support for SASI Inquiry
* Updated SASI LUN check
* Updated SASI LUN handling
* Comment update
* Revert "Comment update"
This reverts commit c6adbde25c
.
* Updated logging
* Implemented SASI READ CAPACITY
* Validate SASI block count
* Do not support ICD semantics for SASI drives
* SASI READ CAPACITY is a group 1 command with 10 bytes
* Comment update
This commit is contained in:
parent
536e77cd9d
commit
9099d7249c
@ -309,7 +309,7 @@ void SASIDEV::Command()
|
||||
ctrl.blocks = 1;
|
||||
|
||||
// If no byte can be received move to the status phase
|
||||
int count = ctrl.bus->CommandHandShake(ctrl.buffer);
|
||||
int count = ctrl.bus->CommandHandShake(ctrl.buffer, IsSASI());
|
||||
if (!count) {
|
||||
Error();
|
||||
return;
|
||||
@ -355,74 +355,95 @@ void SASIDEV::Execute()
|
||||
ctrl.blocks = 1;
|
||||
ctrl.execstart = SysTimer::GetTimerLow();
|
||||
|
||||
int lun = GetEffectiveLun();
|
||||
if (!ctrl.unit[lun]) {
|
||||
ctrl.device->SetStatusCode(STATUS_INVALIDLUN);
|
||||
Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN);
|
||||
return;
|
||||
}
|
||||
|
||||
ctrl.device = ctrl.unit[lun];
|
||||
ctrl.device->SetCtrl(&ctrl);
|
||||
|
||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||
if ((SASIDEV::sasi_command)ctrl.cmd[0] != SASIDEV::eCmdRequestSense) {
|
||||
ctrl.status = 0;
|
||||
ctrl.device->SetStatusCode(0);
|
||||
}
|
||||
|
||||
// Process by command
|
||||
// TODO This code does not belong here. Each device type needs such a dispatcher, which the controller has to call.
|
||||
switch ((SASIDEV::sasi_command)ctrl.cmd[0]) {
|
||||
// TEST UNIT READY
|
||||
case SASIDEV::eCmdTestUnitReady:
|
||||
CmdTestUnitReady();
|
||||
LOGTRACE( "%s TEST UNIT READY Command", __PRETTY_FUNCTION__);
|
||||
ctrl.device->TestUnitReady(this);
|
||||
return;
|
||||
|
||||
// REZERO UNIT
|
||||
case SASIDEV::eCmdRezero:
|
||||
CmdRezero();
|
||||
LOGTRACE( "%s REZERO Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Rezero(this);
|
||||
return;
|
||||
|
||||
// REQUEST SENSE
|
||||
case SASIDEV::eCmdRequestSense:
|
||||
CmdRequestSense();
|
||||
LOGTRACE( "%s REQUEST SENSE Command", __PRETTY_FUNCTION__);
|
||||
ctrl.device->RequestSense(this);
|
||||
return;
|
||||
|
||||
// FORMAT
|
||||
// FORMAT (the old RaSCSI code used 0x06 as opcode, which is not compliant with the SASI specification)
|
||||
// The FORMAT command of RaSCSI does not do anything but just returns a GOOD status
|
||||
case SASIDEV::eCmdFormat:
|
||||
CmdFormat();
|
||||
case SASIDEV::eCmdFormatLegacy:
|
||||
LOGTRACE( "%s FORMAT UNIT Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->FormatUnit(this);
|
||||
return;
|
||||
|
||||
case SASIDEV::eCmdReadCapacity:
|
||||
LOGTRACE( "%s READ CAPACITY Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->ReadCapacity10(this);
|
||||
return;
|
||||
|
||||
// REASSIGN BLOCKS
|
||||
case SASIDEV::eCmdReassign:
|
||||
CmdReassignBlocks();
|
||||
LOGTRACE( "%s REASSIGN BLOCKS Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->ReassignBlocks(this);
|
||||
return;
|
||||
|
||||
// READ(6)
|
||||
case SASIDEV::eCmdRead6:
|
||||
CmdRead6();
|
||||
LOGTRACE( "%s READ Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Read6(this);
|
||||
return;
|
||||
|
||||
// WRITE(6)
|
||||
case SASIDEV::eCmdWrite6:
|
||||
CmdWrite6();
|
||||
LOGTRACE( "%s WRITE Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Write6(this);
|
||||
return;
|
||||
|
||||
// SEEK(6)
|
||||
case SASIDEV::eCmdSeek6:
|
||||
CmdSeek6();
|
||||
LOGTRACE( "%s SEEK Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Seek(this);
|
||||
return;
|
||||
|
||||
case SASIDEV::eCmdInquiry:
|
||||
LOGTRACE( "%s INQUIRY Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Inquiry(this);
|
||||
return;
|
||||
|
||||
// ASSIGN (SASI only)
|
||||
// This doesn't exist in the SCSI Spec, but was in the original RaSCSI code.
|
||||
// This doesn't exist in the SASI Spec, but was in the original RaSCSI code.
|
||||
// leaving it here for now....
|
||||
case SASIDEV::eCmdSasiCmdAssign:
|
||||
CmdAssign();
|
||||
return;
|
||||
|
||||
// RESERVE UNIT(16)
|
||||
case SASIDEV::eCmdReserve6:
|
||||
CmdReserveUnit();
|
||||
LOGTRACE( "%s RESERVE Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Reserve(this);
|
||||
return;
|
||||
|
||||
// RELEASE UNIT(17)
|
||||
case eCmdRelease6:
|
||||
CmdReleaseUnit();
|
||||
LOGTRACE( "%s RELEASE Command", __PRETTY_FUNCTION__);
|
||||
((Disk *)ctrl.device)->Release(this);
|
||||
return;
|
||||
|
||||
// SPECIFY (SASI only)
|
||||
// This doesn't exist in the SCSI Spec, but was in the original RaSCSI code.
|
||||
// This doesn't exist in the SASI Spec, but was in the original RaSCSI code.
|
||||
// leaving it here for now....
|
||||
case SASIDEV::eCmdInvalid:
|
||||
CmdSpecify();
|
||||
@ -432,18 +453,11 @@ void SASIDEV::Execute()
|
||||
break;
|
||||
}
|
||||
|
||||
// Unsupported command
|
||||
LOGTRACE("%s ID %d received unsupported command: $%02X", __PRETTY_FUNCTION__, GetSCSIID(), (BYTE)ctrl.cmd[0]);
|
||||
|
||||
// Logical Unit
|
||||
DWORD lun = GetEffectiveLun();
|
||||
if (ctrl.unit[lun]) {
|
||||
// Command processing on drive
|
||||
ctrl.unit[lun]->SetStatusCode(STATUS_INVALIDCMD);
|
||||
}
|
||||
ctrl.device->SetStatusCode(STATUS_INVALIDCMD);
|
||||
|
||||
// Failure (Error)
|
||||
Error();
|
||||
Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@ -618,11 +632,6 @@ void SASIDEV::DataOut()
|
||||
Receive();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Error
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::Error(sense_key sense_key, asc asc, status status)
|
||||
{
|
||||
// Get bus information
|
||||
@ -644,205 +653,13 @@ void SASIDEV::Error(sense_key sense_key, asc asc, status status)
|
||||
return;
|
||||
}
|
||||
|
||||
// Logical Unit
|
||||
DWORD lun = GetEffectiveLun();
|
||||
|
||||
// Set status and message
|
||||
ctrl.status = (lun << 5) | status;
|
||||
ctrl.status = (GetEffectiveLun() << 5) | status;
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// TEST UNIT READY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdTestUnitReady()
|
||||
{
|
||||
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
ctrl.device->TestUnitReady(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// REZERO UNIT
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdRezero()
|
||||
{
|
||||
LOGTRACE( "%s REZERO UNIT Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
((Disk *)ctrl.device)->Rezero(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// REQUEST SENSE
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdRequestSense()
|
||||
{
|
||||
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
ctrl.device->RequestSense(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FORMAT UNIT
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdFormat()
|
||||
{
|
||||
LOGTRACE( "%s FORMAT UNIT Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
((Disk *)ctrl.device)->FormatUnit(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// REASSIGN BLOCKS
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdReassignBlocks()
|
||||
{
|
||||
LOGTRACE("%s REASSIGN BLOCKS Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
((Disk *)ctrl.device)->ReassignBlocks(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RESERVE UNIT(16)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdReserveUnit()
|
||||
{
|
||||
LOGTRACE( "%s Reserve(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// RELEASE UNIT(17)
|
||||
//
|
||||
// The reserve/release commands are only used in multi-initiator
|
||||
// environments. RaSCSI doesn't support this use case. However, some old
|
||||
// versions of Solaris will issue the reserve/release commands. We will
|
||||
// just respond with an OK status.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdReleaseUnit()
|
||||
{
|
||||
LOGTRACE( "%s Release(6) Command", __PRETTY_FUNCTION__);
|
||||
|
||||
// status phase
|
||||
Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// READ(6)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdRead6()
|
||||
{
|
||||
// Get record number and block number
|
||||
DWORD record = ctrl.cmd[1] & 0x1f;
|
||||
record <<= 8;
|
||||
record |= ctrl.cmd[2];
|
||||
record <<= 8;
|
||||
record |= ctrl.cmd[3];
|
||||
ctrl.blocks = ctrl.cmd[4];
|
||||
if (ctrl.blocks == 0) {
|
||||
ctrl.blocks = 0x100;
|
||||
}
|
||||
|
||||
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
|
||||
|
||||
// Command processing on drive
|
||||
ctrl.length = ((Disk *)ctrl.device)->Read(ctrl.cmd, ctrl.buffer, record);
|
||||
if (ctrl.length <= 0) {
|
||||
// Failure (Error)
|
||||
Error();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set next block
|
||||
ctrl.next = record + 1;
|
||||
|
||||
// Read phase
|
||||
DataIn();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// WRITE(6)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdWrite6()
|
||||
{
|
||||
// Get record number and block number
|
||||
DWORD record = ctrl.cmd[1] & 0x1f;
|
||||
record <<= 8;
|
||||
record |= ctrl.cmd[2];
|
||||
record <<= 8;
|
||||
record |= ctrl.cmd[3];
|
||||
ctrl.blocks = ctrl.cmd[4];
|
||||
if (ctrl.blocks == 0) {
|
||||
ctrl.blocks = 0x100;
|
||||
}
|
||||
|
||||
LOGTRACE("%s WRITE(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (WORD)record, (WORD)ctrl.blocks);
|
||||
|
||||
// Command processing on drive
|
||||
ctrl.length = ((Disk *)ctrl.device)->WriteCheck(record);
|
||||
if (ctrl.length <= 0) {
|
||||
// Failure (Error)
|
||||
Error();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set next block
|
||||
ctrl.next = record + 1;
|
||||
|
||||
// Write phase
|
||||
DataOut();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SEEK(6)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdSeek6()
|
||||
{
|
||||
LOGTRACE("%s SEEK(6) Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
((Disk *)ctrl.device)->Seek6(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ASSIGN
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdAssign()
|
||||
{
|
||||
LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
|
||||
@ -862,11 +679,6 @@ void SASIDEV::CmdAssign()
|
||||
DataOut();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SPECIFY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::CmdSpecify()
|
||||
{
|
||||
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
||||
@ -1276,6 +1088,6 @@ void SASIDEV::FlushUnit()
|
||||
|
||||
int SASIDEV::GetEffectiveLun() const
|
||||
{
|
||||
return ctrl.lun != -1 ? ctrl.lun : (ctrl.cmd[1] >> 5) & 0x07;
|
||||
return (ctrl.cmd[1] >> 5) & 0x07;
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,15 @@ private:
|
||||
eCmdTestUnitReady = 0x00,
|
||||
eCmdRezero = 0x01,
|
||||
eCmdRequestSense = 0x03,
|
||||
eCmdFormat = 0x06,
|
||||
eCmdFormat = 0x04,
|
||||
eCmdReadCapacity = 0x05,
|
||||
eCmdFormatLegacy = 0x06,
|
||||
eCmdReassign = 0x07,
|
||||
eCmdRead6 = 0x08,
|
||||
eCmdWrite6 = 0x0A,
|
||||
eCmdSeek6 = 0x0B,
|
||||
eCmdSetMcastAddr = 0x0D, // DaynaPort specific command
|
||||
eCmdInquiry = 0x12,
|
||||
eCmdModeSelect6 = 0x15,
|
||||
eCmdReserve6 = 0x16,
|
||||
eCmdRelease6 = 0x17,
|
||||
@ -137,8 +140,7 @@ public:
|
||||
void MsgIn(); // Message in phase
|
||||
void DataOut(); // Data out phase
|
||||
|
||||
// Get LUN based on IDENTIFY message, with LUN from the CDB as fallback
|
||||
int GetEffectiveLun() const;
|
||||
virtual int GetEffectiveLun() const;
|
||||
|
||||
virtual void Error(scsi_defs::sense_key sense_key = scsi_defs::sense_key::NO_SENSE,
|
||||
scsi_defs::asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
||||
@ -152,16 +154,6 @@ protected:
|
||||
virtual void Execute(); // Execution phase
|
||||
|
||||
// Commands
|
||||
void CmdTestUnitReady(); // TEST UNIT READY command
|
||||
void CmdRezero(); // REZERO UNIT command
|
||||
void CmdRequestSense(); // REQUEST SENSE command
|
||||
void CmdFormat(); // FORMAT command
|
||||
void CmdReassignBlocks(); // REASSIGN BLOCKS command
|
||||
void CmdReserveUnit(); // RESERVE UNIT command
|
||||
void CmdReleaseUnit(); // RELEASE UNIT command
|
||||
void CmdRead6(); // READ(6) command
|
||||
void CmdWrite6(); // WRITE(6) command
|
||||
void CmdSeek6(); // SEEK(6) command
|
||||
void CmdAssign(); // ASSIGN command
|
||||
void CmdSpecify(); // SPECIFY command
|
||||
|
||||
|
@ -274,7 +274,7 @@ void SCSIDEV::Execute()
|
||||
|
||||
int lun = GetEffectiveLun();
|
||||
if (!ctrl.unit[lun]) {
|
||||
if ((scsi_command)ctrl.cmd[0] != eCmdInquiry &&
|
||||
if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdInquiry &&
|
||||
(scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) {
|
||||
LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
|
||||
|
||||
@ -911,3 +911,8 @@ bool SCSIDEV::XferOut(bool cont)
|
||||
return false;
|
||||
}
|
||||
|
||||
int SCSIDEV::GetEffectiveLun() const
|
||||
{
|
||||
return ctrl.lun != -1 ? ctrl.lun : (ctrl.cmd[1] >> 5) & 0x07;
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,9 @@ public:
|
||||
|
||||
void Receive() override;
|
||||
|
||||
// Get LUN based on IDENTIFY message, with LUN from the CDB as fallback
|
||||
int GetEffectiveLun() const;
|
||||
|
||||
bool IsSASI() const override { return false; }
|
||||
bool IsSCSI() const override { return true; }
|
||||
|
||||
|
@ -25,7 +25,7 @@ using namespace rascsi_interface;
|
||||
|
||||
DeviceFactory::DeviceFactory()
|
||||
{
|
||||
sector_sizes[SAHD] = { 256, 1024 };
|
||||
sector_sizes[SAHD] = { 256, 512, 1024 };
|
||||
sector_sizes[SCHD] = { 512, 1024, 2048, 4096 };
|
||||
sector_sizes[SCRM] = { 512, 1024, 2048, 4096 };
|
||||
sector_sizes[SCMO] = { 512, 1024, 2048, 4096 };
|
||||
|
@ -71,6 +71,8 @@ public:
|
||||
bool Eject(bool) override;
|
||||
|
||||
private:
|
||||
friend class SASIDEV;
|
||||
|
||||
typedef ModePageDevice super;
|
||||
|
||||
// Commands covered by the SCSI specification (see https://www.t10.org/drafts.htm)
|
||||
@ -94,7 +96,7 @@ private:
|
||||
void Verify16(SASIDEV *);
|
||||
void Seek(SASIDEV *);
|
||||
void Seek10(SASIDEV *);
|
||||
void ReadCapacity10(SASIDEV *) override;
|
||||
virtual void ReadCapacity10(SASIDEV *) override;
|
||||
void ReadCapacity16(SASIDEV *) override;
|
||||
void Reserve(SASIDEV *);
|
||||
void Release(SASIDEV *);
|
||||
|
@ -128,8 +128,6 @@ void PrimaryDevice::RequestSense(SASIDEV *controller)
|
||||
memcpy(ctrl->buffer, buf.data(), allocation_length);
|
||||
ctrl->length = allocation_length;
|
||||
|
||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
||||
|
||||
controller->DataIn();
|
||||
}
|
||||
|
||||
@ -205,6 +203,8 @@ vector<BYTE> PrimaryDevice::RequestSense(int)
|
||||
buf[12] = GetStatusCode() >> 8;
|
||||
buf[13] = GetStatusCode();
|
||||
|
||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
|
||||
void TestUnitReady(SASIDEV *);
|
||||
void RequestSense(SASIDEV *);
|
||||
virtual void Inquiry(SASIDEV *);
|
||||
|
||||
void SetCtrl(SASIDEV::ctrl_t *ctrl) { this->ctrl = ctrl; }
|
||||
|
||||
@ -49,6 +50,5 @@ private:
|
||||
|
||||
Dispatcher<PrimaryDevice, SASIDEV> dispatcher;
|
||||
|
||||
void Inquiry(SASIDEV *);
|
||||
void ReportLuns(SASIDEV *);
|
||||
};
|
||||
|
@ -53,6 +53,11 @@ void SASIHD::Open(const Filepath& path)
|
||||
SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 256, true);
|
||||
SetBlockCount((DWORD)(size >> GetSectorSizeShiftCount()));
|
||||
|
||||
// SASI only supports READ/WRITE(6), limiting the block count to 2^21
|
||||
if (GetBlockCount() > 2097152) {
|
||||
throw io_exception("SASI drives are limited to 2097152 blocks");
|
||||
}
|
||||
|
||||
#if defined(REMOVE_FIXED_SASIHD_SIZE)
|
||||
// Effective size must be a multiple of the sector size
|
||||
size = (size / GetSectorSizeInBytes()) * GetSectorSizeInBytes();
|
||||
@ -83,8 +88,9 @@ void SASIHD::Open(const Filepath& path)
|
||||
|
||||
vector<BYTE> SASIHD::Inquiry() const
|
||||
{
|
||||
assert(false);
|
||||
return vector<BYTE>(0);
|
||||
// Byte 0 = 0: Direct access device
|
||||
|
||||
return vector<BYTE>(2);
|
||||
}
|
||||
|
||||
vector<BYTE> SASIHD::RequestSense(int allocation_length)
|
||||
@ -96,5 +102,29 @@ vector<BYTE> SASIHD::RequestSense(int allocation_length)
|
||||
buf[0] = (BYTE)(GetStatusCode() >> 16);
|
||||
buf[1] = (BYTE)(GetLun() << 5);
|
||||
|
||||
LOGTRACE("%s Status $%02X",__PRETTY_FUNCTION__, buf[0]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void SASIHD::ReadCapacity10(SASIDEV *controller)
|
||||
{
|
||||
BYTE *buf = ctrl->buffer;
|
||||
|
||||
// Create end of logical block address (disk.blocks-1)
|
||||
uint32_t blocks = disk.blocks - 1;
|
||||
buf[0] = (BYTE)(blocks >> 24);
|
||||
buf[1] = (BYTE)(blocks >> 16);
|
||||
buf[2] = (BYTE)(blocks >> 8);
|
||||
buf[3] = (BYTE)blocks;
|
||||
|
||||
// Create block length (1 << disk.size)
|
||||
uint32_t length = 1 << disk.size;
|
||||
buf[4] = (BYTE)(length >> 8);
|
||||
buf[5] = (BYTE)length;
|
||||
|
||||
// the size
|
||||
ctrl->length = 6;
|
||||
|
||||
controller->DataIn();
|
||||
}
|
||||
|
@ -35,4 +35,5 @@ public:
|
||||
|
||||
vector<BYTE> RequestSense(int) override;
|
||||
vector<BYTE> Inquiry() const override;
|
||||
virtual void ReadCapacity10(SASIDEV *) override;
|
||||
};
|
||||
|
@ -817,7 +817,7 @@ BOOL GPIOBUS::GetDP()
|
||||
// Receive command handshake
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::CommandHandShake(BYTE *buf)
|
||||
int GPIOBUS::CommandHandShake(BYTE *buf, bool is_sasi)
|
||||
{
|
||||
int count;
|
||||
|
||||
@ -869,7 +869,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf)
|
||||
// semantics. I fact, these semantics have become a standard in the Atari world.
|
||||
|
||||
// RaSCSI becomes ICD compatible by ignoring the prepended $1F byte before processing the CDB.
|
||||
if (*buf == 0x1F) {
|
||||
if (!is_sasi && *buf == 0x1F) {
|
||||
SetSignal(PIN_REQ, ON);
|
||||
|
||||
ret = WaitSignal(PIN_ACK, TRUE);
|
||||
@ -1592,7 +1592,7 @@ int GPIOBUS::GetCommandByteCount(BYTE opcode) {
|
||||
else if (opcode == 0xA0) {
|
||||
return 12;
|
||||
}
|
||||
else if (opcode >= 0x20 && opcode <= 0x7D) {
|
||||
else if (opcode == 0x05 || (opcode >= 0x20 && opcode <= 0x7D)) {
|
||||
return 10;
|
||||
} else {
|
||||
return 6;
|
||||
|
@ -565,7 +565,7 @@ public:
|
||||
// Set DAT signal
|
||||
BOOL GetDP() override;
|
||||
// Get Data parity signal
|
||||
int CommandHandShake(BYTE *buf) override;
|
||||
int CommandHandShake(BYTE *buf, bool) override;
|
||||
// Command receive handshake
|
||||
int ReceiveHandShake(BYTE *buf, int count) override;
|
||||
// Data receive handshake
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
virtual BOOL GetDP() = 0; // Get parity signal
|
||||
|
||||
virtual DWORD Aquire() = 0;
|
||||
virtual int CommandHandShake(BYTE *buf) = 0;
|
||||
virtual int CommandHandShake(BYTE *buf, bool) = 0;
|
||||
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
|
||||
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
||||
|
||||
@ -131,7 +131,8 @@ namespace scsi_defs {
|
||||
SPC_2 = 4,
|
||||
SPC_3 = 5,
|
||||
SPC_4 = 6,
|
||||
SPC_5 = 7
|
||||
SPC_5 = 7,
|
||||
SPC_6 = 8
|
||||
};
|
||||
|
||||
enum device_type : int {
|
||||
|
Loading…
Reference in New Issue
Block a user