mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-21 23:29:39 +00:00
Feature READ/WRITE LONG(10/16) (#481)
* Partial implementation of READ/WRITE LONG(10) * Comment update * Comment update * Fixed typo * Updated dispatcher table * Added READ/LONG(16) * Added 16 byte opcode * Updated flushing * Logging update * Fixed typo * Check start sector * Renaming
This commit is contained in:
parent
4287145615
commit
1ad1242fad
@ -1227,6 +1227,7 @@ void SASIDEV::FlushUnit()
|
||||
case SASIDEV::eCmdWrite6:
|
||||
case SASIDEV::eCmdWrite10:
|
||||
case SASIDEV::eCmdWrite16:
|
||||
case SASIDEV::eCmdWriteLong16:
|
||||
case SASIDEV::eCmdVerify10:
|
||||
case SASIDEV::eCmdVerify16:
|
||||
break;
|
||||
|
@ -77,6 +77,8 @@ private:
|
||||
eCmdRead16 = 0x88,
|
||||
eCmdWrite16 = 0x8A,
|
||||
eCmdVerify16 = 0x8F,
|
||||
eCmdWriteLong10 = 0x3F,
|
||||
eCmdWriteLong16 = 0x9F,
|
||||
eCmdInvalid = 0xC2,
|
||||
eCmdSasiCmdAssign = 0x0E
|
||||
};
|
||||
|
@ -55,8 +55,10 @@ public:
|
||||
eCmdVerify10 = 0x2F,
|
||||
eCmdSynchronizeCache10 = 0x35,
|
||||
eCmdReadDefectData10 = 0x37,
|
||||
eCmdReadLong10 = 0x3E,
|
||||
eCmdWriteLong10 = 0x3F,
|
||||
eCmdReadToc = 0x43,
|
||||
eCmdGetEventStatusNotification = 0x4a,
|
||||
eCmdGetEventStatusNotification = 0x4A,
|
||||
eCmdModeSelect10 = 0x55,
|
||||
eCmdReserve10 = 0x56,
|
||||
eCmdRelease10 = 0x57,
|
||||
@ -65,7 +67,8 @@ public:
|
||||
eCmdWrite16 = 0x8A,
|
||||
eCmdVerify16 = 0x8F,
|
||||
eCmdSynchronizeCache16 = 0x91,
|
||||
eCmdReadCapacity16 = 0x9E,
|
||||
eCmdReadCapacity16_ReadLong16 = 0x9E,
|
||||
eCmdWriteLong16 = 0x9F,
|
||||
eCmdReportLuns = 0xA0
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,9 @@ Disk::Disk(const std::string id) : Device(id), ScsiPrimaryCommands(), ScsiBlockC
|
||||
AddCommand(SCSIDEV::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10);
|
||||
AddCommand(SCSIDEV::eCmdRead10, "Read10", &Disk::Read10);
|
||||
AddCommand(SCSIDEV::eCmdWrite10, "Write10", &Disk::Write10);
|
||||
AddCommand(SCSIDEV::eCmdReadLong10, "ReadLong10", &Disk::ReadLong10);
|
||||
AddCommand(SCSIDEV::eCmdWriteLong10, "WriteLong10", &Disk::WriteLong10);
|
||||
AddCommand(SCSIDEV::eCmdWriteLong16, "WriteLong16", &Disk::WriteLong16);
|
||||
AddCommand(SCSIDEV::eCmdSeek10, "Seek10", &Disk::Seek10);
|
||||
AddCommand(SCSIDEV::eCmdVerify10, "Verify10", &Disk::Verify10);
|
||||
AddCommand(SCSIDEV::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10);
|
||||
@ -63,7 +66,7 @@ Disk::Disk(const std::string id) : Device(id), ScsiPrimaryCommands(), ScsiBlockC
|
||||
AddCommand(SCSIDEV::eCmdRead16, "Read16", &Disk::Read16);
|
||||
AddCommand(SCSIDEV::eCmdWrite16, "Write16", &Disk::Write16);
|
||||
AddCommand(SCSIDEV::eCmdVerify16, "Verify16", &Disk::Verify16);
|
||||
AddCommand(SCSIDEV::eCmdReadCapacity16, "ReadCapacity16", &Disk::ReadCapacity16);
|
||||
AddCommand(SCSIDEV::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16);
|
||||
AddCommand(SCSIDEV::eCmdReportLuns, "ReportLuns", &Disk::ReportLuns);
|
||||
}
|
||||
|
||||
@ -206,11 +209,6 @@ void Disk::ReassignBlocks(SASIDEV *controller)
|
||||
controller->Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// READ
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Disk::Read(SASIDEV *controller, uint64_t record)
|
||||
{
|
||||
ctrl->length = Read(ctrl->cmd, ctrl->buffer, record);
|
||||
@ -229,42 +227,70 @@ void Disk::Read(SASIDEV *controller, uint64_t record)
|
||||
|
||||
void Disk::Read6(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s READ(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s READ(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, record);
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::Read10(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s READ(10) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s READ(10) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, record);
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::Read16(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s READ(16) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s READ(16) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, record);
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// WRITE
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Disk::ReadWriteLong10(SASIDEV *controller)
|
||||
{
|
||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||
if (ctrl->cmd[7] || ctrl->cmd[8]) {
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckBlockAddress(controller, RW10)) {
|
||||
controller->Status();
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::ReadLong10(SASIDEV *controller)
|
||||
{
|
||||
ReadWriteLong10(controller);
|
||||
}
|
||||
|
||||
void Disk::ReadWriteLong16(SASIDEV *controller)
|
||||
{
|
||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||
if (ctrl->cmd[12] || ctrl->cmd[13]) {
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckBlockAddress(controller, RW16)) {
|
||||
controller->Status();
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::ReadLong16(SASIDEV *controller)
|
||||
{
|
||||
ReadWriteLong16(controller);
|
||||
}
|
||||
|
||||
void Disk::Write(SASIDEV *controller, uint64_t record)
|
||||
{
|
||||
ctrl->length = WriteCheck(record);
|
||||
@ -285,42 +311,44 @@ void Disk::Write(SASIDEV *controller, uint64_t record)
|
||||
|
||||
void Disk::Write6(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s WRITE(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s WRITE(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, record);
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::Write10(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s WRITE(10) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s WRITE(10) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, record);
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::Write16(SASIDEV *controller)
|
||||
{
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s WRITE(16) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s WRITE(16) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, record);
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// VERIFY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Disk::WriteLong10(SASIDEV *controller)
|
||||
{
|
||||
ReadWriteLong10(controller);
|
||||
}
|
||||
|
||||
void Disk::WriteLong16(SASIDEV *controller)
|
||||
{
|
||||
ReadWriteLong16(controller);
|
||||
}
|
||||
|
||||
void Disk::Verify(SASIDEV *controller, uint64_t record)
|
||||
{
|
||||
// if BytChk=0
|
||||
@ -1376,6 +1404,24 @@ void Disk::ReadCapacity16(SASIDEV *controller)
|
||||
controller->DataIn();
|
||||
}
|
||||
|
||||
void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller)
|
||||
{
|
||||
// The service action determines the actual command
|
||||
switch (ctrl->cmd[1] & 0x1f) {
|
||||
case 0x10:
|
||||
ReadCapacity16(controller);
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
ReadLong16(controller);
|
||||
break;
|
||||
|
||||
default:
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Disk::ReportLuns(SASIDEV *controller)
|
||||
{
|
||||
BYTE *buf = ctrl->buffer;
|
||||
@ -1470,9 +1516,43 @@ void Disk::Release10(SASIDEV *controller)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get start sector and sector count for a READ/WRITE operation
|
||||
// Check/Get start sector and sector count for a READ/WRITE or READ/WRITE LONG operation
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode)
|
||||
{
|
||||
uint64_t block = ctrl->cmd[2];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[3];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[4];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[5];
|
||||
|
||||
if (mode == RW16) {
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[6];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[7];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[8];
|
||||
block <<= 8;
|
||||
block |= ctrl->cmd[9];
|
||||
}
|
||||
|
||||
uint64_t capacity = GetBlockCount();
|
||||
if (block > capacity) {
|
||||
ostringstream s;
|
||||
s << "Capacity of " << capacity << " blocks exceeded: " << "Trying to access block " << block;
|
||||
LOGTRACE("%s", s.str().c_str());
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& count, access_mode mode)
|
||||
{
|
||||
if (mode == RW6) {
|
||||
@ -1495,6 +1575,7 @@ bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& coun
|
||||
start |= ctrl->cmd[4];
|
||||
start <<= 8;
|
||||
start |= ctrl->cmd[5];
|
||||
|
||||
if (mode == RW16) {
|
||||
start <<= 8;
|
||||
start |= ctrl->cmd[6];
|
||||
@ -1528,7 +1609,7 @@ bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& coun
|
||||
ostringstream s;
|
||||
s << "Capacity of " << capacity << " blocks exceeded: "
|
||||
<< "Trying to read block " << start << ", block count " << ctrl->blocks;
|
||||
LOGDEBUG("%s", s.str().c_str());
|
||||
LOGTRACE("%s", s.str().c_str());
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
|
||||
return false;
|
||||
}
|
||||
|
@ -101,6 +101,10 @@ public:
|
||||
virtual void Write6(SASIDEV *);
|
||||
void Write10(SASIDEV *) override;
|
||||
void Write16(SASIDEV *) override;
|
||||
void ReadLong10(SASIDEV *) override;
|
||||
void ReadLong16(SASIDEV *) override;
|
||||
void WriteLong10(SASIDEV *) override;
|
||||
void WriteLong16(SASIDEV *) override;
|
||||
void Verify10(SASIDEV *) override;
|
||||
void Verify16(SASIDEV *) override;
|
||||
void Seek(SASIDEV *);
|
||||
@ -137,6 +141,7 @@ public:
|
||||
bool SetGeometryForCapacity(uint64_t);
|
||||
uint64_t GetBlockCount() const;
|
||||
void SetBlockCount(uint32_t);
|
||||
bool CheckBlockAddress(SASIDEV *, access_mode);
|
||||
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
|
||||
bool CheckReady();
|
||||
|
||||
@ -162,6 +167,9 @@ private:
|
||||
void Read(SASIDEV *, uint64_t);
|
||||
void Write(SASIDEV *, uint64_t);
|
||||
void Verify(SASIDEV *, uint64_t);
|
||||
void ReadWriteLong10(SASIDEV *);
|
||||
void ReadWriteLong16(SASIDEV *);
|
||||
void ReadCapacity16_ReadLong16(SASIDEV *);
|
||||
bool Format(const DWORD *cdb);
|
||||
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
||||
int ModeSense10(const DWORD *cdb, BYTE *buf);
|
||||
|
@ -34,7 +34,11 @@ public:
|
||||
virtual void RequestSense(SASIDEV *) = 0;
|
||||
|
||||
// Implemented optional commands
|
||||
virtual void ReadLong10(SASIDEV *) = 0;
|
||||
virtual void WriteLong10(SASIDEV *) = 0;
|
||||
virtual void Verify10(SASIDEV *) = 0;
|
||||
virtual void ReadLong16(SASIDEV *) = 0;
|
||||
virtual void WriteLong16(SASIDEV *) = 0;
|
||||
virtual void Verify16(SASIDEV *) = 0;
|
||||
virtual void ModeSense6(SASIDEV *) = 0;
|
||||
virtual void ModeSense10(SASIDEV *) = 0;
|
||||
|
@ -1551,7 +1551,7 @@ BUS::phase_t GPIOBUS::GetPhaseRaw(DWORD raw_data)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::GetCommandByteCount(BYTE opcode) {
|
||||
if (opcode == 0x88 || opcode == 0x8A || opcode == 0x8F || opcode == 0x91 || opcode == 0x9E) {
|
||||
if (opcode == 0x88 || opcode == 0x8A || opcode == 0x8F || opcode == 0x91 || opcode == 0x9E || opcode == 0x9F) {
|
||||
return 16;
|
||||
}
|
||||
else if (opcode == 0xA0) {
|
||||
|
Loading…
Reference in New Issue
Block a user