mirror of
https://github.com/akuker/RASCSI.git
synced 2025-02-18 01:31:02 +00:00
Code cleanup, in particular related to MODE SENSE (#699)
* Replace member functions * Fixed TODO * Added TODOs * Added TODOs * Removed duplicate code * Fixed return value * CD-ROM mode pages are provided by the CD-ROM implementation * MO mode pages are provided by the MO implementation * Comment update * Removed duplicate code * Removed more duplicate code * Optimization * Updated mode page size handling * Addec TODO * Started more flexible mode page handling * Map mode pages * Page 0 must be last * Error handling update * Updated size handling * Updated map handling * Use map references * Move superclass call * Added comment * Host services also support mode page 0x3f (all pages) * Updated handling of page 0 * Removed duplicate code * Updated buffer size handling * Code cleanup * Removed duplicate code * Use calloc() * Removed duplicate code * Comment update * Fixed buffer offset * Fixed TODO * Added buffer size check * Comment udpate * Logging update * Updated logging * Avoid potential memory leak * Updated handling of page 0 * Added TODO * Comment update * Fixed error message * Use vector instead of byte array * Optimization * More optimizations * Removed duplicate code * Do not try to add more pages when buffer is full * Updated error message * Comment update, fixed host services message length handling * Code cleanup, optimizations * Updated payload handling for page 0 * Fixed TODO * Updated handling of PS field * Fixed offsets * Updated handling for page 0 * Code cleanup * More cleanup * Updated block descriptor handling * Result of REPORT LUNS must not depend on whether a device is ready or not * Printer uses a dynamically allocated buffer * Use realloc * Updated memory handling * Added assertion * Comment update * Fixed initialization * Reset byte transfer flag * Updated usage of realloc * Reverted some changes * Re-added buffer size check * Renaming * Inquiry for hard disk must also work when drive is not ready * Primary device checks EVPD * Added page code check to Inquiry * Explicitly set response level format * Added comment * Removed useless cast * Fixed inconsistencies in setting the additional length * Logging uodate * Updated logging * Made methods const * Moved code * Added TODO * Added vendor page * Reduced visibility * Code cleanup * Mark override * Removed duplicate cast * Synchronized host services mode page handling with other code * Added TODO * Signature update * Moved code * Removed duplicate code * Fixed TODO * Removed duplicate code * Added buffer size check * Improved buffer size check * Code cleanup * Removed useless assertions * Cleanup * Renaming * Added overrides * Removed unnecessary casts * Cleanup * Added TODO * Removed obsolete memset * Removed duplicate code * Logging update * Logging update * Assertion update * Removed useless comments * Code cleanup * Removed obsolete casts * User super typedef * Updated log messages * Fixed #712 * Updated error handling * Removed useless assertions * Reduced casts to Disk* * Updated sector size list argument * Removed obsolete casts * Removed comment
This commit is contained in:
parent
33bfe42017
commit
0e8d89e827
@ -115,7 +115,7 @@ void SASIDEV::Connect(int id, BUS *bus)
|
|||||||
// Set the logical unit
|
// Set the logical unit
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SASIDEV::SetUnit(int no, Device *dev)
|
void SASIDEV::SetUnit(int no, PrimaryDevice *dev)
|
||||||
{
|
{
|
||||||
ASSERT(no < UnitMax);
|
ASSERT(no < UnitMax);
|
||||||
|
|
||||||
@ -626,7 +626,7 @@ void SASIDEV::DataOut()
|
|||||||
void SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
void SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
ctrl.bus->Aquire();
|
||||||
|
|
||||||
// Reset check
|
// Reset check
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
@ -664,7 +664,7 @@ void SASIDEV::CmdTestUnitReady()
|
|||||||
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
((Disk *)ctrl.device)->TestUnitReady(this);
|
ctrl.device->TestUnitReady(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -690,7 +690,7 @@ void SASIDEV::CmdRequestSense()
|
|||||||
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on drive
|
||||||
((Disk *)ctrl.device)->RequestSense(this);
|
ctrl.device->RequestSense(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -847,8 +847,8 @@ void SASIDEV::CmdAssign()
|
|||||||
{
|
{
|
||||||
LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on device
|
||||||
bool status = ((Disk *)ctrl.device)->CheckReady();
|
bool status = ctrl.device->CheckReady();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
@ -871,8 +871,8 @@ void SASIDEV::CmdSpecify()
|
|||||||
{
|
{
|
||||||
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Command processing on drive
|
// Command processing on device
|
||||||
bool status = ((Disk *)ctrl.device)->CheckReady();
|
bool status =ctrl.device->CheckReady();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
// Failure (Error)
|
// Failure (Error)
|
||||||
Error();
|
Error();
|
||||||
@ -1143,10 +1143,12 @@ bool SASIDEV::XferOut(bool cont)
|
|||||||
case SASIDEV::eCmdWrite16:
|
case SASIDEV::eCmdWrite16:
|
||||||
case SASIDEV::eCmdVerify10:
|
case SASIDEV::eCmdVerify10:
|
||||||
case SASIDEV::eCmdVerify16:
|
case SASIDEV::eCmdVerify16:
|
||||||
|
{
|
||||||
// If we're a host bridge, use the host bridge's SendMessage10 function
|
// If we're a host bridge, use the host bridge's SendMessage10 function
|
||||||
// TODO This class must not know about SCSIBR
|
// TODO This class must not know about SCSIBR
|
||||||
if (device->IsBridge()) {
|
SCSIBR *bridge = dynamic_cast<SCSIBR *>(device);
|
||||||
if (!((SCSIBR*)device)->SendMessage10(ctrl.cmd, ctrl.buffer)) {
|
if (bridge) {
|
||||||
|
if (!bridge->SendMessage10(ctrl.cmd, ctrl.buffer)) {
|
||||||
// write failed
|
// write failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1158,8 +1160,9 @@ bool SASIDEV::XferOut(bool cont)
|
|||||||
|
|
||||||
// Special case Write function for DaynaPort
|
// Special case Write function for DaynaPort
|
||||||
// TODO This class must not know about DaynaPort
|
// TODO This class must not know about DaynaPort
|
||||||
if (device->IsDaynaPort()) {
|
SCSIDaynaPort *daynaport = dynamic_cast<SCSIDaynaPort *>(device);
|
||||||
if (!((SCSIDaynaPort*)device)->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
if (daynaport) {
|
||||||
|
if (!daynaport->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
||||||
// write failed
|
// write failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1191,6 +1194,7 @@ bool SASIDEV::XferOut(bool cont)
|
|||||||
// If normal, work setting
|
// If normal, work setting
|
||||||
ctrl.offset = 0;
|
ctrl.offset = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// SPECIFY(SASI only)
|
// SPECIFY(SASI only)
|
||||||
case SASIDEV::eCmdInvalid:
|
case SASIDEV::eCmdInvalid:
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
class PrimaryDevice;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
@ -123,10 +124,10 @@ public:
|
|||||||
DWORD length; // Transfer remaining length
|
DWORD length; // Transfer remaining length
|
||||||
|
|
||||||
// Logical unit
|
// Logical unit
|
||||||
Device *unit[UnitMax];
|
PrimaryDevice *unit[UnitMax];
|
||||||
|
|
||||||
// The current device
|
// The current device
|
||||||
Device *device;
|
PrimaryDevice *device;
|
||||||
|
|
||||||
// The LUN from the IDENTIFY message
|
// The LUN from the IDENTIFY message
|
||||||
int lun;
|
int lun;
|
||||||
@ -144,7 +145,7 @@ public:
|
|||||||
// Connect
|
// Connect
|
||||||
void Connect(int id, BUS *sbus); // Controller connection
|
void Connect(int id, BUS *sbus); // Controller connection
|
||||||
Device* GetUnit(int no); // Get logical unit
|
Device* GetUnit(int no); // Get logical unit
|
||||||
void SetUnit(int no, Device *dev); // Logical unit setting
|
void SetUnit(int no, PrimaryDevice *dev); // Logical unit setting
|
||||||
bool HasUnit(); // Has a valid logical unit
|
bool HasUnit(); // Has a valid logical unit
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
SCSIDEV::SCSIDEV() : SASIDEV()
|
SCSIDEV::SCSIDEV() : SASIDEV()
|
||||||
{
|
{
|
||||||
|
scsi.is_byte_transfer = false;
|
||||||
scsi.bytes_to_transfer = 0;
|
scsi.bytes_to_transfer = 0;
|
||||||
shutdown_mode = NONE;
|
shutdown_mode = NONE;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ SCSIDEV::~SCSIDEV()
|
|||||||
|
|
||||||
void SCSIDEV::Reset()
|
void SCSIDEV::Reset()
|
||||||
{
|
{
|
||||||
|
scsi.is_byte_transfer = false;
|
||||||
scsi.bytes_to_transfer = 0;
|
scsi.bytes_to_transfer = 0;
|
||||||
|
|
||||||
// Work initialization
|
// Work initialization
|
||||||
@ -63,7 +65,7 @@ BUS::phase_t SCSIDEV::Process(int initiator_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get bus information
|
// Get bus information
|
||||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
ctrl.bus->Aquire();
|
||||||
|
|
||||||
// Check to see if the reset signal was asserted
|
// Check to see if the reset signal was asserted
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
@ -356,7 +358,7 @@ void SCSIDEV::MsgOut()
|
|||||||
void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
ctrl.bus->Aquire();
|
||||||
|
|
||||||
// Reset check
|
// Reset check
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
@ -402,24 +404,11 @@ void SCSIDEV::Send()
|
|||||||
ASSERT(!ctrl.bus->GetREQ());
|
ASSERT(!ctrl.bus->GetREQ());
|
||||||
ASSERT(ctrl.bus->GetIO());
|
ASSERT(ctrl.bus->GetIO());
|
||||||
|
|
||||||
//if Length! = 0, send
|
|
||||||
if (ctrl.length != 0) {
|
if (ctrl.length != 0) {
|
||||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length "
|
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length "
|
||||||
+ to_string(ctrl.length)).c_str());
|
+ to_string(ctrl.length)).c_str());
|
||||||
|
|
||||||
// TODO Get rid of Daynaport specific code in this class
|
int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0]->GetSendDelay());
|
||||||
// The Daynaport needs to have a delay after the size/flags field
|
|
||||||
// of the read response. In the MacOS driver, it looks like the
|
|
||||||
// driver is doing two "READ" system calls.
|
|
||||||
int len;
|
|
||||||
if (ctrl.unit[0] && ctrl.unit[0]->IsDaynaPort()) {
|
|
||||||
len = ((GPIOBUS*)ctrl.bus)->SendHandShake(
|
|
||||||
&ctrl.buffer[ctrl.offset], ctrl.length, SCSIDaynaPort::DAYNAPORT_READ_HEADER_SZ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, BUS::SEND_NO_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you cannot send all, move to status phase
|
// If you cannot send all, move to status phase
|
||||||
if (len != (int)ctrl.length) {
|
if (len != (int)ctrl.length) {
|
||||||
@ -522,13 +511,13 @@ void SCSIDEV::Receive()
|
|||||||
|
|
||||||
// Length != 0 if received
|
// Length != 0 if received
|
||||||
if (ctrl.length != 0) {
|
if (ctrl.length != 0) {
|
||||||
LOGTRACE("%s length is %d", __PRETTY_FUNCTION__, (int)ctrl.length);
|
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, (int)ctrl.length);
|
||||||
// Receive
|
// Receive
|
||||||
len = ctrl.bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length);
|
len = ctrl.bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||||
|
|
||||||
// If not able to receive all, move to status phase
|
// If not able to receive all, move to status phase
|
||||||
if (len != (int)ctrl.length) {
|
if (len != (int)ctrl.length) {
|
||||||
LOGERROR("%s Not able to receive %d data, only received %d. Going to error",__PRETTY_FUNCTION__, (int)ctrl.length, len);
|
LOGERROR("%s Not able to receive %d bytes of data, only received %d. Going to error",__PRETTY_FUNCTION__, (int)ctrl.length, len);
|
||||||
Error();
|
Error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -658,7 +647,7 @@ void SCSIDEV::Receive()
|
|||||||
// Transfer period factor (limited to 50 x 4 = 200ns)
|
// Transfer period factor (limited to 50 x 4 = 200ns)
|
||||||
scsi.syncperiod = scsi.msb[i + 3];
|
scsi.syncperiod = scsi.msb[i + 3];
|
||||||
if (scsi.syncperiod > 50) {
|
if (scsi.syncperiod > 50) {
|
||||||
scsi.syncoffset = 50;
|
scsi.syncperiod = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
// REQ/ACK offset(limited to 16)
|
// REQ/ACK offset(limited to 16)
|
||||||
@ -736,13 +725,13 @@ void SCSIDEV::ReceiveBytes()
|
|||||||
ASSERT(!ctrl.bus->GetIO());
|
ASSERT(!ctrl.bus->GetIO());
|
||||||
|
|
||||||
if (ctrl.length) {
|
if (ctrl.length) {
|
||||||
LOGTRACE("%s length is %d", __PRETTY_FUNCTION__, ctrl.length);
|
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, ctrl.length);
|
||||||
|
|
||||||
len = ctrl.bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length);
|
len = ctrl.bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||||
|
|
||||||
// If not able to receive all, move to status phase
|
// If not able to receive all, move to status phase
|
||||||
if (len != ctrl.length) {
|
if (len != ctrl.length) {
|
||||||
LOGERROR("%s Not able to receive %d data, only received %d. Going to error",
|
LOGERROR("%s Not able to receive %d bytes of data, only received %d. Going to error",
|
||||||
__PRETTY_FUNCTION__, ctrl.length, len);
|
__PRETTY_FUNCTION__, ctrl.length, len);
|
||||||
Error();
|
Error();
|
||||||
return;
|
return;
|
||||||
@ -904,6 +893,8 @@ bool SCSIDEV::XferOut(bool cont)
|
|||||||
|
|
||||||
ASSERT(ctrl.phase == BUS::dataout);
|
ASSERT(ctrl.phase == BUS::dataout);
|
||||||
|
|
||||||
|
scsi.is_byte_transfer = false;
|
||||||
|
|
||||||
PrimaryDevice *device = dynamic_cast<PrimaryDevice *>(ctrl.unit[GetEffectiveLun()]);
|
PrimaryDevice *device = dynamic_cast<PrimaryDevice *>(ctrl.unit[GetEffectiveLun()]);
|
||||||
if (device && ctrl.cmd[0] == scsi_defs::eCmdWrite6) {
|
if (device && ctrl.cmd[0] == scsi_defs::eCmdWrite6) {
|
||||||
return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer);
|
return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer);
|
||||||
|
@ -184,8 +184,4 @@ public:
|
|||||||
|
|
||||||
bool IsSASIHD() const { return type == "SAHD"; }
|
bool IsSASIHD() const { return type == "SAHD"; }
|
||||||
bool IsSCSIHD() const { return type == "SCHD" || type == "SCRM"; }
|
bool IsSCSIHD() const { return type == "SCHD" || type == "SCRM"; }
|
||||||
bool IsCdRom() const { return type == "SCCD"; }
|
|
||||||
bool IsMo() const { return type == "SCMO"; }
|
|
||||||
bool IsBridge() const { return type == "SCBR"; }
|
|
||||||
bool IsDaynaPort() const { return type == "SCDP"; }
|
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,6 @@ DeviceFactory::DeviceFactory()
|
|||||||
sector_sizes[SCHD] = { 512, 1024, 2048, 4096 };
|
sector_sizes[SCHD] = { 512, 1024, 2048, 4096 };
|
||||||
sector_sizes[SCRM] = { 512, 1024, 2048, 4096 };
|
sector_sizes[SCRM] = { 512, 1024, 2048, 4096 };
|
||||||
sector_sizes[SCMO] = { 512, 1024, 2048, 4096 };
|
sector_sizes[SCMO] = { 512, 1024, 2048, 4096 };
|
||||||
// Some old Sun CD-ROM drives support 512 bytes per sector
|
|
||||||
sector_sizes[SCCD] = { 512, 2048};
|
sector_sizes[SCCD] = { 512, 2048};
|
||||||
|
|
||||||
// 128 MB, 512 bytes per sector, 248826 sectors
|
// 128 MB, 512 bytes per sector, 248826 sectors
|
||||||
@ -124,20 +123,17 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
|||||||
try {
|
try {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SAHD:
|
case SAHD:
|
||||||
device = new SASIHD();
|
device = new SASIHD(sector_sizes[SAHD]);
|
||||||
device->SetSupportedLuns(2);
|
device->SetSupportedLuns(2);
|
||||||
device->SetProduct("SASI HD");
|
device->SetProduct("SASI HD");
|
||||||
((Disk *)device)->SetSectorSizes(sector_sizes[SAHD]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCHD: {
|
case SCHD: {
|
||||||
string ext = GetExtension(filename);
|
string ext = GetExtension(filename);
|
||||||
if (ext == "hdn" || ext == "hdi" || ext == "nhd") {
|
if (ext == "hdn" || ext == "hdi" || ext == "nhd") {
|
||||||
device = new SCSIHD_NEC();
|
device = new SCSIHD_NEC({ 512 });
|
||||||
((Disk *)device)->SetSectorSizes({ 512 });
|
|
||||||
} else {
|
} else {
|
||||||
device = new SCSIHD(false);
|
device = new SCSIHD(sector_sizes[SCHD], false);
|
||||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCHD]);
|
|
||||||
|
|
||||||
// Some Apple tools require a particular drive identification
|
// Some Apple tools require a particular drive identification
|
||||||
if (ext == "hda") {
|
if (ext == "hda") {
|
||||||
@ -151,34 +147,30 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SCRM:
|
case SCRM:
|
||||||
device = new SCSIHD(true);
|
device = new SCSIHD(sector_sizes[SCRM], true);
|
||||||
device->SetProtectable(true);
|
device->SetProtectable(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
device->SetLockable(true);
|
device->SetLockable(true);
|
||||||
device->SetProduct("SCSI HD (REM.)");
|
device->SetProduct("SCSI HD (REM.)");
|
||||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCRM]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCMO:
|
case SCMO:
|
||||||
device = new SCSIMO();
|
device = new SCSIMO(sector_sizes[SCMO], geometries[SCMO]);
|
||||||
device->SetProtectable(true);
|
device->SetProtectable(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
device->SetLockable(true);
|
device->SetLockable(true);
|
||||||
device->SetProduct("SCSI MO");
|
device->SetProduct("SCSI MO");
|
||||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCRM]);
|
|
||||||
((Disk *)device)->SetGeometries(geometries[SCMO]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCCD:
|
case SCCD:
|
||||||
device = new SCSICD();
|
device = new SCSICD(sector_sizes[SCCD]);
|
||||||
device->SetReadOnly(true);
|
device->SetReadOnly(true);
|
||||||
device->SetStoppable(true);
|
device->SetStoppable(true);
|
||||||
device->SetRemovable(true);
|
device->SetRemovable(true);
|
||||||
device->SetLockable(true);
|
device->SetLockable(true);
|
||||||
device->SetProduct("SCSI CD-ROM");
|
device->SetProduct("SCSI CD-ROM");
|
||||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCCD]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCBR:
|
case SCBR:
|
||||||
|
@ -38,8 +38,8 @@ Disk::Disk(const string& id) : ModePageDevice(id), ScsiBlockCommands()
|
|||||||
dispatcher.AddCommand(eCmdRead6, "Read6", &Disk::Read6);
|
dispatcher.AddCommand(eCmdRead6, "Read6", &Disk::Read6);
|
||||||
dispatcher.AddCommand(eCmdWrite6, "Write6", &Disk::Write6);
|
dispatcher.AddCommand(eCmdWrite6, "Write6", &Disk::Write6);
|
||||||
dispatcher.AddCommand(eCmdSeek6, "Seek6", &Disk::Seek6);
|
dispatcher.AddCommand(eCmdSeek6, "Seek6", &Disk::Seek6);
|
||||||
dispatcher.AddCommand(eCmdReserve6, "Reserve6", &Disk::Reserve6);
|
dispatcher.AddCommand(eCmdReserve6, "Reserve6", &Disk::Reserve);
|
||||||
dispatcher.AddCommand(eCmdRelease6, "Release6", &Disk::Release6);
|
dispatcher.AddCommand(eCmdRelease6, "Release6", &Disk::Release);
|
||||||
dispatcher.AddCommand(eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit);
|
dispatcher.AddCommand(eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit);
|
||||||
dispatcher.AddCommand(eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic);
|
dispatcher.AddCommand(eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic);
|
||||||
dispatcher.AddCommand(eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval);
|
dispatcher.AddCommand(eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval);
|
||||||
@ -54,8 +54,8 @@ Disk::Disk(const string& id) : ModePageDevice(id), ScsiBlockCommands()
|
|||||||
dispatcher.AddCommand(eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10);
|
dispatcher.AddCommand(eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache10);
|
||||||
dispatcher.AddCommand(eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16);
|
dispatcher.AddCommand(eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16);
|
||||||
dispatcher.AddCommand(eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10);
|
dispatcher.AddCommand(eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10);
|
||||||
dispatcher.AddCommand(eCmdReserve10, "Reserve10", &Disk::Reserve10);
|
dispatcher.AddCommand(eCmdReserve10, "Reserve10", &Disk::Reserve);
|
||||||
dispatcher.AddCommand(eCmdRelease10, "Release10", &Disk::Release10);
|
dispatcher.AddCommand(eCmdRelease10, "Release10", &Disk::Release);
|
||||||
dispatcher.AddCommand(eCmdRead16, "Read16", &Disk::Read16);
|
dispatcher.AddCommand(eCmdRead16, "Read16", &Disk::Read16);
|
||||||
dispatcher.AddCommand(eCmdWrite16, "Write16", &Disk::Write16);
|
dispatcher.AddCommand(eCmdWrite16, "Write16", &Disk::Write16);
|
||||||
dispatcher.AddCommand(eCmdVerify16, "Verify16", &Disk::Verify16);
|
dispatcher.AddCommand(eCmdVerify16, "Verify16", &Disk::Verify16);
|
||||||
@ -101,7 +101,7 @@ bool Disk::Dispatch(SCSIDEV *controller)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void Disk::Open(const Filepath& path)
|
void Disk::Open(const Filepath& path)
|
||||||
{
|
{
|
||||||
ASSERT(disk.blocks > 0);
|
assert(disk.blocks > 0);
|
||||||
|
|
||||||
SetReady(true);
|
SetReady(true);
|
||||||
|
|
||||||
@ -183,8 +183,6 @@ void Disk::Read6(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
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, start);
|
Read(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,8 +191,6 @@ void Disk::Read10(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
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, start);
|
Read(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,8 +199,6 @@ void Disk::Read16(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
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, start);
|
Read(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,8 +261,6 @@ void Disk::Write6(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
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, start);
|
Write(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,8 +269,6 @@ void Disk::Write10(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
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, start);
|
Write(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,8 +277,6 @@ void Disk::Write16(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
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, start);
|
Write(controller, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,8 +317,6 @@ void Disk::Verify10(SASIDEV *controller)
|
|||||||
// Get record number and block number
|
// Get record number and block number
|
||||||
uint64_t record;
|
uint64_t record;
|
||||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW10)) {
|
if (GetStartAndCount(controller, record, ctrl->blocks, RW10)) {
|
||||||
LOGDEBUG("%s VERIFY(10) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
|
||||||
|
|
||||||
Verify(controller, record);
|
Verify(controller, record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,8 +326,6 @@ void Disk::Verify16(SASIDEV *controller)
|
|||||||
// Get record number and block number
|
// Get record number and block number
|
||||||
uint64_t record;
|
uint64_t record;
|
||||||
if (GetStartAndCount(controller, record, ctrl->blocks, RW16)) {
|
if (GetStartAndCount(controller, record, ctrl->blocks, RW16)) {
|
||||||
LOGDEBUG("%s VERIFY(16) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)record, ctrl->blocks);
|
|
||||||
|
|
||||||
Verify(controller, record);
|
Verify(controller, record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,7 +380,7 @@ void Disk::SynchronizeCache16(SASIDEV *controller)
|
|||||||
|
|
||||||
void Disk::ReadDefectData10(SASIDEV *controller)
|
void Disk::ReadDefectData10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl->length = ReadDefectData10(ctrl->cmd, ctrl->buffer);
|
ctrl->length = ReadDefectData10(ctrl->cmd, ctrl->buffer, ctrl->bufsize);
|
||||||
if (ctrl->length <= 4) {
|
if (ctrl->length <= 4) {
|
||||||
controller->Error();
|
controller->Error();
|
||||||
return;
|
return;
|
||||||
@ -438,29 +422,9 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
|||||||
int length = (int)cdb[4];
|
int length = (int)cdb[4];
|
||||||
memset(buf, 0, length);
|
memset(buf, 0, length);
|
||||||
|
|
||||||
// Get changeable flag
|
|
||||||
bool change = (cdb[2] & 0xc0) == 0x40;
|
|
||||||
|
|
||||||
// Get page code (0x00 is valid from the beginning)
|
|
||||||
int page = cdb[2] & 0x3f;
|
|
||||||
bool valid = page == 0x00;
|
|
||||||
|
|
||||||
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
|
|
||||||
// Basic information
|
// Basic information
|
||||||
int size = 4;
|
int size = 4;
|
||||||
|
|
||||||
// MEDIUM TYPE
|
|
||||||
if (IsMo()) {
|
|
||||||
// Optical reversible or erasable
|
|
||||||
buf[1] = 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEVICE SPECIFIC PARAMETER
|
|
||||||
if (IsProtected()) {
|
|
||||||
buf[2] = 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add block descriptor if DBD is 0
|
// Add block descriptor if DBD is 0
|
||||||
if ((cdb[1] & 0x08) == 0) {
|
if ((cdb[1] & 0x08) == 0) {
|
||||||
// Mode parameter header, block descriptor length
|
// Mode parameter header, block descriptor length
|
||||||
@ -486,70 +450,14 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
|||||||
size = 12;
|
size = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page code 1 (read-write error recovery)
|
int pages_size = super::AddModePages(cdb, &buf[size], length - size);
|
||||||
if (page == 0x01 || page == 0x3f) {
|
if (!pages_size) {
|
||||||
size += AddErrorPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 3 (format device)
|
|
||||||
if (page == 0x03 || page == 0x3f) {
|
|
||||||
size += AddFormatPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 4 (drive parameter)
|
|
||||||
if (page == 0x04 || page == 0x3f) {
|
|
||||||
size += AddDrivePage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 6 (optical)
|
|
||||||
if (IsMo()) {
|
|
||||||
if (page == 0x06 || page == 0x3f) {
|
|
||||||
size += AddOptionPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 8 (caching)
|
|
||||||
if (page == 0x08 || page == 0x3f) {
|
|
||||||
size += AddCachePage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 13 (CD-ROM)
|
|
||||||
if (IsCdRom()) {
|
|
||||||
if (page == 0x0d || page == 0x3f) {
|
|
||||||
size += AddCDROMPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 14 (CD-DA)
|
|
||||||
if (IsCdRom()) {
|
|
||||||
if (page == 0x0e || page == 0x3f) {
|
|
||||||
size += AddCDDAPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page (vendor special)
|
|
||||||
int ret = AddVendorPage(page, change, &buf[size]);
|
|
||||||
if (ret > 0) {
|
|
||||||
size += ret;
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
size += pages_size;
|
||||||
|
|
||||||
// Do not return more than ALLOCATION LENGTH bytes
|
// Do not return more than ALLOCATION LENGTH bytes
|
||||||
if (size > length) {
|
if (size > length) {
|
||||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
|
||||||
size = length;
|
size = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,40 +467,18 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
int Disk::ModeSense10(const DWORD *cdb, BYTE *buf, int max_length)
|
||||||
{
|
{
|
||||||
// Get length, clear buffer
|
// Get length, clear buffer
|
||||||
int length = cdb[7];
|
int length = (cdb[7] << 8) | cdb[8];
|
||||||
length <<= 8;
|
if (length > max_length) {
|
||||||
length |= cdb[8];
|
length = max_length;
|
||||||
if (length > 0x800) {
|
|
||||||
length = 0x800;
|
|
||||||
}
|
}
|
||||||
memset(buf, 0, length);
|
memset(buf, 0, length);
|
||||||
|
|
||||||
// Get changeable flag
|
|
||||||
bool change = (cdb[2] & 0xc0) == 0x40;
|
|
||||||
|
|
||||||
// Get page code (0x00 is valid from the beginning)
|
|
||||||
int page = cdb[2] & 0x3f;
|
|
||||||
bool valid = page == 0x00;
|
|
||||||
|
|
||||||
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
|
|
||||||
// Basic Information
|
// Basic Information
|
||||||
int size = 8;
|
int size = 8;
|
||||||
|
|
||||||
// MEDIUM TYPE
|
|
||||||
if (IsMo()) {
|
|
||||||
// Optical reversible or erasable
|
|
||||||
buf[2] = 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEVICE SPECIFIC PARAMETER
|
|
||||||
if (IsProtected()) {
|
|
||||||
buf[3] = 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add block descriptor if DBD is 0
|
// Add block descriptor if DBD is 0
|
||||||
if ((cdb[1] & 0x08) == 0) {
|
if ((cdb[1] & 0x08) == 0) {
|
||||||
// Only if ready
|
// Only if ready
|
||||||
@ -646,70 +532,14 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page code 1 (read-write error recovery)
|
int pages_size = super::AddModePages(cdb, &buf[size], length - size);
|
||||||
if (page == 0x01 || page == 0x3f) {
|
if (!pages_size) {
|
||||||
size += AddErrorPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 3 (format device)
|
|
||||||
if (page == 0x03 || page == 0x3f) {
|
|
||||||
size += AddFormatPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 4 (drive parameter)
|
|
||||||
if (page == 0x04 || page == 0x3f) {
|
|
||||||
size += AddDrivePage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 6 (optical)
|
|
||||||
if (IsMo()) {
|
|
||||||
if (page == 0x06 || page == 0x3f) {
|
|
||||||
size += AddOptionPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 8 (caching)
|
|
||||||
if (page == 0x08 || page == 0x3f) {
|
|
||||||
size += AddCachePage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 13 (CD-ROM)
|
|
||||||
if (IsCdRom()) {
|
|
||||||
if (page == 0x0d || page == 0x3f) {
|
|
||||||
size += AddCDROMPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page code 14 (CD-DA)
|
|
||||||
if (IsCdRom()) {
|
|
||||||
if (page == 0x0e || page == 0x3f) {
|
|
||||||
size += AddCDDAPage(change, &buf[size]);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page (vendor special)
|
|
||||||
int ret = AddVendorPage(page, change, &buf[size]);
|
|
||||||
if (ret > 0) {
|
|
||||||
size += ret;
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
size += pages_size;
|
||||||
|
|
||||||
// Do not return more than ALLOCATION LENGTH bytes
|
// Do not return more than ALLOCATION LENGTH bytes
|
||||||
if (size > length) {
|
if (size > length) {
|
||||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
|
||||||
size = length;
|
size = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,28 +550,65 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddErrorPage(bool change, BYTE *buf)
|
void Disk::SetDeviceParameters(BYTE *buf)
|
||||||
{
|
{
|
||||||
// Set the message length
|
// DEVICE SPECIFIC PARAMETER
|
||||||
buf[0] = 0x01;
|
if (IsProtected()) {
|
||||||
buf[1] = 0x0a;
|
buf[3] = 0x80;
|
||||||
|
}
|
||||||
// Retry count is 0, limit time uses internal default value
|
|
||||||
return 12;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddFormatPage(bool change, BYTE *buf)
|
void Disk::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
{
|
{
|
||||||
// Set the message length
|
// Page code 1 (read-write error recovery)
|
||||||
buf[0] = 0x80 | 0x03;
|
if (page == 0x01 || page == 0x3f) {
|
||||||
buf[1] = 0x16;
|
AddErrorPage(pages, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page code 3 (format device)
|
||||||
|
if (page == 0x03 || page == 0x3f) {
|
||||||
|
AddFormatPage(pages, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page code 4 (drive parameter)
|
||||||
|
if (page == 0x04 || page == 0x3f) {
|
||||||
|
AddDrivePage(pages, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page code 8 (caching)
|
||||||
|
if (page == 0x08 || page == 0x3f) {
|
||||||
|
AddCachePage(pages, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page (vendor special)
|
||||||
|
AddVendorPage(pages, page, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disk::AddErrorPage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(12);
|
||||||
|
|
||||||
|
// Retry count is 0, limit time uses internal default value
|
||||||
|
|
||||||
|
pages[1] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disk::AddFormatPage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(24);
|
||||||
|
|
||||||
|
// Page can be saved
|
||||||
|
buf[0] = 0x80;
|
||||||
|
|
||||||
// Show the number of bytes in the physical sector as changeable
|
// Show the number of bytes in the physical sector as changeable
|
||||||
// (though it cannot be changed in practice)
|
// (though it cannot be changed in practice)
|
||||||
if (change) {
|
if (changeable) {
|
||||||
buf[0xc] = 0xff;
|
buf[0xc] = 0xff;
|
||||||
buf[0xd] = 0xff;
|
buf[0xd] = 0xff;
|
||||||
return 24;
|
|
||||||
|
pages[3] = buf;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsReady()) {
|
if (IsReady()) {
|
||||||
@ -763,18 +630,18 @@ int Disk::AddFormatPage(bool change, BYTE *buf)
|
|||||||
buf[20] = 0x20;
|
buf[20] = 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 24;
|
pages[3] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddDrivePage(bool change, BYTE *buf)
|
void Disk::AddDrivePage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
{
|
{
|
||||||
// Set the message length
|
vector<BYTE> buf(24);
|
||||||
buf[0] = 0x04;
|
|
||||||
buf[1] = 0x16;
|
|
||||||
|
|
||||||
// No changeable area
|
// No changeable area
|
||||||
if (change) {
|
if (changeable) {
|
||||||
return 24;
|
pages[4] = buf;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsReady()) {
|
if (IsReady()) {
|
||||||
@ -791,81 +658,30 @@ int Disk::AddDrivePage(bool change, BYTE *buf)
|
|||||||
buf[0x5] = 0x8;
|
buf[0x5] = 0x8;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 24;
|
pages[4] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddOptionPage(bool change, BYTE *buf)
|
void Disk::AddCachePage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
{
|
{
|
||||||
// Set the message length
|
vector<BYTE> buf(12);
|
||||||
buf[0] = 0x06;
|
|
||||||
buf[1] = 0x02;
|
|
||||||
|
|
||||||
// Do not report update blocks
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::AddCachePage(bool change, BYTE *buf)
|
|
||||||
{
|
|
||||||
// Set the message length
|
|
||||||
buf[0] = 0x08;
|
|
||||||
buf[1] = 0x0a;
|
|
||||||
|
|
||||||
// Only read cache is valid, no prefetch
|
// Only read cache is valid, no prefetch
|
||||||
return 12;
|
|
||||||
|
pages[8] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddCDROMPage(bool change, BYTE *buf)
|
void Disk::AddVendorPage(map<int, vector<BYTE>>&, int, bool) const
|
||||||
{
|
{
|
||||||
// Set the message length
|
// Nothing to add by default
|
||||||
buf[0] = 0x0d;
|
|
||||||
buf[1] = 0x06;
|
|
||||||
|
|
||||||
// No changeable area
|
|
||||||
if (change) {
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 seconds for inactive timer
|
|
||||||
buf[3] = 0x05;
|
|
||||||
|
|
||||||
// MSF multiples are 60 and 75 respectively
|
|
||||||
buf[5] = 60;
|
|
||||||
buf[7] = 75;
|
|
||||||
|
|
||||||
return 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::AddCDDAPage(bool change, BYTE *buf)
|
int Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf, int max_length)
|
||||||
{
|
{
|
||||||
// Set the message length
|
|
||||||
buf[0] = 0x0e;
|
|
||||||
buf[1] = 0x0e;
|
|
||||||
|
|
||||||
// Audio waits for operation completion and allows
|
|
||||||
// PLAY across multiple tracks
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::AddVendorPage(int /*page*/, bool /*change*/, BYTE *buf)
|
|
||||||
{
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf)
|
|
||||||
{
|
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Get length, clear buffer
|
// Get length, clear buffer
|
||||||
DWORD length = cdb[7];
|
int length = (cdb[7] << 8) | cdb[8];
|
||||||
length <<= 8;
|
if (length > max_length) {
|
||||||
length |= cdb[8];
|
length = max_length;
|
||||||
if (length > 0x800) {
|
|
||||||
length = 0x800;
|
|
||||||
}
|
}
|
||||||
ASSERT((length >= 0) && (length < 0x800));
|
|
||||||
memset(buf, 0, length);
|
memset(buf, 0, length);
|
||||||
|
|
||||||
// P/G/FORMAT
|
// P/G/FORMAT
|
||||||
@ -909,17 +725,10 @@ bool Disk::Format(const DWORD *cdb)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// READ
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// TODO Read more than one block in a single call. Currently blocked by the SASI code (missing early range check)
|
// TODO Read more than one block in a single call. Currently blocked by the SASI code (missing early range check)
|
||||||
// and the track-oriented cache.
|
// and the track-oriented cache.
|
||||||
int Disk::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
int Disk::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
if (!CheckReady()) {
|
if (!CheckReady()) {
|
||||||
@ -939,14 +748,9 @@ int Disk::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
return (1 << disk.size);
|
return 1 << disk.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// WRITE check
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int Disk::WriteCheck(DWORD block)
|
int Disk::WriteCheck(DWORD block)
|
||||||
{
|
{
|
||||||
// Status check
|
// Status check
|
||||||
@ -968,20 +772,13 @@ int Disk::WriteCheck(DWORD block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
return (1 << disk.size);
|
return 1 << disk.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// WRITE
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// TODO Write more than one block in a single call. Currently blocked by the SASI code (missing early range check)
|
// TODO Write more than one block in a single call. Currently blocked by the SASI code (missing early range check)
|
||||||
// and the track-oriented cache.
|
// and the track-oriented cache.
|
||||||
bool Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
bool Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// Error if not ready
|
// Error if not ready
|
||||||
@ -1011,6 +808,7 @@ bool Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO For SCSI the specification mandates that the block address is verified
|
||||||
void Disk::Seek(SASIDEV *controller)
|
void Disk::Seek(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!CheckReady()) {
|
if (!CheckReady()) {
|
||||||
@ -1089,23 +887,13 @@ bool Disk::SendDiag(const DWORD *cdb)
|
|||||||
|
|
||||||
void Disk::ReadCapacity10(SASIDEV *controller)
|
void Disk::ReadCapacity10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
|
if (!CheckReady() || disk.blocks <= 0) {
|
||||||
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BYTE *buf = ctrl->buffer;
|
BYTE *buf = ctrl->buffer;
|
||||||
|
|
||||||
memset(buf, 0, 8);
|
|
||||||
|
|
||||||
if (!CheckReady()) {
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disk.blocks <= 0) {
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
|
||||||
|
|
||||||
LOGWARN("%s Capacity not available, medium may not be present", __PRETTY_FUNCTION__);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create end of logical block address (disk.blocks-1)
|
// Create end of logical block address (disk.blocks-1)
|
||||||
uint32_t blocks = disk.blocks - 1;
|
uint32_t blocks = disk.blocks - 1;
|
||||||
buf[0] = (BYTE)(blocks >> 24);
|
buf[0] = (BYTE)(blocks >> 24);
|
||||||
@ -1128,15 +916,13 @@ void Disk::ReadCapacity10(SASIDEV *controller)
|
|||||||
|
|
||||||
void Disk::ReadCapacity16(SASIDEV *controller)
|
void Disk::ReadCapacity16(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
BYTE *buf = ctrl->buffer;
|
|
||||||
|
|
||||||
memset(buf, 0, 14);
|
|
||||||
|
|
||||||
if (!CheckReady() || disk.blocks <= 0) {
|
if (!CheckReady() || disk.blocks <= 0) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BYTE *buf = ctrl->buffer;
|
||||||
|
|
||||||
// Create end of logical block address (disk.blocks-1)
|
// Create end of logical block address (disk.blocks-1)
|
||||||
uint64_t blocks = disk.blocks - 1;
|
uint64_t blocks = disk.blocks - 1;
|
||||||
buf[0] = (BYTE)(blocks >> 56);
|
buf[0] = (BYTE)(blocks >> 56);
|
||||||
@ -1155,6 +941,8 @@ void Disk::ReadCapacity16(SASIDEV *controller)
|
|||||||
buf[10] = (BYTE)(length >> 8);
|
buf[10] = (BYTE)(length >> 8);
|
||||||
buf[11] = (BYTE)length;
|
buf[11] = (BYTE)length;
|
||||||
|
|
||||||
|
buf[12] = 0;
|
||||||
|
|
||||||
// Logical blocks per physical block: not reported (1 or more)
|
// Logical blocks per physical block: not reported (1 or more)
|
||||||
buf[13] = 0;
|
buf[13] = 0;
|
||||||
|
|
||||||
@ -1184,7 +972,7 @@ void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller)
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// RESERVE(6)
|
// RESERVE/RELEASE(6/10)
|
||||||
//
|
//
|
||||||
// The reserve/release commands are only used in multi-initiator
|
// The reserve/release commands are only used in multi-initiator
|
||||||
// environments. RaSCSI doesn't support this use case. However, some old
|
// environments. RaSCSI doesn't support this use case. However, some old
|
||||||
@ -1192,52 +980,12 @@ void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller)
|
|||||||
// just respond with an OK status.
|
// just respond with an OK status.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void Disk::Reserve6(SASIDEV *controller)
|
void Disk::Reserve(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
void Disk::Release(SASIDEV *controller)
|
||||||
//
|
|
||||||
// RESERVE(10)
|
|
||||||
//
|
|
||||||
// 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 Disk::Reserve10(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
controller->Status();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// RELEASE(6)
|
|
||||||
//
|
|
||||||
// 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 Disk::Release6(SASIDEV *controller)
|
|
||||||
{
|
|
||||||
controller->Status();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// RELEASE(10)
|
|
||||||
//
|
|
||||||
// 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 Disk::Release10(SASIDEV *controller)
|
|
||||||
{
|
{
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
@ -1330,6 +1078,8 @@ bool Disk::GetStartAndCount(SASIDEV *controller, uint64_t& start, uint32_t& coun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGDEBUG("%s READ/WRITE/VERIFY command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, count);
|
||||||
|
|
||||||
// Check capacity
|
// Check capacity
|
||||||
uint64_t capacity = GetBlockCount();
|
uint64_t capacity = GetBlockCount();
|
||||||
if (start > capacity || start + count > capacity) {
|
if (start > capacity || start + count > capacity) {
|
||||||
|
@ -96,10 +96,8 @@ private:
|
|||||||
void Seek10(SASIDEV *);
|
void Seek10(SASIDEV *);
|
||||||
void ReadCapacity10(SASIDEV *) override;
|
void ReadCapacity10(SASIDEV *) override;
|
||||||
void ReadCapacity16(SASIDEV *) override;
|
void ReadCapacity16(SASIDEV *) override;
|
||||||
void Reserve6(SASIDEV *);
|
void Reserve(SASIDEV *);
|
||||||
void Reserve10(SASIDEV *);
|
void Release(SASIDEV *);
|
||||||
void Release6(SASIDEV *);
|
|
||||||
void Release10(SASIDEV *);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -117,7 +115,7 @@ public:
|
|||||||
bool SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
|
bool SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
|
||||||
|
|
||||||
virtual int Read(const DWORD *cdb, BYTE *buf, uint64_t block);
|
virtual int Read(const DWORD *cdb, BYTE *buf, uint64_t block);
|
||||||
int ReadDefectData10(const DWORD *cdb, BYTE *buf);
|
int ReadDefectData10(const DWORD *, BYTE *, int);
|
||||||
|
|
||||||
uint32_t GetSectorSizeInBytes() const;
|
uint32_t GetSectorSizeInBytes() const;
|
||||||
void SetSectorSizeInBytes(uint32_t, bool);
|
void SetSectorSizeInBytes(uint32_t, bool);
|
||||||
@ -138,15 +136,14 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
||||||
int ModeSense10(const DWORD *cdb, BYTE *buf);
|
int ModeSense10(const DWORD *cdb, BYTE *buf, int);
|
||||||
virtual int AddErrorPage(bool change, BYTE *buf);
|
virtual void SetDeviceParameters(BYTE *);
|
||||||
virtual int AddFormatPage(bool change, BYTE *buf);
|
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
virtual int AddDrivePage(bool change, BYTE *buf);
|
virtual void AddErrorPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
virtual int AddVendorPage(int page, bool change, BYTE *buf);
|
virtual void AddFormatPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
int AddOptionPage(bool change, BYTE *buf);
|
virtual void AddDrivePage(map<int, vector<BYTE>>&, bool) const;
|
||||||
int AddCachePage(bool change, BYTE *buf);
|
void AddCachePage(map<int, vector<BYTE>>&, bool) const;
|
||||||
int AddCDROMPage(bool change, BYTE *buf);
|
virtual void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const;
|
||||||
int AddCDDAPage(bool, BYTE *buf);
|
|
||||||
|
|
||||||
// Internal disk data
|
// Internal disk data
|
||||||
disk_t disk;
|
disk_t disk;
|
||||||
|
@ -101,107 +101,92 @@ void HostServices::StartStopUnit(SCSIDEV *controller)
|
|||||||
|
|
||||||
int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf)
|
int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Get length, clear buffer
|
// Block descriptors cannot be returned
|
||||||
|
if (!(cdb[1] & 0x08)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int length = (int)cdb[4];
|
int length = (int)cdb[4];
|
||||||
memset(buf, 0, length);
|
memset(buf, 0, length);
|
||||||
|
|
||||||
// Get page code (0x00 is valid from the beginning)
|
|
||||||
int page = cdb[2] & 0x3f;
|
|
||||||
bool valid = page == 0x00;
|
|
||||||
|
|
||||||
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
|
|
||||||
// Basic information
|
// Basic information
|
||||||
int size = 4;
|
int size = 4;
|
||||||
|
|
||||||
int ret = AddRealtimeClockPage(page, &buf[size]);
|
int pages_size = super::AddModePages(cdb, &buf[size], length - size);
|
||||||
if (ret > 0) {
|
if (!pages_size) {
|
||||||
size += ret;
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
size += pages_size;
|
||||||
|
|
||||||
// Do not return more than ALLOCATION LENGTH bytes
|
// Do not return more than ALLOCATION LENGTH bytes
|
||||||
if (size > length) {
|
if (size > length) {
|
||||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
|
||||||
size = length;
|
size = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final setting of mode data length
|
|
||||||
buf[0] = size;
|
buf[0] = size;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HostServices::ModeSense10(const DWORD *cdb, BYTE *buf)
|
int HostServices::ModeSense10(const DWORD *cdb, BYTE *buf, int max_length)
|
||||||
{
|
{
|
||||||
// Get length, clear buffer
|
// Block descriptors cannot be returned
|
||||||
int length = cdb[7];
|
if (!(cdb[1] & 0x08)) {
|
||||||
length <<= 8;
|
|
||||||
length |= cdb[8];
|
|
||||||
if (length > 0x800) {
|
|
||||||
length = 0x800;
|
|
||||||
}
|
|
||||||
memset(buf, 0, length);
|
|
||||||
|
|
||||||
// Get page code (0x00 is valid from the beginning)
|
|
||||||
int page = cdb[2] & 0x3f;
|
|
||||||
bool valid = page == 0x00;
|
|
||||||
|
|
||||||
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
|
|
||||||
// Basic Information
|
|
||||||
int size = 8;
|
|
||||||
|
|
||||||
int ret = AddRealtimeClockPage(page, &buf[size]);
|
|
||||||
if (ret > 0) {
|
|
||||||
size += ret;
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
|
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int length = (cdb[7] << 8) | cdb[8];
|
||||||
|
if (length > max_length) {
|
||||||
|
length = max_length;
|
||||||
|
}
|
||||||
|
memset(buf, 0, length);
|
||||||
|
|
||||||
|
// Basic information
|
||||||
|
int size = 8;
|
||||||
|
|
||||||
|
int pages_size = super::AddModePages(cdb, &buf[size], length - size);
|
||||||
|
if (!pages_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size += pages_size;
|
||||||
|
|
||||||
// Do not return more than ALLOCATION LENGTH bytes
|
// Do not return more than ALLOCATION LENGTH bytes
|
||||||
if (size > length) {
|
if (size > length) {
|
||||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
|
||||||
size = length;
|
size = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final setting of mode data length
|
|
||||||
buf[0] = size >> 8;
|
buf[0] = size >> 8;
|
||||||
buf[1] = size;
|
buf[1] = size;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HostServices::AddRealtimeClockPage(int page, BYTE *buf)
|
void HostServices::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
{
|
{
|
||||||
if (page == 0x20) {
|
if (page == 0x20 || page == 0x3f) {
|
||||||
|
AddRealtimeClockPage(pages, changeable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostServices::AddRealtimeClockPage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(10);
|
||||||
|
|
||||||
|
if (!changeable) {
|
||||||
// Data structure version 1.0
|
// Data structure version 1.0
|
||||||
buf[0] = 0x01;
|
buf[2] = 0x01;
|
||||||
buf[1] = 0x00;
|
buf[3] = 0x00;
|
||||||
|
|
||||||
std::time_t t = std::time(NULL);
|
std::time_t t = std::time(NULL);
|
||||||
std::tm tm = *std::localtime(&t);
|
std::tm tm = *std::localtime(&t);
|
||||||
buf[2] = tm.tm_year;
|
buf[4] = tm.tm_year;
|
||||||
buf[3] = tm.tm_mon;
|
buf[5] = tm.tm_mon;
|
||||||
buf[4] = tm.tm_mday;
|
buf[6] = tm.tm_mday;
|
||||||
buf[5] = tm.tm_hour;
|
buf[7] = tm.tm_hour;
|
||||||
buf[6] = tm.tm_min;
|
buf[8] = tm.tm_min;
|
||||||
// Ignore leap second for simplicity
|
// Ignore leap second for simplicity
|
||||||
buf[7] = tm.tm_sec < 60 ? tm.tm_sec : 59;
|
buf[9] = tm.tm_sec < 60 ? tm.tm_sec : 59;
|
||||||
|
|
||||||
return 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
pages[32] = buf;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "mode_page_device.h"
|
#include "mode_page_device.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ public:
|
|||||||
void StartStopUnit(SCSIDEV *);
|
void StartStopUnit(SCSIDEV *);
|
||||||
|
|
||||||
int ModeSense6(const DWORD *, BYTE *);
|
int ModeSense6(const DWORD *, BYTE *);
|
||||||
int ModeSense10(const DWORD *, BYTE *);
|
int ModeSense10(const DWORD *, BYTE *, int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -37,5 +38,6 @@ private:
|
|||||||
|
|
||||||
Dispatcher<HostServices, SCSIDEV> dispatcher;
|
Dispatcher<HostServices, SCSIDEV> dispatcher;
|
||||||
|
|
||||||
int AddRealtimeClockPage(int, BYTE *);
|
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
|
void AddRealtimeClockPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,66 @@ bool ModePageDevice::Dispatch(SCSIDEV *controller)
|
|||||||
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ModePageDevice::AddModePages(const DWORD *cdb, BYTE *buf, int max_length)
|
||||||
|
{
|
||||||
|
bool changeable = (cdb[2] & 0xc0) == 0x40;
|
||||||
|
|
||||||
|
// Get page code (0x3f means all pages)
|
||||||
|
int page = cdb[2] & 0x3f;
|
||||||
|
|
||||||
|
LOGTRACE("%s Requesting mode page $%02X", __PRETTY_FUNCTION__, page);
|
||||||
|
|
||||||
|
// Mode page data mapped to the respective page numbers, C++ maps are ordered by key
|
||||||
|
map<int, vector<BYTE>> pages;
|
||||||
|
AddModePages(pages, page, changeable);
|
||||||
|
|
||||||
|
// If no mode data were added at all something must be wrong
|
||||||
|
if (pages.empty()) {
|
||||||
|
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, page);
|
||||||
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
vector<BYTE> page0;
|
||||||
|
for (auto const& page : pages) {
|
||||||
|
if (size + (int)page.second.size() > max_length) {
|
||||||
|
LOGWARN("Mode page data size exceeds reserved buffer size");
|
||||||
|
|
||||||
|
page0.clear();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The specification mandates that page 0 must be returned after all others
|
||||||
|
if (page.first) {
|
||||||
|
// Page data
|
||||||
|
memcpy(&buf[size], page.second.data(), page.second.size());
|
||||||
|
// Page code, PS bit may already have been set
|
||||||
|
buf[size] |= page.first;
|
||||||
|
// Page payload size
|
||||||
|
buf[size + 1] = page.second.size() - 2;
|
||||||
|
|
||||||
|
size += page.second.size();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
page0 = page.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page 0 must be last
|
||||||
|
if (!page0.empty()) {
|
||||||
|
memcpy(&buf[size], page0.data(), page0.size());
|
||||||
|
// Page payload size
|
||||||
|
buf[size + 1] = page0.size() - 2;
|
||||||
|
size += page0.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void ModePageDevice::ModeSense6(SASIDEV *controller)
|
void ModePageDevice::ModeSense6(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
|
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
|
||||||
@ -43,7 +103,7 @@ void ModePageDevice::ModeSense6(SASIDEV *controller)
|
|||||||
|
|
||||||
void ModePageDevice::ModeSense10(SASIDEV *controller)
|
void ModePageDevice::ModeSense10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer);
|
ctrl->length = ModeSense10(ctrl->cmd, ctrl->buffer, ctrl->bufsize);
|
||||||
if (ctrl->length <= 0) {
|
if (ctrl->length <= 0) {
|
||||||
controller->Error();
|
controller->Error();
|
||||||
return;
|
return;
|
||||||
@ -52,12 +112,9 @@ void ModePageDevice::ModeSense10(SASIDEV *controller)
|
|||||||
controller->DataIn();
|
controller->DataIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModePageDevice::ModeSelect(const DWORD* /*cdb*/, const BYTE *buf, int length)
|
bool ModePageDevice::ModeSelect(const DWORD*, const BYTE *, int)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
// Cannot be set
|
||||||
ASSERT(length >= 0);
|
|
||||||
|
|
||||||
// cannot be set
|
|
||||||
SetStatusCode(STATUS_INVALIDPRM);
|
SetStatusCode(STATUS_INVALIDPRM);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -67,7 +124,7 @@ void ModePageDevice::ModeSelect6(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||||
|
|
||||||
ctrl->length = ModeSelectCheck6(ctrl->cmd);
|
ctrl->length = ModeSelectCheck6();
|
||||||
if (ctrl->length <= 0) {
|
if (ctrl->length <= 0) {
|
||||||
controller->Error();
|
controller->Error();
|
||||||
return;
|
return;
|
||||||
@ -80,7 +137,7 @@ void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||||
|
|
||||||
ctrl->length = ModeSelectCheck10(ctrl->cmd);
|
ctrl->length = ModeSelectCheck10();
|
||||||
if (ctrl->length <= 0) {
|
if (ctrl->length <= 0) {
|
||||||
controller->Error();
|
controller->Error();
|
||||||
return;
|
return;
|
||||||
@ -89,11 +146,11 @@ void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
|||||||
controller->DataOut();
|
controller->DataOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
int ModePageDevice::ModeSelectCheck(int length)
|
||||||
{
|
{
|
||||||
// Error if save parameters are set for other types than of SCHD or SCRM
|
// Error if save parameters are set for other types than of SCHD or SCRM
|
||||||
// TODO This assumption is not correct, and this code should be located elsewhere
|
// TODO The assumption above is not correct, and this code should be located elsewhere
|
||||||
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
if (!IsSCSIHD() && (ctrl->cmd[1] & 0x01)) {
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -101,21 +158,21 @@ int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ModePageDevice::ModeSelectCheck6(const DWORD *cdb)
|
int ModePageDevice::ModeSelectCheck6()
|
||||||
{
|
{
|
||||||
// Receive the data specified by the parameter length
|
// Receive the data specified by the parameter length
|
||||||
return ModeSelectCheck(cdb, cdb[4]);
|
return ModeSelectCheck(ctrl->cmd[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ModePageDevice::ModeSelectCheck10(const DWORD *cdb)
|
int ModePageDevice::ModeSelectCheck10()
|
||||||
{
|
{
|
||||||
// Receive the data specified by the parameter length
|
// Receive the data specified by the parameter length
|
||||||
int length = cdb[7];
|
int length = ctrl->cmd[7];
|
||||||
length <<= 8;
|
length <<= 8;
|
||||||
length |= cdb[8];
|
length |= ctrl->cmd[8];
|
||||||
if (length > 0x800) {
|
if (length > ctrl->bufsize) {
|
||||||
length = 0x800;
|
length = ctrl->bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ModeSelectCheck(cdb, length);
|
return ModeSelectCheck(length);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "primary_device.h"
|
#include "primary_device.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -24,11 +26,16 @@ public:
|
|||||||
virtual bool Dispatch(SCSIDEV *) override;
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
virtual int ModeSense6(const DWORD *, BYTE *) = 0;
|
virtual int ModeSense6(const DWORD *, BYTE *) = 0;
|
||||||
virtual int ModeSense10(const DWORD *, BYTE *) = 0;
|
virtual int ModeSense10(const DWORD *, BYTE *, int) = 0;
|
||||||
|
|
||||||
// TODO This method should not be called by SASIDEV
|
// TODO This method should not be called by SASIDEV
|
||||||
virtual bool ModeSelect(const DWORD *, const BYTE *, int);
|
virtual bool ModeSelect(const DWORD *, const BYTE *, int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int AddModePages(const DWORD *, BYTE *, int);
|
||||||
|
virtual void AddModePages(map<int, vector<BYTE>>&, int, bool) const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef PrimaryDevice super;
|
typedef PrimaryDevice super;
|
||||||
@ -40,7 +47,7 @@ private:
|
|||||||
void ModeSelect6(SASIDEV *);
|
void ModeSelect6(SASIDEV *);
|
||||||
void ModeSelect10(SASIDEV *);
|
void ModeSelect10(SASIDEV *);
|
||||||
|
|
||||||
int ModeSelectCheck(const DWORD *, int);
|
int ModeSelectCheck(int);
|
||||||
int ModeSelectCheck6(const DWORD *);
|
int ModeSelectCheck6();
|
||||||
int ModeSelectCheck10(const DWORD *);
|
int ModeSelectCheck10();
|
||||||
};
|
};
|
||||||
|
@ -68,11 +68,6 @@ void PrimaryDevice::ReportLuns(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
BYTE *buf = ctrl->buffer;
|
BYTE *buf = ctrl->buffer;
|
||||||
|
|
||||||
if (!CheckReady()) {
|
|
||||||
controller->Error();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
||||||
memset(buf, 0, allocation_length);
|
memset(buf, 0, allocation_length);
|
||||||
|
|
||||||
@ -111,7 +106,7 @@ void PrimaryDevice::RequestSense(SASIDEV *controller)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctrl->length = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(ctrl->cmd, ctrl->buffer);
|
ctrl->length = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(ctrl->cmd, ctrl->buffer);
|
||||||
ASSERT(ctrl->length > 0);
|
assert(ctrl->length > 0);
|
||||||
|
|
||||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
||||||
|
|
||||||
@ -124,7 +119,7 @@ bool PrimaryDevice::CheckReady()
|
|||||||
if (IsReset()) {
|
if (IsReset()) {
|
||||||
SetStatusCode(STATUS_DEVRESET);
|
SetStatusCode(STATUS_DEVRESET);
|
||||||
SetReset(false);
|
SetReset(false);
|
||||||
LOGTRACE("%s Disk in reset", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Device in reset", __PRETTY_FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,26 +127,32 @@ bool PrimaryDevice::CheckReady()
|
|||||||
if (IsAttn()) {
|
if (IsAttn()) {
|
||||||
SetStatusCode(STATUS_ATTENTION);
|
SetStatusCode(STATUS_ATTENTION);
|
||||||
SetAttn(false);
|
SetAttn(false);
|
||||||
LOGTRACE("%s Disk in needs attention", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Device in needs attention", __PRETTY_FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return status if not ready
|
// Return status if not ready
|
||||||
if (!IsReady()) {
|
if (!IsReady()) {
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
SetStatusCode(STATUS_NOTREADY);
|
||||||
LOGTRACE("%s Disk not ready", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Device not ready", __PRETTY_FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization with no error
|
// Initialization with no error
|
||||||
LOGTRACE("%s Disk is ready", __PRETTY_FUNCTION__);
|
LOGTRACE("%s Device is ready", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DWORD *cdb, BYTE *buf)
|
int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
int allocation_length = cdb[4] + (((DWORD)cdb[3]) << 8);
|
// EVPD and page code check
|
||||||
|
if ((cdb[1] & 0x01) || cdb[2]) {
|
||||||
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int allocation_length = cdb[4] + (cdb[3] << 8);
|
||||||
if (allocation_length > 4) {
|
if (allocation_length > 4) {
|
||||||
if (allocation_length > 44) {
|
if (allocation_length > 44) {
|
||||||
allocation_length = 44;
|
allocation_length = 44;
|
||||||
@ -167,6 +168,8 @@ int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DW
|
|||||||
buf[0] = type;
|
buf[0] = type;
|
||||||
buf[1] = is_removable ? 0x80 : 0x00;
|
buf[1] = is_removable ? 0x80 : 0x00;
|
||||||
buf[2] = scsi_level;
|
buf[2] = scsi_level;
|
||||||
|
// Response data format is SCSI-2 for devices supporting SCSI-2 or newer, otherwise it is SCSI-1-CCS
|
||||||
|
buf[3] = scsi_level >= 2 ? 2 : 0;
|
||||||
buf[4] = 0x1F;
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
@ -178,22 +181,16 @@ int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DW
|
|||||||
|
|
||||||
int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf)
|
int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Return not ready only if there are no errors
|
// Return not ready only if there are no errors
|
||||||
if (GetStatusCode() == STATUS_NOERROR) {
|
if (GetStatusCode() == STATUS_NOERROR && !IsReady()) {
|
||||||
if (!IsReady()) {
|
SetStatusCode(STATUS_NOTREADY);
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size determination (according to allocation length)
|
// Size determination (according to allocation length)
|
||||||
int size = (int)cdb[4];
|
int size = (int)cdb[4];
|
||||||
ASSERT((size >= 0) && (size < 0x100));
|
assert(size >= 0 && size < 0x100);
|
||||||
|
|
||||||
// For SCSI-1, transfer 4 bytes when the size is 0
|
// For SCSI-1, transfer 4 bytes when the size is 0
|
||||||
// (Deleted this specification for SCSI-2)
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
size = 4;
|
size = 4;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
virtual int Inquiry(const DWORD *, BYTE *) = 0;
|
virtual int Inquiry(const DWORD *, BYTE *) = 0;
|
||||||
virtual int RequestSense(const DWORD *, BYTE *);
|
virtual int RequestSense(const DWORD *, BYTE *);
|
||||||
virtual bool WriteBytes(BYTE *, uint32_t);
|
virtual bool WriteBytes(BYTE *, uint32_t);
|
||||||
|
virtual int GetSendDelay() { return BUS::SEND_NO_DELAY; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -19,26 +19,11 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
//===========================================================================
|
SASIHD::SASIHD(const set<uint32_t>& sector_sizes) : Disk("SAHD")
|
||||||
//
|
|
||||||
// SASI Hard Disk
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Constructor
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
SASIHD::SASIHD() : Disk("SAHD")
|
|
||||||
{
|
{
|
||||||
|
SetSectorSizes(sector_sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Reset
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SASIHD::Reset()
|
void SASIHD::Reset()
|
||||||
{
|
{
|
||||||
// Unlock, clear attention
|
// Unlock, clear attention
|
||||||
@ -50,14 +35,9 @@ void SASIHD::Reset()
|
|||||||
SetStatusCode(STATUS_NOERROR);
|
SetStatusCode(STATUS_NOERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Open
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SASIHD::Open(const Filepath& path)
|
void SASIHD::Open(const Filepath& path)
|
||||||
{
|
{
|
||||||
ASSERT(!IsReady());
|
assert(!IsReady());
|
||||||
|
|
||||||
// Open as read-only
|
// Open as read-only
|
||||||
Fileio fio;
|
Fileio fio;
|
||||||
@ -101,30 +81,17 @@ void SASIHD::Open(const Filepath& path)
|
|||||||
FileSupport::SetPath(path);
|
FileSupport::SetPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// INQUIRY
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SASIHD::Inquiry(const DWORD* /*cdb*/, BYTE* /*buf*/)
|
int SASIHD::Inquiry(const DWORD* /*cdb*/, BYTE* /*buf*/)
|
||||||
{
|
{
|
||||||
SetStatusCode(STATUS_INVALIDCMD);
|
SetStatusCode(STATUS_INVALIDCMD);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// REQUEST SENSE
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SASIHD::RequestSense(const DWORD *cdb, BYTE *buf)
|
int SASIHD::RequestSense(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Size decision
|
// Size decision
|
||||||
int size = (int)cdb[4];
|
int size = (int)cdb[4];
|
||||||
ASSERT(size >= 0 && size < 0x100);
|
assert(size >= 0 && size < 0x100);
|
||||||
|
|
||||||
// Transfer 4 bytes when size 0 (Shugart Associates System Interface specification)
|
// Transfer 4 bytes when size 0 (Shugart Associates System Interface specification)
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
class SASIHD : public Disk, public FileSupport
|
class SASIHD : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SASIHD();
|
SASIHD(const set<uint32_t>&);
|
||||||
~SASIHD() {};
|
~SASIHD() {}
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
@ -583,3 +583,11 @@ void SCSIDaynaPort::EnableInterface(SASIDEV *controller)
|
|||||||
|
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SCSIDaynaPort::GetSendDelay()
|
||||||
|
{
|
||||||
|
// The Daynaport needs to have a delay after the size/flags field
|
||||||
|
// of the read response. In the MacOS driver, it looks like the
|
||||||
|
// driver is doing two "READ" system calls.
|
||||||
|
return DAYNAPORT_READ_HEADER_SZ;
|
||||||
|
}
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
void SetInterfaceMode(SASIDEV *);
|
void SetInterfaceMode(SASIDEV *);
|
||||||
void SetMcastAddr(SASIDEV *);
|
void SetMcastAddr(SASIDEV *);
|
||||||
void EnableInterface(SASIDEV *);
|
void EnableInterface(SASIDEV *);
|
||||||
|
int GetSendDelay() override;
|
||||||
|
|
||||||
bool Dispatch(SCSIDEV *) override;
|
bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
buf[0] = 0x09;
|
buf[0] = 0x09;
|
||||||
buf[2] = 0x02;
|
buf[2] = 0x02;
|
||||||
buf[3] = 0x02;
|
buf[3] = 0x02;
|
||||||
buf[4] = 36 - 5 + 8; // required + 8 byte extension
|
buf[4] = 0x1F + 8; // required + 8 byte extension
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
@ -152,13 +152,9 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
void SCSIBR::TestUnitReady(SASIDEV *controller)
|
void SCSIBR::TestUnitReady(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
// Always successful
|
// Always successful
|
||||||
controller->Status();}
|
controller->Status();
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// GET MESSAGE(10)
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
// Type
|
// Type
|
||||||
@ -239,16 +235,8 @@ int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// SEND MESSAGE(10)
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
int type = cdb[2];
|
int type = cdb[2];
|
||||||
|
|
||||||
@ -301,11 +289,6 @@ bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// GET MESSAGE(10)
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIBR::GetMessage10(SASIDEV *controller)
|
void SCSIBR::GetMessage10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
// Reallocate buffer (because it is not transfer for each block)
|
// Reallocate buffer (because it is not transfer for each block)
|
||||||
@ -365,41 +348,22 @@ void SCSIBR::SendMessage10(SASIDEV *controller)
|
|||||||
controller->DataOut();
|
controller->DataOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Get MAC Address
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SCSIBR::GetMacAddr(BYTE *mac)
|
int SCSIBR::GetMacAddr(BYTE *mac)
|
||||||
{
|
{
|
||||||
ASSERT(mac);
|
|
||||||
|
|
||||||
memcpy(mac, mac_addr, 6);
|
memcpy(mac, mac_addr, 6);
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Set MAC Address
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIBR::SetMacAddr(BYTE *mac)
|
void SCSIBR::SetMacAddr(BYTE *mac)
|
||||||
{
|
{
|
||||||
ASSERT(mac);
|
|
||||||
|
|
||||||
memcpy(mac_addr, mac, 6);
|
memcpy(mac_addr, mac, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Receive Packet
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIBR::ReceivePacket()
|
void SCSIBR::ReceivePacket()
|
||||||
{
|
{
|
||||||
static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
ASSERT(tap);
|
assert(tap);
|
||||||
|
|
||||||
// previous packet has not been received
|
// previous packet has not been received
|
||||||
if (packet_enable) {
|
if (packet_enable) {
|
||||||
@ -429,15 +393,9 @@ void SCSIBR::ReceivePacket()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Get Packet
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIBR::GetPacketBuf(BYTE *buf)
|
void SCSIBR::GetPacketBuf(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(tap);
|
assert(tap);
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Size limit
|
// Size limit
|
||||||
int len = packet_len;
|
int len = packet_len;
|
||||||
@ -452,15 +410,9 @@ void SCSIBR::GetPacketBuf(BYTE *buf)
|
|||||||
packet_enable = false;
|
packet_enable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Send Packet
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIBR::SendPacket(BYTE *buf, int len)
|
void SCSIBR::SendPacket(BYTE *buf, int len)
|
||||||
{
|
{
|
||||||
ASSERT(tap);
|
assert(tap);
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
tap->Tx(buf, len);
|
tap->Tx(buf, len);
|
||||||
}
|
}
|
||||||
@ -472,9 +424,6 @@ void SCSIBR::SendPacket(BYTE *buf, int len)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_InitDevice(BYTE *buf)
|
void SCSIBR::FS_InitDevice(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
fs->Reset();
|
fs->Reset();
|
||||||
fsresult = fs->InitDevice((Human68k::argument_t*)buf);
|
fsresult = fs->InitDevice((Human68k::argument_t*)buf);
|
||||||
}
|
}
|
||||||
@ -486,13 +435,9 @@ void SCSIBR::FS_InitDevice(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_CheckDir(BYTE *buf)
|
void SCSIBR::FS_CheckDir(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -507,13 +452,9 @@ void SCSIBR::FS_CheckDir(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_MakeDir(BYTE *buf)
|
void SCSIBR::FS_MakeDir(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -528,13 +469,9 @@ void SCSIBR::FS_MakeDir(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_RemoveDir(BYTE *buf)
|
void SCSIBR::FS_RemoveDir(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -549,13 +486,9 @@ void SCSIBR::FS_RemoveDir(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Rename(BYTE *buf)
|
void SCSIBR::FS_Rename(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -573,13 +506,9 @@ void SCSIBR::FS_Rename(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Delete(BYTE *buf)
|
void SCSIBR::FS_Delete(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -594,13 +523,9 @@ void SCSIBR::FS_Delete(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Attribute(BYTE *buf)
|
void SCSIBR::FS_Attribute(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||||
i += sizeof(Human68k::namests_t);
|
i += sizeof(Human68k::namests_t);
|
||||||
@ -619,13 +544,9 @@ void SCSIBR::FS_Attribute(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Files(BYTE *buf)
|
void SCSIBR::FS_Files(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -665,13 +586,9 @@ void SCSIBR::FS_Files(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_NFiles(BYTE *buf)
|
void SCSIBR::FS_NFiles(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -708,13 +625,9 @@ void SCSIBR::FS_NFiles(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Create(BYTE *buf)
|
void SCSIBR::FS_Create(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -762,13 +675,9 @@ void SCSIBR::FS_Create(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Open(BYTE *buf)
|
void SCSIBR::FS_Open(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -808,13 +717,9 @@ void SCSIBR::FS_Open(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Close(BYTE *buf)
|
void SCSIBR::FS_Close(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -851,13 +756,9 @@ void SCSIBR::FS_Close(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Read(BYTE *buf)
|
void SCSIBR::FS_Read(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||||
i += sizeof(Human68k::fcb_t);
|
i += sizeof(Human68k::fcb_t);
|
||||||
@ -896,13 +797,9 @@ void SCSIBR::FS_Read(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Write(BYTE *buf)
|
void SCSIBR::FS_Write(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||||
i += sizeof(Human68k::fcb_t);
|
i += sizeof(Human68k::fcb_t);
|
||||||
@ -939,13 +836,9 @@ void SCSIBR::FS_Write(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Seek(BYTE *buf)
|
void SCSIBR::FS_Seek(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||||
i += sizeof(Human68k::fcb_t);
|
i += sizeof(Human68k::fcb_t);
|
||||||
@ -986,13 +879,9 @@ void SCSIBR::FS_Seek(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_TimeStamp(BYTE *buf)
|
void SCSIBR::FS_TimeStamp(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nKey = ntohl(*dp);
|
DWORD nKey = ntohl(*dp);
|
||||||
@ -1033,9 +922,6 @@ void SCSIBR::FS_TimeStamp(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_GetCapacity(BYTE *buf)
|
void SCSIBR::FS_GetCapacity(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1058,13 +944,9 @@ void SCSIBR::FS_GetCapacity(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_CtrlDrive(BYTE *buf)
|
void SCSIBR::FS_CtrlDrive(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
Human68k::ctrldrive_t *pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i];
|
Human68k::ctrldrive_t *pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i];
|
||||||
|
|
||||||
@ -1081,9 +963,6 @@ void SCSIBR::FS_CtrlDrive(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_GetDPB(BYTE *buf)
|
void SCSIBR::FS_GetDPB(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1108,13 +987,9 @@ void SCSIBR::FS_GetDPB(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_DiskRead(BYTE *buf)
|
void SCSIBR::FS_DiskRead(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nSector = ntohl(*dp);
|
DWORD nSector = ntohl(*dp);
|
||||||
@ -1135,9 +1010,6 @@ void SCSIBR::FS_DiskRead(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_DiskWrite(BYTE *buf)
|
void SCSIBR::FS_DiskWrite(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1151,13 +1023,9 @@ void SCSIBR::FS_DiskWrite(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Ioctrl(BYTE *buf)
|
void SCSIBR::FS_Ioctrl(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
i += sizeof(DWORD);
|
int i = sizeof(DWORD);
|
||||||
|
|
||||||
dp = (DWORD*)&buf[i];
|
dp = (DWORD*)&buf[i];
|
||||||
DWORD nFunction = ntohl(*dp);
|
DWORD nFunction = ntohl(*dp);
|
||||||
@ -1198,9 +1066,6 @@ void SCSIBR::FS_Ioctrl(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Flush(BYTE *buf)
|
void SCSIBR::FS_Flush(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1214,9 +1079,6 @@ void SCSIBR::FS_Flush(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_CheckMedia(BYTE *buf)
|
void SCSIBR::FS_CheckMedia(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1230,9 +1092,6 @@ void SCSIBR::FS_CheckMedia(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::FS_Lock(BYTE *buf)
|
void SCSIBR::FS_Lock(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(fs);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
DWORD nUnit = ntohl(*dp);
|
DWORD nUnit = ntohl(*dp);
|
||||||
|
|
||||||
@ -1246,8 +1105,6 @@ void SCSIBR::FS_Lock(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int SCSIBR::ReadFsResult(BYTE *buf)
|
int SCSIBR::ReadFsResult(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
DWORD *dp = (DWORD*)buf;
|
DWORD *dp = (DWORD*)buf;
|
||||||
*dp = htonl(fsresult);
|
*dp = htonl(fsresult);
|
||||||
return sizeof(DWORD);
|
return sizeof(DWORD);
|
||||||
@ -1260,8 +1117,6 @@ int SCSIBR::ReadFsResult(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int SCSIBR::ReadFsOut(BYTE *buf)
|
int SCSIBR::ReadFsOut(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
memcpy(buf, fsout, fsoutlen);
|
memcpy(buf, fsout, fsoutlen);
|
||||||
return fsoutlen;
|
return fsoutlen;
|
||||||
}
|
}
|
||||||
@ -1273,8 +1128,6 @@ int SCSIBR::ReadFsOut(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int SCSIBR::ReadFsOpt(BYTE *buf)
|
int SCSIBR::ReadFsOpt(BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
memcpy(buf, fsopt, fsoptlen);
|
memcpy(buf, fsopt, fsoptlen);
|
||||||
return fsoptlen;
|
return fsoptlen;
|
||||||
}
|
}
|
||||||
@ -1286,8 +1139,6 @@ int SCSIBR::ReadFsOpt(BYTE *buf)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIBR::WriteFs(int func, BYTE *buf)
|
void SCSIBR::WriteFs(int func, BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
fsresult = FS_FATAL_INVALIDCOMMAND;
|
fsresult = FS_FATAL_INVALIDCOMMAND;
|
||||||
fsoutlen = 0;
|
fsoutlen = 0;
|
||||||
fsoptlen = 0;
|
fsoptlen = 0;
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
// 2. The client sends the data to be printed with one or several PRINT commands. Due to
|
// 2. The client sends the data to be printed with one or several PRINT commands. Due to
|
||||||
// https://github.com/akuker/RASCSI/issues/669 the maximum transfer size per PRINT command is
|
// https://github.com/akuker/RASCSI/issues/669 the maximum transfer size per PRINT command is
|
||||||
// limited to 4096 bytes.
|
// limited to 4096 bytes.
|
||||||
// 3. The client triggers printing with SYNCHRONIZE BUFFER.
|
// 3. The client triggers printing with SYNCHRONIZE BUFFER. Each SYNCHRONIZE BUFFER results in
|
||||||
|
// the print command for this printer (see below) to be called for the data not yet printed.
|
||||||
// 4. The client releases the printer with RELEASE UNIT (optional step, mandatory for a
|
// 4. The client releases the printer with RELEASE UNIT (optional step, mandatory for a
|
||||||
// multi-initiator environment).
|
// multi-initiator environment).
|
||||||
//
|
//
|
||||||
@ -68,7 +69,7 @@ SCSIPrinter::SCSIPrinter() : PrimaryDevice("SCLP"), ScsiPrinterCommands()
|
|||||||
|
|
||||||
SCSIPrinter::~SCSIPrinter()
|
SCSIPrinter::~SCSIPrinter()
|
||||||
{
|
{
|
||||||
DiscardReservation();
|
Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIPrinter::Init(const map<string, string>& params)
|
bool SCSIPrinter::Init(const map<string, string>& params)
|
||||||
@ -168,7 +169,7 @@ void SCSIPrinter::Print(SCSIDEV *controller)
|
|||||||
|
|
||||||
// TODO This device suffers from the statically allocated buffer size,
|
// TODO This device suffers from the statically allocated buffer size,
|
||||||
// see https://github.com/akuker/RASCSI/issues/669
|
// see https://github.com/akuker/RASCSI/issues/669
|
||||||
if (length > (uint32_t)controller->DEFAULT_BUFFER_SIZE) {
|
if (length > (uint32_t)ctrl->bufsize) {
|
||||||
LOGERROR("Transfer buffer overflow");
|
LOGERROR("Transfer buffer overflow");
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
||||||
|
@ -176,8 +176,10 @@ bool CDTrack::IsAudio() const
|
|||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
SCSICD::SCSICD() : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
|
SCSICD::SCSICD(const set<uint32_t>& sector_sizes) : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
|
||||||
{
|
{
|
||||||
|
SetSectorSizes(sector_sizes);
|
||||||
|
|
||||||
// NOT in raw format
|
// NOT in raw format
|
||||||
rawfile = false;
|
rawfile = false;
|
||||||
|
|
||||||
@ -262,7 +264,7 @@ void SCSICD::Open(const Filepath& path)
|
|||||||
// Successful opening
|
// Successful opening
|
||||||
ASSERT(GetBlockCount() > 0);
|
ASSERT(GetBlockCount() > 0);
|
||||||
|
|
||||||
Disk::Open(path);
|
super::Open(path);
|
||||||
FileSupport::SetPath(path);
|
FileSupport::SetPath(path);
|
||||||
|
|
||||||
// Set RAW flag
|
// Set RAW flag
|
||||||
@ -414,7 +416,7 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
buf[1] = 0x80;
|
buf[1] = 0x80;
|
||||||
buf[2] = 0x02;
|
buf[2] = 0x02;
|
||||||
buf[3] = 0x02;
|
buf[3] = 0x02;
|
||||||
buf[4] = 36 - 5; // Required
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Fill with blanks
|
// Fill with blanks
|
||||||
memset(&buf[8], 0x20, buf[4] - 3);
|
memset(&buf[8], 0x20, buf[4] - 3);
|
||||||
@ -456,6 +458,48 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SCSICD::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
|
{
|
||||||
|
super::AddModePages(pages, page, changeable);
|
||||||
|
|
||||||
|
// Page code 13
|
||||||
|
if (page == 0x0d || page == 0x3f) {
|
||||||
|
AddCDROMPage(pages, changeable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page code 14
|
||||||
|
if (page == 0x0e || page == 0x3f) {
|
||||||
|
AddCDDAPage(pages, changeable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCSICD::AddCDROMPage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(8);
|
||||||
|
|
||||||
|
// No changeable area
|
||||||
|
if (!changeable) {
|
||||||
|
// 2 seconds for inactive timer
|
||||||
|
buf[3] = 0x05;
|
||||||
|
|
||||||
|
// MSF multiples are 60 and 75 respectively
|
||||||
|
buf[5] = 60;
|
||||||
|
buf[7] = 75;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages[13] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCSICD::AddCDDAPage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(16);
|
||||||
|
|
||||||
|
// Audio waits for operation completion and allows
|
||||||
|
// PLAY across multiple tracks
|
||||||
|
|
||||||
|
pages[14] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
ASSERT(buf);
|
||||||
@ -497,7 +541,7 @@ int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
|||||||
|
|
||||||
// Base class
|
// Base class
|
||||||
ASSERT(dataindex >= 0);
|
ASSERT(dataindex >= 0);
|
||||||
return Disk::Read(cdb, buf, block);
|
return super::Read(cdb, buf, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSICD::ReadToc(const DWORD *cdb, BYTE *buf)
|
int SCSICD::ReadToc(const DWORD *cdb, BYTE *buf)
|
||||||
|
@ -76,7 +76,7 @@ public:
|
|||||||
TrackMax = 96 // Maximum number of tracks
|
TrackMax = 96 // Maximum number of tracks
|
||||||
};
|
};
|
||||||
|
|
||||||
SCSICD();
|
SCSICD(const set<uint32_t>&);
|
||||||
~SCSICD();
|
~SCSICD();
|
||||||
|
|
||||||
bool Dispatch(SCSIDEV *) override;
|
bool Dispatch(SCSIDEV *) override;
|
||||||
@ -88,11 +88,18 @@ public:
|
|||||||
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; // READ command
|
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; // READ command
|
||||||
int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
|
int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef Disk super;
|
typedef Disk super;
|
||||||
|
|
||||||
Dispatcher<SCSICD, SASIDEV> dispatcher;
|
Dispatcher<SCSICD, SASIDEV> dispatcher;
|
||||||
|
|
||||||
|
void AddCDROMPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
|
void AddCDDAPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
void OpenCue(const Filepath& path); // Open(CUE)
|
void OpenCue(const Filepath& path); // Open(CUE)
|
||||||
void OpenIso(const Filepath& path); // Open(ISO)
|
void OpenIso(const Filepath& path); // Open(ISO)
|
||||||
|
@ -26,8 +26,9 @@
|
|||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
SCSIHD::SCSIHD(bool removable) : Disk(removable ? "SCRM" : "SCHD")
|
SCSIHD::SCSIHD(const set<uint32_t>& sector_sizes, bool removable) : Disk(removable ? "SCRM" : "SCHD")
|
||||||
{
|
{
|
||||||
|
SetSectorSizes(sector_sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIHD::FinalizeSetup(const Filepath &path, off_t size)
|
void SCSIHD::FinalizeSetup(const Filepath &path, off_t size)
|
||||||
@ -75,7 +76,7 @@ void SCSIHD::Reset()
|
|||||||
|
|
||||||
void SCSIHD::Open(const Filepath& path)
|
void SCSIHD::Open(const Filepath& path)
|
||||||
{
|
{
|
||||||
ASSERT(!IsReady());
|
assert(!IsReady());
|
||||||
|
|
||||||
// Open as read-only
|
// Open as read-only
|
||||||
Fileio fio;
|
Fileio fio;
|
||||||
@ -105,12 +106,6 @@ int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ready check (Error if no image file)
|
|
||||||
if (!IsReady()) {
|
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
// Basic data
|
||||||
// buf[0] ... Direct Access Device
|
// buf[0] ... Direct Access Device
|
||||||
// buf[1] ... Bit 7 set means removable
|
// buf[1] ... Bit 7 set means removable
|
||||||
@ -121,7 +116,7 @@ int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
buf[1] = IsRemovable() ? 0x80 : 0x00;
|
buf[1] = IsRemovable() ? 0x80 : 0x00;
|
||||||
buf[2] = 0x02;
|
buf[2] = 0x02;
|
||||||
buf[3] = 0x02;
|
buf[3] = 0x02;
|
||||||
buf[4] = 28 + 3; // Value close to real HDD
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
@ -139,10 +134,9 @@ int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
|
|
||||||
bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
||||||
{
|
{
|
||||||
int size;
|
assert(length >= 0);
|
||||||
|
|
||||||
ASSERT(buf);
|
int size;
|
||||||
ASSERT(length >= 0);
|
|
||||||
|
|
||||||
// PF
|
// PF
|
||||||
if (cdb[1] & 0x10) {
|
if (cdb[1] & 0x10) {
|
||||||
@ -216,23 +210,19 @@ bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
|||||||
// Add Vendor special page to make drive Apple compatible
|
// Add Vendor special page to make drive Apple compatible
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int SCSIHD::AddVendorPage(int page, bool change, BYTE *buf)
|
void SCSIHD::AddVendorPage(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
// Page code 48
|
||||||
|
|
||||||
// Page code 48 or 63
|
|
||||||
if (page != 0x30 && page != 0x3f) {
|
if (page != 0x30 && page != 0x3f) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the message length
|
vector<BYTE> buf(30);
|
||||||
buf[0] = 0x30;
|
|
||||||
buf[1] = 0x1c;
|
|
||||||
|
|
||||||
// No changeable area
|
// No changeable area
|
||||||
if (!change) {
|
if (!changeable) {
|
||||||
memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20);
|
memcpy(&buf.data()[0xa], "APPLE COMPUTER, INC.", 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 30;
|
pages[48] = buf;
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
class SCSIHD : public Disk, public FileSupport
|
class SCSIHD : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIHD(bool);
|
SCSIHD(const set<uint32_t>&, bool);
|
||||||
virtual ~SCSIHD() {};
|
virtual ~SCSIHD() {}
|
||||||
|
|
||||||
void FinalizeSetup(const Filepath&, off_t);
|
void FinalizeSetup(const Filepath&, off_t);
|
||||||
|
|
||||||
@ -34,6 +34,5 @@ public:
|
|||||||
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||||
|
|
||||||
// Add vendor special page
|
void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
int AddVendorPage(int page, bool change, BYTE *buf) override;
|
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
SCSIHD_NEC::SCSIHD_NEC() : SCSIHD(false)
|
SCSIHD_NEC::SCSIHD_NEC(const set<uint32_t>& sector_sizes) : SCSIHD(sector_sizes, false)
|
||||||
{
|
{
|
||||||
// Work initialization
|
// Work initialization
|
||||||
cylinders = 0;
|
cylinders = 0;
|
||||||
@ -146,31 +146,30 @@ int SCSIHD_NEC::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIHD_NEC::AddErrorPage(bool change, BYTE *buf)
|
void SCSIHD_NEC::AddErrorPage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
vector<BYTE> buf(8);
|
||||||
|
|
||||||
// Set the message length
|
|
||||||
buf[0] = 0x01;
|
|
||||||
buf[1] = 0x06;
|
|
||||||
|
|
||||||
// The retry count is 0, and the limit time uses the default value inside the device.
|
// The retry count is 0, and the limit time uses the default value inside the device.
|
||||||
return 8;
|
|
||||||
|
pages[1] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIHD_NEC::AddFormatPage(bool change, BYTE *buf)
|
void SCSIHD_NEC::AddFormatPage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
vector<BYTE> buf(24);
|
||||||
|
|
||||||
// Set the message length
|
// Page can be saved
|
||||||
buf[0] = 0x80 | 0x03;
|
buf[0] = 0x80;
|
||||||
buf[1] = 0x16;
|
|
||||||
|
|
||||||
// Make the number of bytes in the physical sector appear mutable (although it cannot actually be)
|
// Make the number of bytes in the physical sector appear mutable (although it cannot actually be)
|
||||||
if (change) {
|
if (changeable) {
|
||||||
buf[0xc] = 0xff;
|
buf[0xc] = 0xff;
|
||||||
buf[0xd] = 0xff;
|
buf[0xd] = 0xff;
|
||||||
return 24;
|
|
||||||
|
pages[3] = buf;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsReady()) {
|
if (IsReady()) {
|
||||||
@ -193,19 +192,15 @@ int SCSIHD_NEC::AddFormatPage(bool change, BYTE *buf)
|
|||||||
buf[20] = 0x20;
|
buf[20] = 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 24;
|
pages[3] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIHD_NEC::AddDrivePage(bool change, BYTE *buf)
|
void SCSIHD_NEC::AddDrivePage(map<int, vector<BYTE>>& pages, bool changeable) const
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
vector<BYTE> buf(20);
|
||||||
|
|
||||||
// Set the message length
|
|
||||||
buf[0] = 0x04;
|
|
||||||
buf[1] = 0x12;
|
|
||||||
|
|
||||||
// No changeable area
|
// No changeable area
|
||||||
if (!change && IsReady()) {
|
if (!changeable && IsReady()) {
|
||||||
// Set the number of cylinders
|
// Set the number of cylinders
|
||||||
buf[0x2] = (BYTE)(cylinders >> 16);
|
buf[0x2] = (BYTE)(cylinders >> 16);
|
||||||
buf[0x3] = (BYTE)(cylinders >> 8);
|
buf[0x3] = (BYTE)(cylinders >> 8);
|
||||||
@ -215,5 +210,5 @@ int SCSIHD_NEC::AddDrivePage(bool change, BYTE *buf)
|
|||||||
buf[0x5] = (BYTE)heads;
|
buf[0x5] = (BYTE)heads;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 20;
|
pages[4] = buf;
|
||||||
}
|
}
|
||||||
|
@ -25,17 +25,17 @@
|
|||||||
class SCSIHD_NEC : public SCSIHD
|
class SCSIHD_NEC : public SCSIHD
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIHD_NEC();
|
SCSIHD_NEC(const set<uint32_t>&);
|
||||||
~SCSIHD_NEC() {};
|
~SCSIHD_NEC() {}
|
||||||
|
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||||
|
|
||||||
int AddErrorPage(bool change, BYTE *buf) override;
|
void AddErrorPage(map<int, vector<BYTE>>&, bool) const override;
|
||||||
int AddFormatPage(bool change, BYTE *buf) override;
|
void AddFormatPage(map<int, vector<BYTE>>&, bool) const override;
|
||||||
int AddDrivePage(bool change, BYTE *buf) override;
|
void AddDrivePage(map<int, vector<BYTE>>&, bool) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Geometry data
|
// Geometry data
|
||||||
|
@ -19,29 +19,15 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
//===========================================================================
|
SCSIMO::SCSIMO(const set<uint32_t>& sector_sizes, const map<uint64_t, Geometry>& geometries) : Disk("SCMO")
|
||||||
//
|
|
||||||
// SCSI magneto-optical disk
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Constructor
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
SCSIMO::SCSIMO() : Disk("SCMO")
|
|
||||||
{
|
{
|
||||||
|
SetSectorSizes(sector_sizes);
|
||||||
|
SetGeometries(geometries);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Open
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void SCSIMO::Open(const Filepath& path)
|
void SCSIMO::Open(const Filepath& path)
|
||||||
{
|
{
|
||||||
ASSERT(!IsReady());
|
assert(!IsReady());
|
||||||
|
|
||||||
// Open as read-only
|
// Open as read-only
|
||||||
Fileio fio;
|
Fileio fio;
|
||||||
@ -77,16 +63,8 @@ void SCSIMO::Open(const Filepath& path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// INQUIRY
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||||
{
|
{
|
||||||
ASSERT(cdb);
|
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// EVPD check
|
// EVPD check
|
||||||
if (cdb[1] & 0x01) {
|
if (cdb[1] & 0x01) {
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
SetStatusCode(STATUS_INVALIDCDB);
|
||||||
@ -104,7 +82,7 @@ int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
buf[1] = 0x80;
|
buf[1] = 0x80;
|
||||||
buf[2] = 0x02;
|
buf[2] = 0x02;
|
||||||
buf[3] = 0x02;
|
buf[3] = 0x02;
|
||||||
buf[4] = 36 - 5; // required
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
@ -120,16 +98,36 @@ int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
void SCSIMO::SetDeviceParameters(BYTE *buf)
|
||||||
//
|
{
|
||||||
// MODE SELECT
|
Disk::SetDeviceParameters(buf);
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
// MEDIUM TYPE: Optical reversible or erasable
|
||||||
|
buf[2] = 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCSIMO::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
|
{
|
||||||
|
Disk::AddModePages(pages, page, changeable);
|
||||||
|
|
||||||
|
// Page code 6
|
||||||
|
if (page == 0x06 || page == 0x3f) {
|
||||||
|
AddOptionPage(pages, changeable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCSIMO::AddOptionPage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
|
{
|
||||||
|
vector<BYTE> buf(4);
|
||||||
|
pages[6] = buf;
|
||||||
|
|
||||||
|
// Do not report update blocks
|
||||||
|
}
|
||||||
|
|
||||||
bool SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
bool SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
ASSERT(buf);
|
|
||||||
ASSERT(length >= 0);
|
ASSERT(length >= 0);
|
||||||
|
|
||||||
// PF
|
// PF
|
||||||
@ -191,22 +189,20 @@ bool SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
|||||||
// Vendor Unique Format Page 20h (MO)
|
// Vendor Unique Format Page 20h (MO)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int SCSIMO::AddVendor(int page, BOOL change, BYTE *buf)
|
void SCSIMO::AddVendorPage(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
{
|
{
|
||||||
ASSERT(buf);
|
|
||||||
|
|
||||||
// Page code 20h
|
// Page code 20h
|
||||||
if ((page != 0x20) && (page != 0x3f)) {
|
if (page != 0x20 && page != 0x3f) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the message length
|
vector<BYTE> buf(12);
|
||||||
buf[0] = 0x20;
|
|
||||||
buf[1] = 0x0a;
|
|
||||||
|
|
||||||
// No changeable area
|
// No changeable area
|
||||||
if (change) {
|
if (changeable) {
|
||||||
return 12;
|
pages[32] = buf;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -287,5 +283,7 @@ int SCSIMO::AddVendor(int page, BOOL change, BYTE *buf)
|
|||||||
buf[11] = (BYTE)bands;
|
buf[11] = (BYTE)bands;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 12;
|
pages[32] = buf;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
class SCSIMO : public Disk, public FileSupport
|
class SCSIMO : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIMO();
|
SCSIMO(const set<uint32_t>&, const map<uint64_t, Geometry>&);
|
||||||
~SCSIMO() {};
|
~SCSIMO() {}
|
||||||
|
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
@ -31,6 +31,14 @@ public:
|
|||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
// Internal processing
|
// Internal processing
|
||||||
int AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special page
|
void SetDeviceParameters(BYTE *) override;
|
||||||
|
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
|
void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void AddOptionPage(map<int, vector<BYTE>>&, bool) const;
|
||||||
};
|
};
|
||||||
|
@ -488,7 +488,7 @@ public:
|
|||||||
// Bus signal acquisition
|
// Bus signal acquisition
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
inline DWORD Aquire()
|
inline DWORD Aquire() override
|
||||||
{
|
{
|
||||||
#if defined(__x86_64__) || defined(__X86__)
|
#if defined(__x86_64__) || defined(__X86__)
|
||||||
// Only used for development/debugging purposes. Isn't really applicable
|
// Only used for development/debugging purposes. Isn't really applicable
|
||||||
@ -509,24 +509,24 @@ public:
|
|||||||
void SetENB(BOOL ast);
|
void SetENB(BOOL ast);
|
||||||
// Set ENB signal
|
// Set ENB signal
|
||||||
|
|
||||||
bool GetBSY();
|
bool GetBSY() override;
|
||||||
// Get BSY signal
|
// Get BSY signal
|
||||||
void SetBSY(bool ast);
|
void SetBSY(bool ast) override;
|
||||||
// Set BSY signal
|
// Set BSY signal
|
||||||
|
|
||||||
BOOL GetSEL();
|
BOOL GetSEL() override;
|
||||||
// Get SEL signal
|
// Get SEL signal
|
||||||
void SetSEL(BOOL ast);
|
void SetSEL(BOOL ast) override;
|
||||||
// Set SEL signal
|
// Set SEL signal
|
||||||
|
|
||||||
BOOL GetATN();
|
BOOL GetATN() override;
|
||||||
// Get ATN signal
|
// Get ATN signal
|
||||||
void SetATN(BOOL ast);
|
void SetATN(BOOL ast) override;
|
||||||
// Set ATN signal
|
// Set ATN signal
|
||||||
|
|
||||||
BOOL GetACK();
|
BOOL GetACK() override;
|
||||||
// Get ACK signal
|
// Get ACK signal
|
||||||
void SetACK(BOOL ast);
|
void SetACK(BOOL ast) override;
|
||||||
// Set ACK signal
|
// Set ACK signal
|
||||||
|
|
||||||
BOOL GetACT();
|
BOOL GetACT();
|
||||||
@ -534,42 +534,42 @@ public:
|
|||||||
void SetACT(BOOL ast);
|
void SetACT(BOOL ast);
|
||||||
// Set ACT signal
|
// Set ACT signal
|
||||||
|
|
||||||
BOOL GetRST();
|
BOOL GetRST() override;
|
||||||
// Get RST signal
|
// Get RST signal
|
||||||
void SetRST(BOOL ast);
|
void SetRST(BOOL ast) override;
|
||||||
// Set RST signal
|
// Set RST signal
|
||||||
|
|
||||||
BOOL GetMSG();
|
BOOL GetMSG() override;
|
||||||
// Get MSG signal
|
// Get MSG signal
|
||||||
void SetMSG(BOOL ast);
|
void SetMSG(BOOL ast) override;
|
||||||
// Set MSG signal
|
// Set MSG signal
|
||||||
|
|
||||||
BOOL GetCD();
|
BOOL GetCD() override;
|
||||||
// Get CD signal
|
// Get CD signal
|
||||||
void SetCD(BOOL ast);
|
void SetCD(BOOL ast) override;
|
||||||
// Set CD signal
|
// Set CD signal
|
||||||
|
|
||||||
BOOL GetIO();
|
BOOL GetIO() override;
|
||||||
// Get IO signal
|
// Get IO signal
|
||||||
void SetIO(BOOL ast);
|
void SetIO(BOOL ast) override;
|
||||||
// Set IO signal
|
// Set IO signal
|
||||||
|
|
||||||
BOOL GetREQ();
|
BOOL GetREQ() override;
|
||||||
// Get REQ signal
|
// Get REQ signal
|
||||||
void SetREQ(BOOL ast);
|
void SetREQ(BOOL ast) override;
|
||||||
// Set REQ signal
|
// Set REQ signal
|
||||||
|
|
||||||
BYTE GetDAT();
|
BYTE GetDAT() override;
|
||||||
// Get DAT signal
|
// Get DAT signal
|
||||||
void SetDAT(BYTE dat);
|
void SetDAT(BYTE dat) override;
|
||||||
// Set DAT signal
|
// Set DAT signal
|
||||||
BOOL GetDP();
|
BOOL GetDP() override;
|
||||||
// Get Data parity signal
|
// Get Data parity signal
|
||||||
int CommandHandShake(BYTE *buf);
|
int CommandHandShake(BYTE *buf) override;
|
||||||
// Command receive handshake
|
// Command receive handshake
|
||||||
int ReceiveHandShake(BYTE *buf, int count);
|
int ReceiveHandShake(BYTE *buf, int count) override;
|
||||||
// Data receive handshake
|
// Data receive handshake
|
||||||
int SendHandShake(BYTE *buf, int count, int delay_after_bytes);
|
int SendHandShake(BYTE *buf, int count, int delay_after_bytes) override;
|
||||||
// Data transmission handshake
|
// Data transmission handshake
|
||||||
|
|
||||||
static BUS::phase_t GetPhaseRaw(DWORD raw_data);
|
static BUS::phase_t GetPhaseRaw(DWORD raw_data);
|
||||||
|
@ -772,8 +772,9 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
|||||||
LOGINFO("Insert %sfile '%s' requested into %s ID %d, unit %d", pb_device.protected_() ? "protected " : "",
|
LOGINFO("Insert %sfile '%s' requested into %s ID %d, unit %d", pb_device.protected_() ? "protected " : "",
|
||||||
filename.c_str(), device->GetType().c_str(), pb_device.id(), pb_device.unit());
|
filename.c_str(), device->GetType().c_str(), pb_device.id(), pb_device.unit());
|
||||||
|
|
||||||
|
Disk *disk = dynamic_cast<Disk *>(device);
|
||||||
|
|
||||||
if (pb_device.block_size()) {
|
if (pb_device.block_size()) {
|
||||||
Disk *disk = dynamic_cast<Disk *>(device);
|
|
||||||
if (disk && disk->IsSectorSizeConfigurable()) {
|
if (disk && disk->IsSectorSizeConfigurable()) {
|
||||||
if (!disk->SetConfiguredSectorSize(pb_device.block_size())) {
|
if (!disk->SetConfiguredSectorSize(pb_device.block_size())) {
|
||||||
return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size()));
|
return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size()));
|
||||||
@ -822,7 +823,6 @@ bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
|||||||
device->SetProtected(pb_device.protected_());
|
device->SetProtected(pb_device.protected_());
|
||||||
}
|
}
|
||||||
|
|
||||||
Disk *disk = dynamic_cast<Disk *>(device);
|
|
||||||
if (disk) {
|
if (disk) {
|
||||||
disk->MediumChanged();
|
disk->MediumChanged();
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,7 @@ public:
|
|||||||
virtual void SetDAT(BYTE dat) = 0;
|
virtual void SetDAT(BYTE dat) = 0;
|
||||||
virtual BOOL GetDP() = 0; // Get parity signal
|
virtual BOOL GetDP() = 0; // Get parity signal
|
||||||
|
|
||||||
|
virtual DWORD Aquire() = 0;
|
||||||
virtual int CommandHandShake(BYTE *buf) = 0;
|
virtual int CommandHandShake(BYTE *buf) = 0;
|
||||||
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
|
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
|
||||||
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user