mirror of
https://github.com/akuker/RASCSI.git
synced 2024-11-25 20:33:35 +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
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIDEV::SetUnit(int no, Device *dev)
|
||||
void SASIDEV::SetUnit(int no, PrimaryDevice *dev)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// Get bus information
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
ctrl.bus->Aquire();
|
||||
|
||||
// Reset check
|
||||
if (ctrl.bus->GetRST()) {
|
||||
@ -664,7 +664,7 @@ void SASIDEV::CmdTestUnitReady()
|
||||
LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// 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__);
|
||||
|
||||
// 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__);
|
||||
|
||||
// Command processing on drive
|
||||
bool status = ((Disk *)ctrl.device)->CheckReady();
|
||||
// Command processing on device
|
||||
bool status = ctrl.device->CheckReady();
|
||||
if (!status) {
|
||||
// Failure (Error)
|
||||
Error();
|
||||
@ -871,8 +871,8 @@ void SASIDEV::CmdSpecify()
|
||||
{
|
||||
LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
|
||||
|
||||
// Command processing on drive
|
||||
bool status = ((Disk *)ctrl.device)->CheckReady();
|
||||
// Command processing on device
|
||||
bool status =ctrl.device->CheckReady();
|
||||
if (!status) {
|
||||
// Failure (Error)
|
||||
Error();
|
||||
@ -1143,10 +1143,12 @@ bool SASIDEV::XferOut(bool cont)
|
||||
case SASIDEV::eCmdWrite16:
|
||||
case SASIDEV::eCmdVerify10:
|
||||
case SASIDEV::eCmdVerify16:
|
||||
{
|
||||
// If we're a host bridge, use the host bridge's SendMessage10 function
|
||||
// TODO This class must not know about SCSIBR
|
||||
if (device->IsBridge()) {
|
||||
if (!((SCSIBR*)device)->SendMessage10(ctrl.cmd, ctrl.buffer)) {
|
||||
SCSIBR *bridge = dynamic_cast<SCSIBR *>(device);
|
||||
if (bridge) {
|
||||
if (!bridge->SendMessage10(ctrl.cmd, ctrl.buffer)) {
|
||||
// write failed
|
||||
return false;
|
||||
}
|
||||
@ -1158,8 +1160,9 @@ bool SASIDEV::XferOut(bool cont)
|
||||
|
||||
// Special case Write function for DaynaPort
|
||||
// TODO This class must not know about DaynaPort
|
||||
if (device->IsDaynaPort()) {
|
||||
if (!((SCSIDaynaPort*)device)->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
||||
SCSIDaynaPort *daynaport = dynamic_cast<SCSIDaynaPort *>(device);
|
||||
if (daynaport) {
|
||||
if (!daynaport->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
|
||||
// write failed
|
||||
return false;
|
||||
}
|
||||
@ -1191,6 +1194,7 @@ bool SASIDEV::XferOut(bool cont)
|
||||
// If normal, work setting
|
||||
ctrl.offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// SPECIFY(SASI only)
|
||||
case SASIDEV::eCmdInvalid:
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "fileio.h"
|
||||
|
||||
class Device;
|
||||
class PrimaryDevice;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
@ -123,10 +124,10 @@ public:
|
||||
DWORD length; // Transfer remaining length
|
||||
|
||||
// Logical unit
|
||||
Device *unit[UnitMax];
|
||||
PrimaryDevice *unit[UnitMax];
|
||||
|
||||
// The current device
|
||||
Device *device;
|
||||
PrimaryDevice *device;
|
||||
|
||||
// The LUN from the IDENTIFY message
|
||||
int lun;
|
||||
@ -144,7 +145,7 @@ public:
|
||||
// Connect
|
||||
void Connect(int id, BUS *sbus); // Controller connection
|
||||
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
|
||||
|
||||
// Other
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
SCSIDEV::SCSIDEV() : SASIDEV()
|
||||
{
|
||||
scsi.is_byte_transfer = false;
|
||||
scsi.bytes_to_transfer = 0;
|
||||
shutdown_mode = NONE;
|
||||
|
||||
@ -45,6 +46,7 @@ SCSIDEV::~SCSIDEV()
|
||||
|
||||
void SCSIDEV::Reset()
|
||||
{
|
||||
scsi.is_byte_transfer = false;
|
||||
scsi.bytes_to_transfer = 0;
|
||||
|
||||
// Work initialization
|
||||
@ -63,7 +65,7 @@ BUS::phase_t SCSIDEV::Process(int initiator_id)
|
||||
}
|
||||
|
||||
// Get bus information
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
ctrl.bus->Aquire();
|
||||
|
||||
// Check to see if the reset signal was asserted
|
||||
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)
|
||||
{
|
||||
// Get bus information
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
ctrl.bus->Aquire();
|
||||
|
||||
// Reset check
|
||||
if (ctrl.bus->GetRST()) {
|
||||
@ -402,24 +404,11 @@ void SCSIDEV::Send()
|
||||
ASSERT(!ctrl.bus->GetREQ());
|
||||
ASSERT(ctrl.bus->GetIO());
|
||||
|
||||
//if Length! = 0, send
|
||||
if (ctrl.length != 0) {
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length "
|
||||
+ to_string(ctrl.length)).c_str());
|
||||
|
||||
// TODO Get rid of Daynaport specific code in this class
|
||||
// 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);
|
||||
}
|
||||
int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0]->GetSendDelay());
|
||||
|
||||
// If you cannot send all, move to status phase
|
||||
if (len != (int)ctrl.length) {
|
||||
@ -522,13 +511,13 @@ void SCSIDEV::Receive()
|
||||
|
||||
// Length != 0 if received
|
||||
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
|
||||
len = ctrl.bus->ReceiveHandShake(&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||
|
||||
// If not able to receive all, move to status phase
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -658,7 +647,7 @@ void SCSIDEV::Receive()
|
||||
// Transfer period factor (limited to 50 x 4 = 200ns)
|
||||
scsi.syncperiod = scsi.msb[i + 3];
|
||||
if (scsi.syncperiod > 50) {
|
||||
scsi.syncoffset = 50;
|
||||
scsi.syncperiod = 50;
|
||||
}
|
||||
|
||||
// REQ/ACK offset(limited to 16)
|
||||
@ -736,13 +725,13 @@ void SCSIDEV::ReceiveBytes()
|
||||
ASSERT(!ctrl.bus->GetIO());
|
||||
|
||||
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);
|
||||
|
||||
// If not able to receive all, move to status phase
|
||||
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);
|
||||
Error();
|
||||
return;
|
||||
@ -904,6 +893,8 @@ bool SCSIDEV::XferOut(bool cont)
|
||||
|
||||
ASSERT(ctrl.phase == BUS::dataout);
|
||||
|
||||
scsi.is_byte_transfer = false;
|
||||
|
||||
PrimaryDevice *device = dynamic_cast<PrimaryDevice *>(ctrl.unit[GetEffectiveLun()]);
|
||||
if (device && ctrl.cmd[0] == scsi_defs::eCmdWrite6) {
|
||||
return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer);
|
||||
|
@ -184,8 +184,4 @@ public:
|
||||
|
||||
bool IsSASIHD() const { return type == "SAHD"; }
|
||||
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[SCRM] = { 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};
|
||||
|
||||
// 128 MB, 512 bytes per sector, 248826 sectors
|
||||
@ -124,20 +123,17 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||
try {
|
||||
switch (type) {
|
||||
case SAHD:
|
||||
device = new SASIHD();
|
||||
device = new SASIHD(sector_sizes[SAHD]);
|
||||
device->SetSupportedLuns(2);
|
||||
device->SetProduct("SASI HD");
|
||||
((Disk *)device)->SetSectorSizes(sector_sizes[SAHD]);
|
||||
break;
|
||||
|
||||
case SCHD: {
|
||||
string ext = GetExtension(filename);
|
||||
if (ext == "hdn" || ext == "hdi" || ext == "nhd") {
|
||||
device = new SCSIHD_NEC();
|
||||
((Disk *)device)->SetSectorSizes({ 512 });
|
||||
device = new SCSIHD_NEC({ 512 });
|
||||
} else {
|
||||
device = new SCSIHD(false);
|
||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCHD]);
|
||||
device = new SCSIHD(sector_sizes[SCHD], false);
|
||||
|
||||
// Some Apple tools require a particular drive identification
|
||||
if (ext == "hda") {
|
||||
@ -151,34 +147,30 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
||||
}
|
||||
|
||||
case SCRM:
|
||||
device = new SCSIHD(true);
|
||||
device = new SCSIHD(sector_sizes[SCRM], true);
|
||||
device->SetProtectable(true);
|
||||
device->SetStoppable(true);
|
||||
device->SetRemovable(true);
|
||||
device->SetLockable(true);
|
||||
device->SetProduct("SCSI HD (REM.)");
|
||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCRM]);
|
||||
break;
|
||||
|
||||
case SCMO:
|
||||
device = new SCSIMO();
|
||||
device = new SCSIMO(sector_sizes[SCMO], geometries[SCMO]);
|
||||
device->SetProtectable(true);
|
||||
device->SetStoppable(true);
|
||||
device->SetRemovable(true);
|
||||
device->SetLockable(true);
|
||||
device->SetProduct("SCSI MO");
|
||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCRM]);
|
||||
((Disk *)device)->SetGeometries(geometries[SCMO]);
|
||||
break;
|
||||
|
||||
case SCCD:
|
||||
device = new SCSICD();
|
||||
device = new SCSICD(sector_sizes[SCCD]);
|
||||
device->SetReadOnly(true);
|
||||
device->SetStoppable(true);
|
||||
device->SetRemovable(true);
|
||||
device->SetLockable(true);
|
||||
device->SetProduct("SCSI CD-ROM");
|
||||
((Disk *)device)->SetSectorSizes(sector_sizes[SCCD]);
|
||||
break;
|
||||
|
||||
case SCBR:
|
||||
|
@ -38,8 +38,8 @@ Disk::Disk(const string& id) : ModePageDevice(id), ScsiBlockCommands()
|
||||
dispatcher.AddCommand(eCmdRead6, "Read6", &Disk::Read6);
|
||||
dispatcher.AddCommand(eCmdWrite6, "Write6", &Disk::Write6);
|
||||
dispatcher.AddCommand(eCmdSeek6, "Seek6", &Disk::Seek6);
|
||||
dispatcher.AddCommand(eCmdReserve6, "Reserve6", &Disk::Reserve6);
|
||||
dispatcher.AddCommand(eCmdRelease6, "Release6", &Disk::Release6);
|
||||
dispatcher.AddCommand(eCmdReserve6, "Reserve6", &Disk::Reserve);
|
||||
dispatcher.AddCommand(eCmdRelease6, "Release6", &Disk::Release);
|
||||
dispatcher.AddCommand(eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit);
|
||||
dispatcher.AddCommand(eCmdSendDiag, "SendDiagnostic", &Disk::SendDiagnostic);
|
||||
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(eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache16);
|
||||
dispatcher.AddCommand(eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10);
|
||||
dispatcher.AddCommand(eCmdReserve10, "Reserve10", &Disk::Reserve10);
|
||||
dispatcher.AddCommand(eCmdRelease10, "Release10", &Disk::Release10);
|
||||
dispatcher.AddCommand(eCmdReserve10, "Reserve10", &Disk::Reserve);
|
||||
dispatcher.AddCommand(eCmdRelease10, "Release10", &Disk::Release);
|
||||
dispatcher.AddCommand(eCmdRead16, "Read16", &Disk::Read16);
|
||||
dispatcher.AddCommand(eCmdWrite16, "Write16", &Disk::Write16);
|
||||
dispatcher.AddCommand(eCmdVerify16, "Verify16", &Disk::Verify16);
|
||||
@ -101,7 +101,7 @@ bool Disk::Dispatch(SCSIDEV *controller)
|
||||
//---------------------------------------------------------------------------
|
||||
void Disk::Open(const Filepath& path)
|
||||
{
|
||||
ASSERT(disk.blocks > 0);
|
||||
assert(disk.blocks > 0);
|
||||
|
||||
SetReady(true);
|
||||
|
||||
@ -183,8 +183,6 @@ void Disk::Read6(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s READ(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
@ -193,8 +191,6 @@ void Disk::Read10(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s READ(10) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
@ -203,8 +199,6 @@ void Disk::Read16(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s READ(16) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Read(controller, start);
|
||||
}
|
||||
}
|
||||
@ -267,8 +261,6 @@ void Disk::Write6(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW6)) {
|
||||
LOGDEBUG("%s WRITE(6) command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
@ -277,8 +269,6 @@ void Disk::Write10(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW10)) {
|
||||
LOGDEBUG("%s WRITE(10) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
@ -287,8 +277,6 @@ void Disk::Write16(SASIDEV *controller)
|
||||
{
|
||||
uint64_t start;
|
||||
if (GetStartAndCount(controller, start, ctrl->blocks, RW16)) {
|
||||
LOGDEBUG("%s WRITE(16) command record=$%08X blocks=%d",__PRETTY_FUNCTION__, (uint32_t)start, ctrl->blocks);
|
||||
|
||||
Write(controller, start);
|
||||
}
|
||||
}
|
||||
@ -329,8 +317,6 @@ void Disk::Verify10(SASIDEV *controller)
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -340,8 +326,6 @@ void Disk::Verify16(SASIDEV *controller)
|
||||
// Get record number and block number
|
||||
uint64_t record;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -396,7 +380,7 @@ void Disk::SynchronizeCache16(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) {
|
||||
controller->Error();
|
||||
return;
|
||||
@ -438,29 +422,9 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||
int length = (int)cdb[4];
|
||||
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
|
||||
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
|
||||
if ((cdb[1] & 0x08) == 0) {
|
||||
// Mode parameter header, block descriptor length
|
||||
@ -486,70 +450,14 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||
size = 12;
|
||||
}
|
||||
|
||||
// Page code 1 (read-write error recovery)
|
||||
if (page == 0x01 || page == 0x3f) {
|
||||
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);
|
||||
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
|
||||
if (size > length) {
|
||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
@ -559,40 +467,18 @@ int Disk::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||
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
|
||||
int length = cdb[7];
|
||||
length <<= 8;
|
||||
length |= cdb[8];
|
||||
if (length > 0x800) {
|
||||
length = 0x800;
|
||||
int length = (cdb[7] << 8) | cdb[8];
|
||||
if (length > max_length) {
|
||||
length = max_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
|
||||
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
|
||||
if ((cdb[1] & 0x08) == 0) {
|
||||
// Only if ready
|
||||
@ -646,70 +532,14 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
||||
}
|
||||
}
|
||||
|
||||
// Page code 1 (read-write error recovery)
|
||||
if (page == 0x01 || page == 0x3f) {
|
||||
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);
|
||||
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
|
||||
if (size > length) {
|
||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
@ -720,28 +550,65 @@ int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
||||
return size;
|
||||
}
|
||||
|
||||
int Disk::AddErrorPage(bool change, BYTE *buf)
|
||||
void Disk::SetDeviceParameters(BYTE *buf)
|
||||
{
|
||||
// Set the message length
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x0a;
|
||||
|
||||
// Retry count is 0, limit time uses internal default value
|
||||
return 12;
|
||||
// DEVICE SPECIFIC PARAMETER
|
||||
if (IsProtected()) {
|
||||
buf[3] = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
int Disk::AddFormatPage(bool change, BYTE *buf)
|
||||
void Disk::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||
{
|
||||
// Set the message length
|
||||
buf[0] = 0x80 | 0x03;
|
||||
buf[1] = 0x16;
|
||||
// Page code 1 (read-write error recovery)
|
||||
if (page == 0x01 || page == 0x3f) {
|
||||
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
|
||||
// (though it cannot be changed in practice)
|
||||
if (change) {
|
||||
if (changeable) {
|
||||
buf[0xc] = 0xff;
|
||||
buf[0xd] = 0xff;
|
||||
return 24;
|
||||
|
||||
pages[3] = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsReady()) {
|
||||
@ -763,18 +630,18 @@ int Disk::AddFormatPage(bool change, BYTE *buf)
|
||||
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
|
||||
buf[0] = 0x04;
|
||||
buf[1] = 0x16;
|
||||
vector<BYTE> buf(24);
|
||||
|
||||
// No changeable area
|
||||
if (change) {
|
||||
return 24;
|
||||
if (changeable) {
|
||||
pages[4] = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsReady()) {
|
||||
@ -791,81 +658,30 @@ int Disk::AddDrivePage(bool change, BYTE *buf)
|
||||
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
|
||||
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;
|
||||
vector<BYTE> buf(12);
|
||||
|
||||
// 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
|
||||
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;
|
||||
// Nothing to add by default
|
||||
}
|
||||
|
||||
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
|
||||
DWORD length = cdb[7];
|
||||
length <<= 8;
|
||||
length |= cdb[8];
|
||||
if (length > 0x800) {
|
||||
length = 0x800;
|
||||
int length = (cdb[7] << 8) | cdb[8];
|
||||
if (length > max_length) {
|
||||
length = max_length;
|
||||
}
|
||||
ASSERT((length >= 0) && (length < 0x800));
|
||||
memset(buf, 0, length);
|
||||
|
||||
// P/G/FORMAT
|
||||
@ -909,17 +725,10 @@ bool Disk::Format(const DWORD *cdb)
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// READ
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
// 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.
|
||||
int Disk::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||
|
||||
if (!CheckReady()) {
|
||||
@ -939,14 +748,9 @@ int Disk::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
||||
}
|
||||
|
||||
// Success
|
||||
return (1 << disk.size);
|
||||
return 1 << disk.size;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// WRITE check
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int Disk::WriteCheck(DWORD block)
|
||||
{
|
||||
// Status check
|
||||
@ -968,20 +772,13 @@ int Disk::WriteCheck(DWORD block)
|
||||
}
|
||||
|
||||
// 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)
|
||||
// and the track-oriented cache.
|
||||
bool Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||
|
||||
// Error if not ready
|
||||
@ -1011,6 +808,7 @@ bool Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO For SCSI the specification mandates that the block address is verified
|
||||
void Disk::Seek(SASIDEV *controller)
|
||||
{
|
||||
if (!CheckReady()) {
|
||||
@ -1089,23 +887,13 @@ bool Disk::SendDiag(const DWORD *cdb)
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
uint32_t blocks = disk.blocks - 1;
|
||||
buf[0] = (BYTE)(blocks >> 24);
|
||||
@ -1128,15 +916,13 @@ void Disk::ReadCapacity10(SASIDEV *controller)
|
||||
|
||||
void Disk::ReadCapacity16(SASIDEV *controller)
|
||||
{
|
||||
BYTE *buf = ctrl->buffer;
|
||||
|
||||
memset(buf, 0, 14);
|
||||
|
||||
if (!CheckReady() || disk.blocks <= 0) {
|
||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
||||
return;
|
||||
}
|
||||
|
||||
BYTE *buf = ctrl->buffer;
|
||||
|
||||
// Create end of logical block address (disk.blocks-1)
|
||||
uint64_t blocks = disk.blocks - 1;
|
||||
buf[0] = (BYTE)(blocks >> 56);
|
||||
@ -1155,6 +941,8 @@ void Disk::ReadCapacity16(SASIDEV *controller)
|
||||
buf[10] = (BYTE)(length >> 8);
|
||||
buf[11] = (BYTE)length;
|
||||
|
||||
buf[12] = 0;
|
||||
|
||||
// Logical blocks per physical block: not reported (1 or more)
|
||||
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
|
||||
// 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.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Disk::Reserve6(SASIDEV *controller)
|
||||
void Disk::Reserve(SASIDEV *controller)
|
||||
{
|
||||
controller->Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// 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)
|
||||
void Disk::Release(SASIDEV *controller)
|
||||
{
|
||||
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
|
||||
uint64_t capacity = GetBlockCount();
|
||||
if (start > capacity || start + count > capacity) {
|
||||
|
@ -96,10 +96,8 @@ private:
|
||||
void Seek10(SASIDEV *);
|
||||
void ReadCapacity10(SASIDEV *) override;
|
||||
void ReadCapacity16(SASIDEV *) override;
|
||||
void Reserve6(SASIDEV *);
|
||||
void Reserve10(SASIDEV *);
|
||||
void Release6(SASIDEV *);
|
||||
void Release10(SASIDEV *);
|
||||
void Reserve(SASIDEV *);
|
||||
void Release(SASIDEV *);
|
||||
|
||||
public:
|
||||
|
||||
@ -117,7 +115,7 @@ public:
|
||||
bool SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
|
||||
|
||||
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;
|
||||
void SetSectorSizeInBytes(uint32_t, bool);
|
||||
@ -138,15 +136,14 @@ public:
|
||||
|
||||
protected:
|
||||
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
||||
int ModeSense10(const DWORD *cdb, BYTE *buf);
|
||||
virtual int AddErrorPage(bool change, BYTE *buf);
|
||||
virtual int AddFormatPage(bool change, BYTE *buf);
|
||||
virtual int AddDrivePage(bool change, BYTE *buf);
|
||||
virtual int AddVendorPage(int page, bool change, BYTE *buf);
|
||||
int AddOptionPage(bool change, BYTE *buf);
|
||||
int AddCachePage(bool change, BYTE *buf);
|
||||
int AddCDROMPage(bool change, BYTE *buf);
|
||||
int AddCDDAPage(bool, BYTE *buf);
|
||||
int ModeSense10(const DWORD *cdb, BYTE *buf, int);
|
||||
virtual void SetDeviceParameters(BYTE *);
|
||||
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||
virtual void AddErrorPage(map<int, vector<BYTE>>&, bool) const;
|
||||
virtual void AddFormatPage(map<int, vector<BYTE>>&, bool) const;
|
||||
virtual void AddDrivePage(map<int, vector<BYTE>>&, bool) const;
|
||||
void AddCachePage(map<int, vector<BYTE>>&, bool) const;
|
||||
virtual void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const;
|
||||
|
||||
// Internal disk data
|
||||
disk_t disk;
|
||||
|
@ -101,107 +101,92 @@ void HostServices::StartStopUnit(SCSIDEV *controller)
|
||||
|
||||
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];
|
||||
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 = 4;
|
||||
|
||||
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);
|
||||
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
|
||||
if (size > length) {
|
||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
// Final setting of mode data length
|
||||
buf[0] = 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
|
||||
int length = cdb[7];
|
||||
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);
|
||||
// Block descriptors cannot be returned
|
||||
if (!(cdb[1] & 0x08)) {
|
||||
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
|
||||
if (size > length) {
|
||||
LOGTRACE("%s %d bytes available, %d bytes requested", __PRETTY_FUNCTION__, size, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
// Final setting of mode data length
|
||||
buf[0] = size >> 8;
|
||||
buf[1] = 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
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x01;
|
||||
buf[3] = 0x00;
|
||||
|
||||
std::time_t t = std::time(NULL);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
buf[2] = tm.tm_year;
|
||||
buf[3] = tm.tm_mon;
|
||||
buf[4] = tm.tm_mday;
|
||||
buf[5] = tm.tm_hour;
|
||||
buf[6] = tm.tm_min;
|
||||
buf[4] = tm.tm_year;
|
||||
buf[5] = tm.tm_mon;
|
||||
buf[6] = tm.tm_mday;
|
||||
buf[7] = tm.tm_hour;
|
||||
buf[8] = tm.tm_min;
|
||||
// Ignore leap second for simplicity
|
||||
buf[7] = tm.tm_sec < 60 ? tm.tm_sec : 59;
|
||||
|
||||
return 8;
|
||||
buf[9] = tm.tm_sec < 60 ? tm.tm_sec : 59;
|
||||
}
|
||||
|
||||
return 0;
|
||||
pages[32] = buf;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "mode_page_device.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -29,7 +30,7 @@ public:
|
||||
void StartStopUnit(SCSIDEV *);
|
||||
|
||||
int ModeSense6(const DWORD *, BYTE *);
|
||||
int ModeSense10(const DWORD *, BYTE *);
|
||||
int ModeSense10(const DWORD *, BYTE *, int);
|
||||
|
||||
private:
|
||||
|
||||
@ -37,5 +38,6 @@ private:
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ctrl->length = ModeSense6(ctrl->cmd, ctrl->buffer);
|
||||
@ -43,7 +103,7 @@ void ModePageDevice::ModeSense6(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) {
|
||||
controller->Error();
|
||||
return;
|
||||
@ -52,12 +112,9 @@ void ModePageDevice::ModeSense10(SASIDEV *controller)
|
||||
controller->DataIn();
|
||||
}
|
||||
|
||||
bool ModePageDevice::ModeSelect(const DWORD* /*cdb*/, const BYTE *buf, int length)
|
||||
bool ModePageDevice::ModeSelect(const DWORD*, const BYTE *, int)
|
||||
{
|
||||
ASSERT(buf);
|
||||
ASSERT(length >= 0);
|
||||
|
||||
// cannot be set
|
||||
// Cannot be set
|
||||
SetStatusCode(STATUS_INVALIDPRM);
|
||||
|
||||
return false;
|
||||
@ -67,7 +124,7 @@ void ModePageDevice::ModeSelect6(SASIDEV *controller)
|
||||
{
|
||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||
|
||||
ctrl->length = ModeSelectCheck6(ctrl->cmd);
|
||||
ctrl->length = ModeSelectCheck6();
|
||||
if (ctrl->length <= 0) {
|
||||
controller->Error();
|
||||
return;
|
||||
@ -80,7 +137,7 @@ void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
||||
{
|
||||
LOGTRACE("%s Unsupported mode page $%02X", __PRETTY_FUNCTION__, ctrl->buffer[0]);
|
||||
|
||||
ctrl->length = ModeSelectCheck10(ctrl->cmd);
|
||||
ctrl->length = ModeSelectCheck10();
|
||||
if (ctrl->length <= 0) {
|
||||
controller->Error();
|
||||
return;
|
||||
@ -89,11 +146,11 @@ void ModePageDevice::ModeSelect10(SASIDEV *controller)
|
||||
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
|
||||
// TODO This assumption is not correct, and this code should be located elsewhere
|
||||
if (!IsSCSIHD() && (cdb[1] & 0x01)) {
|
||||
// TODO The assumption above is not correct, and this code should be located elsewhere
|
||||
if (!IsSCSIHD() && (ctrl->cmd[1] & 0x01)) {
|
||||
SetStatusCode(STATUS_INVALIDCDB);
|
||||
return 0;
|
||||
}
|
||||
@ -101,21 +158,21 @@ int ModePageDevice::ModeSelectCheck(const DWORD *cdb, int length)
|
||||
return length;
|
||||
}
|
||||
|
||||
int ModePageDevice::ModeSelectCheck6(const DWORD *cdb)
|
||||
int ModePageDevice::ModeSelectCheck6()
|
||||
{
|
||||
// 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
|
||||
int length = cdb[7];
|
||||
int length = ctrl->cmd[7];
|
||||
length <<= 8;
|
||||
length |= cdb[8];
|
||||
if (length > 0x800) {
|
||||
length = 0x800;
|
||||
length |= ctrl->cmd[8];
|
||||
if (length > ctrl->bufsize) {
|
||||
length = ctrl->bufsize;
|
||||
}
|
||||
|
||||
return ModeSelectCheck(cdb, length);
|
||||
return ModeSelectCheck(length);
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "primary_device.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -24,11 +26,16 @@ public:
|
||||
virtual bool Dispatch(SCSIDEV *) override;
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
typedef PrimaryDevice super;
|
||||
@ -40,7 +47,7 @@ private:
|
||||
void ModeSelect6(SASIDEV *);
|
||||
void ModeSelect10(SASIDEV *);
|
||||
|
||||
int ModeSelectCheck(const DWORD *, int);
|
||||
int ModeSelectCheck6(const DWORD *);
|
||||
int ModeSelectCheck10(const DWORD *);
|
||||
int ModeSelectCheck(int);
|
||||
int ModeSelectCheck6();
|
||||
int ModeSelectCheck10();
|
||||
};
|
||||
|
@ -68,11 +68,6 @@ void PrimaryDevice::ReportLuns(SASIDEV *controller)
|
||||
{
|
||||
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];
|
||||
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);
|
||||
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]);
|
||||
|
||||
@ -124,7 +119,7 @@ bool PrimaryDevice::CheckReady()
|
||||
if (IsReset()) {
|
||||
SetStatusCode(STATUS_DEVRESET);
|
||||
SetReset(false);
|
||||
LOGTRACE("%s Disk in reset", __PRETTY_FUNCTION__);
|
||||
LOGTRACE("%s Device in reset", __PRETTY_FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -132,26 +127,32 @@ bool PrimaryDevice::CheckReady()
|
||||
if (IsAttn()) {
|
||||
SetStatusCode(STATUS_ATTENTION);
|
||||
SetAttn(false);
|
||||
LOGTRACE("%s Disk in needs attention", __PRETTY_FUNCTION__);
|
||||
LOGTRACE("%s Device in needs attention", __PRETTY_FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return status if not ready
|
||||
if (!IsReady()) {
|
||||
SetStatusCode(STATUS_NOTREADY);
|
||||
LOGTRACE("%s Disk not ready", __PRETTY_FUNCTION__);
|
||||
LOGTRACE("%s Device not ready", __PRETTY_FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialization with no error
|
||||
LOGTRACE("%s Disk is ready", __PRETTY_FUNCTION__);
|
||||
LOGTRACE("%s Device is ready", __PRETTY_FUNCTION__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 > 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[1] = is_removable ? 0x80 : 0x00;
|
||||
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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
ASSERT(cdb);
|
||||
ASSERT(buf);
|
||||
|
||||
// Return not ready only if there are no errors
|
||||
if (GetStatusCode() == STATUS_NOERROR) {
|
||||
if (!IsReady()) {
|
||||
SetStatusCode(STATUS_NOTREADY);
|
||||
}
|
||||
if (GetStatusCode() == STATUS_NOERROR && !IsReady()) {
|
||||
SetStatusCode(STATUS_NOTREADY);
|
||||
}
|
||||
|
||||
// Size determination (according to allocation length)
|
||||
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
|
||||
// (Deleted this specification for SCSI-2)
|
||||
if (size == 0) {
|
||||
size = 4;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
virtual int Inquiry(const DWORD *, BYTE *) = 0;
|
||||
virtual int RequestSense(const DWORD *, BYTE *);
|
||||
virtual bool WriteBytes(BYTE *, uint32_t);
|
||||
virtual int GetSendDelay() { return BUS::SEND_NO_DELAY; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -19,26 +19,11 @@
|
||||
#include "exceptions.h"
|
||||
#include "../config.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// SASI Hard Disk
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
SASIHD::SASIHD() : Disk("SAHD")
|
||||
SASIHD::SASIHD(const set<uint32_t>& sector_sizes) : Disk("SAHD")
|
||||
{
|
||||
SetSectorSizes(sector_sizes);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIHD::Reset()
|
||||
{
|
||||
// Unlock, clear attention
|
||||
@ -50,14 +35,9 @@ void SASIHD::Reset()
|
||||
SetStatusCode(STATUS_NOERROR);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Open
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SASIHD::Open(const Filepath& path)
|
||||
{
|
||||
ASSERT(!IsReady());
|
||||
assert(!IsReady());
|
||||
|
||||
// Open as read-only
|
||||
Fileio fio;
|
||||
@ -101,30 +81,17 @@ void SASIHD::Open(const Filepath& path)
|
||||
FileSupport::SetPath(path);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// INQUIRY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SASIHD::Inquiry(const DWORD* /*cdb*/, BYTE* /*buf*/)
|
||||
{
|
||||
SetStatusCode(STATUS_INVALIDCMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// REQUEST SENSE
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SASIHD::RequestSense(const DWORD *cdb, BYTE *buf)
|
||||
{
|
||||
ASSERT(cdb);
|
||||
ASSERT(buf);
|
||||
|
||||
// Size decision
|
||||
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)
|
||||
if (size == 0) {
|
||||
|
@ -27,8 +27,8 @@
|
||||
class SASIHD : public Disk, public FileSupport
|
||||
{
|
||||
public:
|
||||
SASIHD();
|
||||
~SASIHD() {};
|
||||
SASIHD(const set<uint32_t>&);
|
||||
~SASIHD() {}
|
||||
|
||||
void Reset();
|
||||
void Open(const Filepath& path) override;
|
||||
|
@ -583,3 +583,11 @@ void SCSIDaynaPort::EnableInterface(SASIDEV *controller)
|
||||
|
||||
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 SetMcastAddr(SASIDEV *);
|
||||
void EnableInterface(SASIDEV *);
|
||||
int GetSendDelay() override;
|
||||
|
||||
bool Dispatch(SCSIDEV *) override;
|
||||
|
||||
|
@ -121,7 +121,7 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
buf[0] = 0x09;
|
||||
buf[2] = 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
|
||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||
@ -152,13 +152,9 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
void SCSIBR::TestUnitReady(SASIDEV *controller)
|
||||
{
|
||||
// Always successful
|
||||
controller->Status();}
|
||||
controller->Status();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// GET MESSAGE(10)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
||||
{
|
||||
// Type
|
||||
@ -239,16 +235,8 @@ int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SEND MESSAGE(10)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
||||
{
|
||||
ASSERT(cdb);
|
||||
ASSERT(buf);
|
||||
|
||||
// Type
|
||||
int type = cdb[2];
|
||||
|
||||
@ -301,11 +289,6 @@ bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// GET MESSAGE(10)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::GetMessage10(SASIDEV *controller)
|
||||
{
|
||||
// Reallocate buffer (because it is not transfer for each block)
|
||||
@ -365,41 +348,22 @@ void SCSIBR::SendMessage10(SASIDEV *controller)
|
||||
controller->DataOut();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get MAC Address
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::GetMacAddr(BYTE *mac)
|
||||
{
|
||||
ASSERT(mac);
|
||||
|
||||
memcpy(mac, mac_addr, 6);
|
||||
return 6;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Set MAC Address
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::SetMacAddr(BYTE *mac)
|
||||
{
|
||||
ASSERT(mac);
|
||||
|
||||
memcpy(mac_addr, mac, 6);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Receive Packet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::ReceivePacket()
|
||||
{
|
||||
static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
ASSERT(tap);
|
||||
assert(tap);
|
||||
|
||||
// previous packet has not been received
|
||||
if (packet_enable) {
|
||||
@ -429,15 +393,9 @@ void SCSIBR::ReceivePacket()
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get Packet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::GetPacketBuf(BYTE *buf)
|
||||
{
|
||||
ASSERT(tap);
|
||||
ASSERT(buf);
|
||||
assert(tap);
|
||||
|
||||
// Size limit
|
||||
int len = packet_len;
|
||||
@ -452,15 +410,9 @@ void SCSIBR::GetPacketBuf(BYTE *buf)
|
||||
packet_enable = false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Send Packet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::SendPacket(BYTE *buf, int len)
|
||||
{
|
||||
ASSERT(tap);
|
||||
ASSERT(buf);
|
||||
assert(tap);
|
||||
|
||||
tap->Tx(buf, len);
|
||||
}
|
||||
@ -472,9 +424,6 @@ void SCSIBR::SendPacket(BYTE *buf, int len)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_InitDevice(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
fs->Reset();
|
||||
fsresult = fs->InitDevice((Human68k::argument_t*)buf);
|
||||
}
|
||||
@ -486,13 +435,9 @@ void SCSIBR::FS_InitDevice(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CheckDir(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -507,13 +452,9 @@ void SCSIBR::FS_CheckDir(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_MakeDir(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -528,13 +469,9 @@ void SCSIBR::FS_MakeDir(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_RemoveDir(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -549,13 +486,9 @@ void SCSIBR::FS_RemoveDir(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Rename(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -573,13 +506,9 @@ void SCSIBR::FS_Rename(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Delete(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -594,13 +523,9 @@ void SCSIBR::FS_Delete(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Attribute(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
|
||||
i += sizeof(Human68k::namests_t);
|
||||
@ -619,13 +544,9 @@ void SCSIBR::FS_Attribute(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Files(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -665,13 +586,9 @@ void SCSIBR::FS_Files(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_NFiles(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -708,13 +625,9 @@ void SCSIBR::FS_NFiles(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Create(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -762,13 +675,9 @@ void SCSIBR::FS_Create(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Open(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -808,13 +717,9 @@ void SCSIBR::FS_Open(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Close(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -851,13 +756,9 @@ void SCSIBR::FS_Close(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Read(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nKey = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||
i += sizeof(Human68k::fcb_t);
|
||||
@ -896,13 +797,9 @@ void SCSIBR::FS_Read(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Write(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nKey = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||
i += sizeof(Human68k::fcb_t);
|
||||
@ -939,13 +836,9 @@ void SCSIBR::FS_Write(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Seek(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nKey = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
|
||||
i += sizeof(Human68k::fcb_t);
|
||||
@ -986,13 +879,9 @@ void SCSIBR::FS_Seek(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_TimeStamp(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nKey = ntohl(*dp);
|
||||
@ -1033,9 +922,6 @@ void SCSIBR::FS_TimeStamp(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_GetCapacity(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1058,13 +944,9 @@ void SCSIBR::FS_GetCapacity(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CtrlDrive(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
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)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1108,13 +987,9 @@ void SCSIBR::FS_GetDPB(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_DiskRead(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nSector = ntohl(*dp);
|
||||
@ -1135,9 +1010,6 @@ void SCSIBR::FS_DiskRead(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_DiskWrite(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1151,13 +1023,9 @@ void SCSIBR::FS_DiskWrite(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Ioctrl(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
int i = 0;
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
i += sizeof(DWORD);
|
||||
int i = sizeof(DWORD);
|
||||
|
||||
dp = (DWORD*)&buf[i];
|
||||
DWORD nFunction = ntohl(*dp);
|
||||
@ -1198,9 +1066,6 @@ void SCSIBR::FS_Ioctrl(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Flush(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1214,9 +1079,6 @@ void SCSIBR::FS_Flush(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CheckMedia(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1230,9 +1092,6 @@ void SCSIBR::FS_CheckMedia(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Lock(BYTE *buf)
|
||||
{
|
||||
ASSERT(fs);
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
DWORD nUnit = ntohl(*dp);
|
||||
|
||||
@ -1246,8 +1105,6 @@ void SCSIBR::FS_Lock(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsResult(BYTE *buf)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
DWORD *dp = (DWORD*)buf;
|
||||
*dp = htonl(fsresult);
|
||||
return sizeof(DWORD);
|
||||
@ -1260,8 +1117,6 @@ int SCSIBR::ReadFsResult(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsOut(BYTE *buf)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
memcpy(buf, fsout, fsoutlen);
|
||||
return fsoutlen;
|
||||
}
|
||||
@ -1273,8 +1128,6 @@ int SCSIBR::ReadFsOut(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsOpt(BYTE *buf)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
memcpy(buf, fsopt, fsoptlen);
|
||||
return fsoptlen;
|
||||
}
|
||||
@ -1286,8 +1139,6 @@ int SCSIBR::ReadFsOpt(BYTE *buf)
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::WriteFs(int func, BYTE *buf)
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
fsresult = FS_FATAL_INVALIDCOMMAND;
|
||||
fsoutlen = 0;
|
||||
fsoptlen = 0;
|
||||
|
@ -17,7 +17,8 @@
|
||||
// 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
|
||||
// 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
|
||||
// multi-initiator environment).
|
||||
//
|
||||
@ -68,7 +69,7 @@ SCSIPrinter::SCSIPrinter() : PrimaryDevice("SCLP"), ScsiPrinterCommands()
|
||||
|
||||
SCSIPrinter::~SCSIPrinter()
|
||||
{
|
||||
DiscardReservation();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
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,
|
||||
// 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");
|
||||
|
||||
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
|
||||
rawfile = false;
|
||||
|
||||
@ -262,7 +264,7 @@ void SCSICD::Open(const Filepath& path)
|
||||
// Successful opening
|
||||
ASSERT(GetBlockCount() > 0);
|
||||
|
||||
Disk::Open(path);
|
||||
super::Open(path);
|
||||
FileSupport::SetPath(path);
|
||||
|
||||
// Set RAW flag
|
||||
@ -414,7 +416,7 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
buf[1] = 0x80;
|
||||
buf[2] = 0x02;
|
||||
buf[3] = 0x02;
|
||||
buf[4] = 36 - 5; // Required
|
||||
buf[4] = 0x1F;
|
||||
|
||||
// Fill with blanks
|
||||
memset(&buf[8], 0x20, buf[4] - 3);
|
||||
@ -456,6 +458,48 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
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)
|
||||
{
|
||||
ASSERT(buf);
|
||||
@ -497,7 +541,7 @@ int SCSICD::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
|
||||
|
||||
// Base class
|
||||
ASSERT(dataindex >= 0);
|
||||
return Disk::Read(cdb, buf, block);
|
||||
return super::Read(cdb, buf, block);
|
||||
}
|
||||
|
||||
int SCSICD::ReadToc(const DWORD *cdb, BYTE *buf)
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
TrackMax = 96 // Maximum number of tracks
|
||||
};
|
||||
|
||||
SCSICD();
|
||||
SCSICD(const set<uint32_t>&);
|
||||
~SCSICD();
|
||||
|
||||
bool Dispatch(SCSIDEV *) override;
|
||||
@ -88,11 +88,18 @@ public:
|
||||
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; // READ command
|
||||
int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
|
||||
|
||||
protected:
|
||||
|
||||
void AddModePages(map<int, vector<BYTE>>&, int, bool) const override;
|
||||
|
||||
private:
|
||||
typedef Disk super;
|
||||
|
||||
Dispatcher<SCSICD, SASIDEV> dispatcher;
|
||||
|
||||
void AddCDROMPage(map<int, vector<BYTE>>&, bool) const;
|
||||
void AddCDDAPage(map<int, vector<BYTE>>&, bool) const;
|
||||
|
||||
// Open
|
||||
void OpenCue(const Filepath& path); // Open(CUE)
|
||||
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)
|
||||
@ -75,7 +76,7 @@ void SCSIHD::Reset()
|
||||
|
||||
void SCSIHD::Open(const Filepath& path)
|
||||
{
|
||||
ASSERT(!IsReady());
|
||||
assert(!IsReady());
|
||||
|
||||
// Open as read-only
|
||||
Fileio fio;
|
||||
@ -105,12 +106,6 @@ int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ready check (Error if no image file)
|
||||
if (!IsReady()) {
|
||||
SetStatusCode(STATUS_NOTREADY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Basic data
|
||||
// buf[0] ... Direct Access Device
|
||||
// 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[2] = 0x02;
|
||||
buf[3] = 0x02;
|
||||
buf[4] = 28 + 3; // Value close to real HDD
|
||||
buf[4] = 0x1F;
|
||||
|
||||
// Padded vendor, product, revision
|
||||
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)
|
||||
{
|
||||
int size;
|
||||
assert(length >= 0);
|
||||
|
||||
ASSERT(buf);
|
||||
ASSERT(length >= 0);
|
||||
int size;
|
||||
|
||||
// PF
|
||||
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
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
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 or 63
|
||||
// Page code 48
|
||||
if (page != 0x30 && page != 0x3f) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the message length
|
||||
buf[0] = 0x30;
|
||||
buf[1] = 0x1c;
|
||||
vector<BYTE> buf(30);
|
||||
|
||||
// No changeable area
|
||||
if (!change) {
|
||||
memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20);
|
||||
if (!changeable) {
|
||||
memcpy(&buf.data()[0xa], "APPLE COMPUTER, INC.", 20);
|
||||
}
|
||||
|
||||
return 30;
|
||||
pages[48] = buf;
|
||||
}
|
||||
|
@ -22,8 +22,8 @@
|
||||
class SCSIHD : public Disk, public FileSupport
|
||||
{
|
||||
public:
|
||||
SCSIHD(bool);
|
||||
virtual ~SCSIHD() {};
|
||||
SCSIHD(const set<uint32_t>&, bool);
|
||||
virtual ~SCSIHD() {}
|
||||
|
||||
void FinalizeSetup(const Filepath&, off_t);
|
||||
|
||||
@ -34,6 +34,5 @@ public:
|
||||
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||
|
||||
// Add vendor special page
|
||||
int AddVendorPage(int page, bool change, BYTE *buf) override;
|
||||
void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const override;
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "fileio.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
|
||||
cylinders = 0;
|
||||
@ -146,31 +146,30 @@ int SCSIHD_NEC::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
return size;
|
||||
}
|
||||
|
||||
int SCSIHD_NEC::AddErrorPage(bool change, BYTE *buf)
|
||||
void SCSIHD_NEC::AddErrorPage(map<int, vector<BYTE>>& pages, bool) const
|
||||
{
|
||||
ASSERT(buf);
|
||||
|
||||
// Set the message length
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x06;
|
||||
vector<BYTE> buf(8);
|
||||
|
||||
// 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
|
||||
buf[0] = 0x80 | 0x03;
|
||||
buf[1] = 0x16;
|
||||
// Page can be saved
|
||||
buf[0] = 0x80;
|
||||
|
||||
// Make the number of bytes in the physical sector appear mutable (although it cannot actually be)
|
||||
if (change) {
|
||||
if (changeable) {
|
||||
buf[0xc] = 0xff;
|
||||
buf[0xd] = 0xff;
|
||||
return 24;
|
||||
|
||||
pages[3] = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsReady()) {
|
||||
@ -193,19 +192,15 @@ int SCSIHD_NEC::AddFormatPage(bool change, BYTE *buf)
|
||||
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);
|
||||
|
||||
// Set the message length
|
||||
buf[0] = 0x04;
|
||||
buf[1] = 0x12;
|
||||
vector<BYTE> buf(20);
|
||||
|
||||
// No changeable area
|
||||
if (!change && IsReady()) {
|
||||
if (!changeable && IsReady()) {
|
||||
// Set the number of cylinders
|
||||
buf[0x2] = (BYTE)(cylinders >> 16);
|
||||
buf[0x3] = (BYTE)(cylinders >> 8);
|
||||
@ -215,5 +210,5 @@ int SCSIHD_NEC::AddDrivePage(bool change, BYTE *buf)
|
||||
buf[0x5] = (BYTE)heads;
|
||||
}
|
||||
|
||||
return 20;
|
||||
pages[4] = buf;
|
||||
}
|
||||
|
@ -25,17 +25,17 @@
|
||||
class SCSIHD_NEC : public SCSIHD
|
||||
{
|
||||
public:
|
||||
SCSIHD_NEC();
|
||||
~SCSIHD_NEC() {};
|
||||
SCSIHD_NEC(const set<uint32_t>&);
|
||||
~SCSIHD_NEC() {}
|
||||
|
||||
void Open(const Filepath& path) override;
|
||||
|
||||
// Commands
|
||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||
|
||||
int AddErrorPage(bool change, BYTE *buf) override;
|
||||
int AddFormatPage(bool change, BYTE *buf) override;
|
||||
int AddDrivePage(bool change, BYTE *buf) override;
|
||||
void AddErrorPage(map<int, vector<BYTE>>&, bool) const override;
|
||||
void AddFormatPage(map<int, vector<BYTE>>&, bool) const override;
|
||||
void AddDrivePage(map<int, vector<BYTE>>&, bool) const override;
|
||||
|
||||
private:
|
||||
// Geometry data
|
||||
|
@ -19,29 +19,15 @@
|
||||
#include "fileio.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// SCSI magneto-optical disk
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
SCSIMO::SCSIMO() : Disk("SCMO")
|
||||
SCSIMO::SCSIMO(const set<uint32_t>& sector_sizes, const map<uint64_t, Geometry>& geometries) : Disk("SCMO")
|
||||
{
|
||||
SetSectorSizes(sector_sizes);
|
||||
SetGeometries(geometries);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Open
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIMO::Open(const Filepath& path)
|
||||
{
|
||||
ASSERT(!IsReady());
|
||||
assert(!IsReady());
|
||||
|
||||
// Open as read-only
|
||||
Fileio fio;
|
||||
@ -77,16 +63,8 @@ void SCSIMO::Open(const Filepath& path)
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// INQUIRY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
{
|
||||
ASSERT(cdb);
|
||||
ASSERT(buf);
|
||||
|
||||
// EVPD check
|
||||
if (cdb[1] & 0x01) {
|
||||
SetStatusCode(STATUS_INVALIDCDB);
|
||||
@ -104,7 +82,7 @@ int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
buf[1] = 0x80;
|
||||
buf[2] = 0x02;
|
||||
buf[3] = 0x02;
|
||||
buf[4] = 36 - 5; // required
|
||||
buf[4] = 0x1F;
|
||||
|
||||
// Padded vendor, product, revision
|
||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||
@ -120,16 +98,36 @@ int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
||||
return size;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// MODE SELECT
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIMO::SetDeviceParameters(BYTE *buf)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int size;
|
||||
|
||||
ASSERT(buf);
|
||||
ASSERT(length >= 0);
|
||||
|
||||
// PF
|
||||
@ -191,22 +189,20 @@ bool SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
||||
// 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
|
||||
if ((page != 0x20) && (page != 0x3f)) {
|
||||
return 0;
|
||||
if (page != 0x20 && page != 0x3f) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the message length
|
||||
buf[0] = 0x20;
|
||||
buf[1] = 0x0a;
|
||||
vector<BYTE> buf(12);
|
||||
|
||||
// No changeable area
|
||||
if (change) {
|
||||
return 12;
|
||||
if (changeable) {
|
||||
pages[32] = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -287,5 +283,7 @@ int SCSIMO::AddVendor(int page, BOOL change, BYTE *buf)
|
||||
buf[11] = (BYTE)bands;
|
||||
}
|
||||
|
||||
return 12;
|
||||
pages[32] = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -22,8 +22,8 @@
|
||||
class SCSIMO : public Disk, public FileSupport
|
||||
{
|
||||
public:
|
||||
SCSIMO();
|
||||
~SCSIMO() {};
|
||||
SCSIMO(const set<uint32_t>&, const map<uint64_t, Geometry>&);
|
||||
~SCSIMO() {}
|
||||
|
||||
void Open(const Filepath& path) override;
|
||||
|
||||
@ -31,6 +31,14 @@ public:
|
||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||
|
||||
protected:
|
||||
|
||||
// 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
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
inline DWORD Aquire()
|
||||
inline DWORD Aquire() override
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__X86__)
|
||||
// Only used for development/debugging purposes. Isn't really applicable
|
||||
@ -509,24 +509,24 @@ public:
|
||||
void SetENB(BOOL ast);
|
||||
// Set ENB signal
|
||||
|
||||
bool GetBSY();
|
||||
bool GetBSY() override;
|
||||
// Get BSY signal
|
||||
void SetBSY(bool ast);
|
||||
void SetBSY(bool ast) override;
|
||||
// Set BSY signal
|
||||
|
||||
BOOL GetSEL();
|
||||
BOOL GetSEL() override;
|
||||
// Get SEL signal
|
||||
void SetSEL(BOOL ast);
|
||||
void SetSEL(BOOL ast) override;
|
||||
// Set SEL signal
|
||||
|
||||
BOOL GetATN();
|
||||
BOOL GetATN() override;
|
||||
// Get ATN signal
|
||||
void SetATN(BOOL ast);
|
||||
void SetATN(BOOL ast) override;
|
||||
// Set ATN signal
|
||||
|
||||
BOOL GetACK();
|
||||
BOOL GetACK() override;
|
||||
// Get ACK signal
|
||||
void SetACK(BOOL ast);
|
||||
void SetACK(BOOL ast) override;
|
||||
// Set ACK signal
|
||||
|
||||
BOOL GetACT();
|
||||
@ -534,42 +534,42 @@ public:
|
||||
void SetACT(BOOL ast);
|
||||
// Set ACT signal
|
||||
|
||||
BOOL GetRST();
|
||||
BOOL GetRST() override;
|
||||
// Get RST signal
|
||||
void SetRST(BOOL ast);
|
||||
void SetRST(BOOL ast) override;
|
||||
// Set RST signal
|
||||
|
||||
BOOL GetMSG();
|
||||
BOOL GetMSG() override;
|
||||
// Get MSG signal
|
||||
void SetMSG(BOOL ast);
|
||||
void SetMSG(BOOL ast) override;
|
||||
// Set MSG signal
|
||||
|
||||
BOOL GetCD();
|
||||
BOOL GetCD() override;
|
||||
// Get CD signal
|
||||
void SetCD(BOOL ast);
|
||||
void SetCD(BOOL ast) override;
|
||||
// Set CD signal
|
||||
|
||||
BOOL GetIO();
|
||||
BOOL GetIO() override;
|
||||
// Get IO signal
|
||||
void SetIO(BOOL ast);
|
||||
void SetIO(BOOL ast) override;
|
||||
// Set IO signal
|
||||
|
||||
BOOL GetREQ();
|
||||
BOOL GetREQ() override;
|
||||
// Get REQ signal
|
||||
void SetREQ(BOOL ast);
|
||||
void SetREQ(BOOL ast) override;
|
||||
// Set REQ signal
|
||||
|
||||
BYTE GetDAT();
|
||||
BYTE GetDAT() override;
|
||||
// Get DAT signal
|
||||
void SetDAT(BYTE dat);
|
||||
void SetDAT(BYTE dat) override;
|
||||
// Set DAT signal
|
||||
BOOL GetDP();
|
||||
BOOL GetDP() override;
|
||||
// Get Data parity signal
|
||||
int CommandHandShake(BYTE *buf);
|
||||
int CommandHandShake(BYTE *buf) override;
|
||||
// Command receive handshake
|
||||
int ReceiveHandShake(BYTE *buf, int count);
|
||||
int ReceiveHandShake(BYTE *buf, int count) override;
|
||||
// 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
|
||||
|
||||
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 " : "",
|
||||
filename.c_str(), device->GetType().c_str(), pb_device.id(), pb_device.unit());
|
||||
|
||||
Disk *disk = dynamic_cast<Disk *>(device);
|
||||
|
||||
if (pb_device.block_size()) {
|
||||
Disk *disk = dynamic_cast<Disk *>(device);
|
||||
if (disk && disk->IsSectorSizeConfigurable()) {
|
||||
if (!disk->SetConfiguredSectorSize(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_());
|
||||
}
|
||||
|
||||
Disk *disk = dynamic_cast<Disk *>(device);
|
||||
if (disk) {
|
||||
disk->MediumChanged();
|
||||
}
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
virtual void SetDAT(BYTE dat) = 0;
|
||||
virtual BOOL GetDP() = 0; // Get parity signal
|
||||
|
||||
virtual DWORD Aquire() = 0;
|
||||
virtual int CommandHandShake(BYTE *buf) = 0;
|
||||
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
|
||||
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user