mirror of
https://github.com/akuker/RASCSI.git
synced 2025-01-10 17:30:47 +00:00
Use vector for INQUIRY data, LUN list can have gaps, made methods const (#713)
* Use vector for INQUIRY data, Inquiry() is const, moved EVPD check * Moved code * Fixed warning * Updated memcpy * Set length * Limit result vector size * Limit result buffer size * Inquiry() result buffer handling update * Logging update * Inquiry cleanup * NEC drive can also use PrimaryDevice::Inquiry() * NEC drive is never removable * Comment update * Bridge can also use PrimaryDevice::Inquiry() * Removed unused method argument * Comment update * Updated comment * Updated REQUEST SENSE buffer handling * Fixed typo * Fixed typo * Re-added comment * Updated additional length handling * Check for INQUIRY command support first * Added assertion * Size handling update * Renaming * Renaming * Removed obsolete casts * Cleanup * Moved error codes to scsi_defs namespace * Fixed ReadDefectData10 * Comment update * Updated buffer handling * Data type update * SendDiagnostic is now const * Removed obsolete forward declaration * removed unused enum * Reduced method visibility * Renaming * GetSendDelay() can be const * Made method const * Made method const * Added TODO * Use iterator * Made method const * Revert "Made method const" This reverts commit 38412b8dddbd1a60f34baa663a12d8285190e3a8. * No need to sort all set/maps * Do not sort all sets * Removed more unnecessary sorting * Cleaned up includes * More include cleanups * Updated REPORT LUNS * LUNs must not be consecutive anymore * Updated detaching of LUN * Improvements for devices without LUN 0 * Assume LUN 0 is always present * Enforce presence of LUN 0 * Updated error handling
This commit is contained in:
parent
da02eccb2e
commit
1df7cdb1f3
@ -623,7 +623,7 @@ void SASIDEV::DataOut()
|
|||||||
// Error
|
// Error
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
void SASIDEV::Error(sense_key sense_key, asc asc, status status)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
ctrl.bus->Aquire();
|
ctrl.bus->Aquire();
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "scsi.h"
|
#include "scsi.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
|
||||||
class Device;
|
|
||||||
class PrimaryDevice;
|
class PrimaryDevice;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -31,30 +30,6 @@ class PrimaryDevice;
|
|||||||
class SASIDEV
|
class SASIDEV
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
enum scsi_message_code : BYTE {
|
|
||||||
eMsgCodeAbort = 0x06,
|
|
||||||
eMsgCodeAbortTag = 0x0D,
|
|
||||||
eMsgCodeBusDeviceReset = 0x0C,
|
|
||||||
eMsgCodeClearQueue = 0x0E,
|
|
||||||
eMsgCodeCommandComplete = 0x00,
|
|
||||||
eMsgCodeDisconnect = 0x04,
|
|
||||||
eMsgCodeIdentify = 0x80,
|
|
||||||
eMsgCodeIgnoreWideResidue = 0x23, // (Two Bytes)
|
|
||||||
eMsgCodeInitiateRecovery = 0x0F,
|
|
||||||
eMsgCodeInitiatorDetectedError = 0x05,
|
|
||||||
eMsgCodeLinkedCommandComplete = 0x0A,
|
|
||||||
eMsgCodeLinkedCommandCompleteWithFlag = 0x0B,
|
|
||||||
eMsgCodeMessageParityError = 0x09,
|
|
||||||
eMsgCodeMessageReject = 0x07,
|
|
||||||
eMsgCodeNoOperation = 0x08,
|
|
||||||
eMsgCodeHeadOfQueueTag = 0x21,
|
|
||||||
eMsgCodeOrderedQueueTag = 0x22,
|
|
||||||
eMsgCodeSimpleQueueTag = 0x20,
|
|
||||||
eMsgCodeReleaseRecovery = 0x10,
|
|
||||||
eMsgCodeRestorePointers = 0x03,
|
|
||||||
eMsgCodeSaveDataPointer = 0x02,
|
|
||||||
eMsgCodeTerminateIOProcess = 0x11
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum sasi_command : int {
|
enum sasi_command : int {
|
||||||
@ -123,7 +98,7 @@ public:
|
|||||||
DWORD offset; // Transfer offset
|
DWORD offset; // Transfer offset
|
||||||
DWORD length; // Transfer remaining length
|
DWORD length; // Transfer remaining length
|
||||||
|
|
||||||
// Logical unit
|
// Logical units
|
||||||
PrimaryDevice *unit[UnitMax];
|
PrimaryDevice *unit[UnitMax];
|
||||||
|
|
||||||
// The current device
|
// The current device
|
||||||
@ -144,7 +119,7 @@ public:
|
|||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
void Connect(int id, BUS *sbus); // Controller connection
|
void Connect(int id, BUS *sbus); // Controller connection
|
||||||
Device* GetUnit(int no); // Get logical unit
|
PrimaryDevice* GetUnit(int no); // Get logical unit
|
||||||
void SetUnit(int no, PrimaryDevice *dev); // Logical unit setting
|
void SetUnit(int no, PrimaryDevice *dev); // Logical unit setting
|
||||||
bool HasUnit(); // Has a valid logical unit
|
bool HasUnit(); // Has a valid logical unit
|
||||||
|
|
||||||
@ -165,9 +140,9 @@ public:
|
|||||||
// Get LUN based on IDENTIFY message, with LUN from the CDB as fallback
|
// Get LUN based on IDENTIFY message, with LUN from the CDB as fallback
|
||||||
int GetEffectiveLun() const;
|
int GetEffectiveLun() const;
|
||||||
|
|
||||||
virtual void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
|
virtual void Error(scsi_defs::sense_key sense_key = scsi_defs::sense_key::NO_SENSE,
|
||||||
ERROR_CODES::asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
scsi_defs::asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
||||||
ERROR_CODES::status = ERROR_CODES::status::CHECK_CONDITION); // Common error handling
|
scsi_defs::status = scsi_defs::status::CHECK_CONDITION); // Common error handling
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Phase processing
|
// Phase processing
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include "devices/scsi_daynaport.h"
|
#include "devices/scsi_daynaport.h"
|
||||||
#include "devices/scsi_printer.h"
|
#include "devices/scsi_printer.h"
|
||||||
|
|
||||||
|
using namespace scsi_defs;
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// SCSI Device
|
// SCSI Device
|
||||||
@ -264,7 +266,7 @@ void SCSIDEV::Execute()
|
|||||||
ctrl.execstart = SysTimer::GetTimerLow();
|
ctrl.execstart = SysTimer::GetTimerLow();
|
||||||
|
|
||||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) {
|
if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) {
|
||||||
ctrl.status = 0;
|
ctrl.status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,11 +274,11 @@ void SCSIDEV::Execute()
|
|||||||
|
|
||||||
int lun = GetEffectiveLun();
|
int lun = GetEffectiveLun();
|
||||||
if (!ctrl.unit[lun]) {
|
if (!ctrl.unit[lun]) {
|
||||||
if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdInquiry &&
|
if ((scsi_command)ctrl.cmd[0] != eCmdInquiry &&
|
||||||
(scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) {
|
(scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) {
|
||||||
LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
|
LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
|
||||||
|
|
||||||
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Use LUN 0 for INQUIRY and REQUEST SENSE because LUN0 is assumed to be always available.
|
// Use LUN 0 for INQUIRY and REQUEST SENSE because LUN0 is assumed to be always available.
|
||||||
@ -291,18 +293,18 @@ void SCSIDEV::Execute()
|
|||||||
ctrl.device = ctrl.unit[lun];
|
ctrl.device = ctrl.unit[lun];
|
||||||
|
|
||||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||||
if ((scsi_defs::scsi_command)ctrl.cmd[0] != scsi_defs::eCmdRequestSense) {
|
if ((scsi_command)ctrl.cmd[0] != scsi_command::eCmdRequestSense) {
|
||||||
ctrl.device->SetStatusCode(0);
|
ctrl.device->SetStatusCode(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctrl.device->Dispatch(this)) {
|
if (!ctrl.device->Dispatch(this)) {
|
||||||
LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetSCSIID(), lun, (BYTE)ctrl.cmd[0]);
|
LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetSCSIID(), lun, (BYTE)ctrl.cmd[0]);
|
||||||
|
|
||||||
Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE);
|
Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
|
// SCSI-2 p.104 4.4.3 Incorrect logical unit handling
|
||||||
if ((scsi_defs::scsi_command)ctrl.cmd[0] == scsi_defs::eCmdInquiry && !ctrl.unit[lun]) {
|
if ((scsi_command)ctrl.cmd[0] == scsi_command::eCmdInquiry && !ctrl.unit[lun]) {
|
||||||
lun = GetEffectiveLun();
|
lun = GetEffectiveLun();
|
||||||
|
|
||||||
LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId());
|
LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId());
|
||||||
@ -355,7 +357,7 @@ void SCSIDEV::MsgOut()
|
|||||||
// Common Error Handling
|
// Common Error Handling
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERROR_CODES::status status)
|
void SCSIDEV::Error(sense_key sense_key, asc asc, status status)
|
||||||
{
|
{
|
||||||
// Get bus information
|
// Get bus information
|
||||||
ctrl.bus->Aquire();
|
ctrl.bus->Aquire();
|
||||||
@ -377,8 +379,10 @@ void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc, ERRO
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lun = GetEffectiveLun();
|
int lun = GetEffectiveLun();
|
||||||
if (!ctrl.unit[lun] || asc == ERROR_CODES::INVALID_LUN) {
|
if (!ctrl.unit[lun] || asc == INVALID_LUN) {
|
||||||
lun = 0;
|
lun = 0;
|
||||||
|
|
||||||
|
assert(ctrl.unit[lun]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sense_key || asc) {
|
if (sense_key || asc) {
|
||||||
@ -408,7 +412,9 @@ void SCSIDEV::Send()
|
|||||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length "
|
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(ctrl.offset) + ", length "
|
||||||
+ to_string(ctrl.length)).c_str());
|
+ to_string(ctrl.length)).c_str());
|
||||||
|
|
||||||
int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0]->GetSendDelay());
|
// TODO The delay has to be taken from ctrl.unit[lun], but as there are no Daynaport drivers for
|
||||||
|
// LUNs other than 0 this work-around works.
|
||||||
|
int len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, ctrl.unit[0] ? ctrl.unit[0]->GetSendDelay() : 0);
|
||||||
|
|
||||||
// If you cannot send all, move to status phase
|
// If you cannot send all, move to status phase
|
||||||
if (len != (int)ctrl.length) {
|
if (len != (int)ctrl.length) {
|
||||||
@ -896,7 +902,7 @@ bool SCSIDEV::XferOut(bool cont)
|
|||||||
scsi.is_byte_transfer = false;
|
scsi.is_byte_transfer = false;
|
||||||
|
|
||||||
PrimaryDevice *device = dynamic_cast<PrimaryDevice *>(ctrl.unit[GetEffectiveLun()]);
|
PrimaryDevice *device = dynamic_cast<PrimaryDevice *>(ctrl.unit[GetEffectiveLun()]);
|
||||||
if (device && ctrl.cmd[0] == scsi_defs::eCmdWrite6) {
|
if (device && ctrl.cmd[0] == scsi_command::eCmdWrite6) {
|
||||||
return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer);
|
return device->WriteBytes(ctrl.buffer, scsi.bytes_to_transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "controllers/sasidev_ctrl.h"
|
#include "controllers/sasidev_ctrl.h"
|
||||||
#include <map>
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
@ -67,9 +66,9 @@ public:
|
|||||||
bool IsSCSI() const override { return true; }
|
bool IsSCSI() const override { return true; }
|
||||||
|
|
||||||
// Common error handling
|
// Common error handling
|
||||||
void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
|
void Error(scsi_defs::sense_key sense_key = scsi_defs::sense_key::NO_SENSE,
|
||||||
ERROR_CODES::asc asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
scsi_defs::asc asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
||||||
ERROR_CODES::status status = ERROR_CODES::status::CHECK_CONDITION) override;
|
scsi_defs::status status = scsi_defs::status::CHECK_CONDITION) override;
|
||||||
|
|
||||||
void ScheduleShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; }
|
void ScheduleShutDown(rascsi_shutdown_mode shutdown_mode) { this->shutdown_mode = shutdown_mode; }
|
||||||
|
|
||||||
|
@ -96,9 +96,9 @@ static bool is_interface_up(const string& interface) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTapDriver::Init(const map<string, string>& const_params)
|
bool CTapDriver::Init(const unordered_map<string, string>& const_params)
|
||||||
{
|
{
|
||||||
map<string, string> params = const_params;
|
unordered_map<string, string> params = const_params;
|
||||||
if (params.count("interfaces")) {
|
if (params.count("interfaces")) {
|
||||||
LOGWARN("You are using the deprecated 'interfaces' parameter. "
|
LOGWARN("You are using the deprecated 'interfaces' parameter. "
|
||||||
"Provide the interface list and the IP address/netmask with the 'interface' and 'inet' parameters");
|
"Provide the interface list and the IP address/netmask with the 'interface' and 'inet' parameters");
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include <pcap/pcap.h>
|
#include <pcap/pcap.h>
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ private:
|
|||||||
CTapDriver();
|
CTapDriver();
|
||||||
~CTapDriver() {}
|
~CTapDriver() {}
|
||||||
|
|
||||||
bool Init(const map<string, string>&);
|
bool Init(const unordered_map<string, string>&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
set<Device *> Device::devices;
|
unordered_set<Device *> Device::devices;
|
||||||
|
|
||||||
Device::Device(const string& type)
|
Device::Device(const string& type)
|
||||||
{
|
{
|
||||||
@ -121,7 +121,7 @@ const string Device::GetParam(const string& key)
|
|||||||
return params.find(key) != params.end() ? params[key] : "";
|
return params.find(key) != params.end() ? params[key] : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::SetParams(const map<string, string>& params)
|
void Device::SetParams(const unordered_map<string, string>& params)
|
||||||
{
|
{
|
||||||
this->params = GetDefaultParams();
|
this->params = GetDefaultParams();
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -97,17 +97,17 @@ private:
|
|||||||
string revision;
|
string revision;
|
||||||
|
|
||||||
// The parameters the device was created with
|
// The parameters the device was created with
|
||||||
map<string, string> params;
|
unordered_map<string, string> params;
|
||||||
|
|
||||||
// The default parameters
|
// The default parameters
|
||||||
map<string, string> default_params;
|
unordered_map<string, string> default_params;
|
||||||
|
|
||||||
// Sense Key, ASC and ASCQ
|
// Sense Key, ASC and ASCQ
|
||||||
int status_code;
|
int status_code;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static set<Device *> devices;
|
static unordered_set<Device *> devices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ public:
|
|||||||
virtual ~Device();
|
virtual ~Device();
|
||||||
|
|
||||||
// Override for device specific initializations, to be called after all device properties have been set
|
// Override for device specific initializations, to be called after all device properties have been set
|
||||||
virtual bool Init(const map<string, string>&) { return true; };
|
virtual bool Init(const unordered_map<string, string>&) { return true; };
|
||||||
|
|
||||||
virtual bool Dispatch(SCSIDEV *) = 0;
|
virtual bool Dispatch(SCSIDEV *) = 0;
|
||||||
|
|
||||||
@ -169,11 +169,11 @@ public:
|
|||||||
bool SupportsParams() const { return supports_params; }
|
bool SupportsParams() const { return supports_params; }
|
||||||
bool SupportsFile() const { return !supports_params; }
|
bool SupportsFile() const { return !supports_params; }
|
||||||
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
|
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
|
||||||
const map<string, string> GetParams() const { return params; }
|
const unordered_map<string, string> GetParams() const { return params; }
|
||||||
const string GetParam(const string&);
|
const string GetParam(const string&);
|
||||||
void SetParams(const map<string, string>&);
|
void SetParams(const unordered_map<string, string>&);
|
||||||
const map<string, string> GetDefaultParams() const { return default_params; }
|
const unordered_map<string, string> GetDefaultParams() const { return default_params; }
|
||||||
void SetDefaultParams(const map<string, string>& default_params) { this->default_params = default_params; }
|
void SetDefaultParams(const unordered_map<string, string>& default_params) { this->default_params = default_params; }
|
||||||
|
|
||||||
int GetStatusCode() const { return status_code; }
|
int GetStatusCode() const { return status_code; }
|
||||||
void SetStatusCode(int);
|
void SetStatusCode(int);
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "device_factory.h"
|
#include "device_factory.h"
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include "host_services.h"
|
#include "host_services.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -86,12 +84,13 @@ string DeviceFactory::GetExtension(const string& filename) const
|
|||||||
return ext;
|
return ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
PbDeviceType DeviceFactory::GetTypeForFile(const string& filename)
|
PbDeviceType DeviceFactory::GetTypeForFile(const string& filename) const
|
||||||
{
|
{
|
||||||
string ext = GetExtension(filename);
|
string ext = GetExtension(filename);
|
||||||
|
|
||||||
if (extension_mapping.find(ext) != extension_mapping.end()) {
|
const auto& it = extension_mapping.find(ext);
|
||||||
return extension_mapping[ext];
|
if (it != extension_mapping.end()) {
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
else if (filename == "bridge") {
|
else if (filename == "bridge") {
|
||||||
return SCBR;
|
return SCBR;
|
||||||
@ -216,19 +215,19 @@ Device *DeviceFactory::CreateDevice(PbDeviceType type, const string& filename)
|
|||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
const set<uint32_t>& DeviceFactory::GetSectorSizes(const string& type)
|
const unordered_set<uint32_t>& DeviceFactory::GetSectorSizes(const string& type)
|
||||||
{
|
{
|
||||||
PbDeviceType t = UNDEFINED;
|
PbDeviceType t = UNDEFINED;
|
||||||
PbDeviceType_Parse(type, &t);
|
PbDeviceType_Parse(type, &t);
|
||||||
return sector_sizes[t];
|
return sector_sizes[t];
|
||||||
}
|
}
|
||||||
|
|
||||||
const set<uint64_t> DeviceFactory::GetCapacities(PbDeviceType type)
|
const unordered_set<uint64_t> DeviceFactory::GetCapacities(PbDeviceType type) const
|
||||||
{
|
{
|
||||||
set<uint64_t> keys;
|
unordered_set<uint64_t> keys;
|
||||||
|
|
||||||
for (const auto& geometry : geometries[type]) {
|
for (auto it = geometries.begin(); it != geometries.end(); ++it) {
|
||||||
keys.insert(geometry.first);
|
keys.insert(it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "rascsi_interface.pb.h"
|
#include "rascsi_interface.pb.h"
|
||||||
|
|
||||||
@ -28,31 +28,31 @@ class DeviceFactory
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DeviceFactory();
|
DeviceFactory();
|
||||||
~DeviceFactory() {};
|
~DeviceFactory() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DeviceFactory& instance();
|
static DeviceFactory& instance();
|
||||||
|
|
||||||
Device *CreateDevice(PbDeviceType, const string&);
|
Device *CreateDevice(PbDeviceType, const string&);
|
||||||
PbDeviceType GetTypeForFile(const string&);
|
PbDeviceType GetTypeForFile(const string&) const;
|
||||||
const set<uint32_t>& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; }
|
const unordered_set<uint32_t>& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; }
|
||||||
const set<uint32_t>& GetSectorSizes(const string&);
|
const unordered_set<uint32_t>& GetSectorSizes(const string&);
|
||||||
const set<uint64_t> GetCapacities(PbDeviceType);
|
const unordered_set<uint64_t> GetCapacities(PbDeviceType) const;
|
||||||
const map<string, string>& GetDefaultParams(PbDeviceType type) { return default_params[type]; }
|
const unordered_map<string, string>& GetDefaultParams(PbDeviceType type) { return default_params[type]; }
|
||||||
const list<string> GetNetworkInterfaces() const;
|
const list<string> GetNetworkInterfaces() const;
|
||||||
const map<string, PbDeviceType> GetExtensionMapping() const { return extension_mapping; }
|
const unordered_map<string, PbDeviceType> GetExtensionMapping() const { return extension_mapping; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
map<PbDeviceType, set<uint32_t>> sector_sizes;
|
unordered_map<PbDeviceType, unordered_set<uint32_t>> sector_sizes;
|
||||||
|
|
||||||
// Optional mapping of drive capacities to drive geometries
|
// Optional mapping of drive capacities to drive geometries
|
||||||
map<PbDeviceType, map<uint64_t, Geometry>> geometries;
|
unordered_map<PbDeviceType, unordered_map<uint64_t, Geometry>> geometries;
|
||||||
|
|
||||||
map<PbDeviceType, map<string, string>> default_params;
|
unordered_map<PbDeviceType, unordered_map<string, string>> default_params;
|
||||||
|
|
||||||
map<string, PbDeviceType> extension_mapping;
|
unordered_map<string, PbDeviceType> extension_mapping;
|
||||||
|
|
||||||
string GetExtension(const string&) const;
|
string GetExtension(const string&) const;
|
||||||
};
|
};
|
||||||
|
@ -85,7 +85,7 @@ bool Disk::Dispatch(SCSIDEV *controller)
|
|||||||
|
|
||||||
disk.is_medium_changed = false;
|
disk.is_medium_changed = false;
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::UNIT_ATTENTION, ERROR_CODES::asc::NOT_READY_TO_READY_CHANGE);
|
controller->Error(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,11 +207,11 @@ void Disk::ReadWriteLong10(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||||
if (ctrl->cmd[7] || ctrl->cmd[8]) {
|
if (ctrl->cmd[7] || ctrl->cmd[8]) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckBlockAddress(controller, RW10)) {
|
if (ValidateBlockAddress(controller, RW10)) {
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,11 +225,11 @@ void Disk::ReadWriteLong16(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||||
if (ctrl->cmd[12] || ctrl->cmd[13]) {
|
if (ctrl->cmd[12] || ctrl->cmd[13]) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckBlockAddress(controller, RW16)) {
|
if (ValidateBlockAddress(controller, RW16)) {
|
||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,11 +243,11 @@ void Disk::Write(SASIDEV *controller, uint64_t record)
|
|||||||
{
|
{
|
||||||
ctrl->length = WriteCheck(record);
|
ctrl->length = WriteCheck(record);
|
||||||
if (ctrl->length == 0) {
|
if (ctrl->length == 0) {
|
||||||
controller->Error(ERROR_CODES::sense_key::NOT_READY, ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION);
|
controller->Error(sense_key::NOT_READY, asc::NO_ADDITIONAL_SENSE_INFORMATION);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ctrl->length < 0) {
|
else if (ctrl->length < 0) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::WRITE_PROTECTED);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::WRITE_PROTECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ void Disk::StartStopUnit(SASIDEV *controller)
|
|||||||
void Disk::SendDiagnostic(SASIDEV *controller)
|
void Disk::SendDiagnostic(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!SendDiag(ctrl->cmd)) {
|
if (!SendDiag(ctrl->cmd)) {
|
||||||
controller->Error();
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,12 +380,15 @@ void Disk::SynchronizeCache16(SASIDEV *controller)
|
|||||||
|
|
||||||
void Disk::ReadDefectData10(SASIDEV *controller)
|
void Disk::ReadDefectData10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl->length = ReadDefectData10(ctrl->cmd, ctrl->buffer, ctrl->bufsize);
|
int allocation_length = (ctrl->cmd[7] << 8) | ctrl->cmd[8];
|
||||||
if (ctrl->length <= 4) {
|
if (allocation_length > 4) {
|
||||||
controller->Error();
|
allocation_length = 4;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The defect list is empty
|
||||||
|
memset(ctrl->buffer, 0, allocation_length);
|
||||||
|
ctrl->length = allocation_length;
|
||||||
|
|
||||||
controller->DataIn();
|
controller->DataIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,34 +678,6 @@ void Disk::AddVendorPage(map<int, vector<BYTE>>&, int, bool) const
|
|||||||
// Nothing to add by default
|
// Nothing to add by default
|
||||||
}
|
}
|
||||||
|
|
||||||
int Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf, int max_length)
|
|
||||||
{
|
|
||||||
// Get length, clear buffer
|
|
||||||
int length = (cdb[7] << 8) | cdb[8];
|
|
||||||
if (length > max_length) {
|
|
||||||
length = max_length;
|
|
||||||
}
|
|
||||||
memset(buf, 0, length);
|
|
||||||
|
|
||||||
// P/G/FORMAT
|
|
||||||
buf[1] = (cdb[1] & 0x18) | 5;
|
|
||||||
buf[3] = 8;
|
|
||||||
|
|
||||||
buf[4] = 0xff;
|
|
||||||
buf[5] = 0xff;
|
|
||||||
buf[6] = 0xff;
|
|
||||||
buf[7] = 0xff;
|
|
||||||
|
|
||||||
buf[8] = 0xff;
|
|
||||||
buf[9] = 0xff;
|
|
||||||
buf[10] = 0xff;
|
|
||||||
buf[11] = 0xff;
|
|
||||||
|
|
||||||
// no list
|
|
||||||
SetStatusCode(STATUS_NODEFECT);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FORMAT UNIT
|
// FORMAT UNIT
|
||||||
@ -868,17 +843,15 @@ bool Disk::StartStop(const DWORD *cdb)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Disk::SendDiag(const DWORD *cdb)
|
bool Disk::SendDiag(const DWORD *cdb) const
|
||||||
{
|
{
|
||||||
// Do not support PF bit
|
// Do not support PF bit
|
||||||
if (cdb[1] & 0x10) {
|
if (cdb[1] & 0x10) {
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not support parameter list
|
// Do not support parameter list
|
||||||
if ((cdb[3] != 0) || (cdb[4] != 0)) {
|
if ((cdb[3] != 0) || (cdb[4] != 0)) {
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -888,7 +861,7 @@ bool Disk::SendDiag(const DWORD *cdb)
|
|||||||
void Disk::ReadCapacity10(SASIDEV *controller)
|
void Disk::ReadCapacity10(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!CheckReady() || disk.blocks <= 0) {
|
if (!CheckReady() || disk.blocks <= 0) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,7 +890,7 @@ void Disk::ReadCapacity10(SASIDEV *controller)
|
|||||||
void Disk::ReadCapacity16(SASIDEV *controller)
|
void Disk::ReadCapacity16(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
if (!CheckReady() || disk.blocks <= 0) {
|
if (!CheckReady() || disk.blocks <= 0) {
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::MEDIUM_NOT_PRESENT);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -965,7 +938,7 @@ void Disk::ReadCapacity16_ReadLong16(SASIDEV *controller)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -996,7 +969,7 @@ void Disk::Release(SASIDEV *controller)
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode)
|
bool Disk::ValidateBlockAddress(SASIDEV *controller, access_mode mode)
|
||||||
{
|
{
|
||||||
uint64_t block = ctrl->cmd[2];
|
uint64_t block = ctrl->cmd[2];
|
||||||
block <<= 8;
|
block <<= 8;
|
||||||
@ -1021,7 +994,7 @@ bool Disk::CheckBlockAddress(SASIDEV *controller, access_mode mode)
|
|||||||
if (block > capacity) {
|
if (block > capacity) {
|
||||||
LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block "
|
LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block "
|
||||||
+ to_string(block)).c_str());
|
+ to_string(block)).c_str());
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1078,14 +1051,14 @@ 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);
|
LOGTRACE("%s READ/WRITE/VERIFY command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, count);
|
||||||
|
|
||||||
// Check capacity
|
// Check capacity
|
||||||
uint64_t capacity = GetBlockCount();
|
uint64_t capacity = GetBlockCount();
|
||||||
if (start > capacity || start + count > capacity) {
|
if (start > capacity || start + count > capacity) {
|
||||||
LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block "
|
LOGTRACE("%s", ("Capacity of " + to_string(capacity) + " blocks exceeded: Trying to access block "
|
||||||
+ to_string(start) + ", block count " + to_string(ctrl->blocks)).c_str());
|
+ to_string(start) + ", block count " + to_string(ctrl->blocks)).c_str());
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::LBA_OUT_OF_RANGE);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1106,7 +1079,7 @@ uint32_t Disk::GetSectorSizeInBytes() const
|
|||||||
|
|
||||||
void Disk::SetSectorSizeInBytes(uint32_t size, bool sasi)
|
void Disk::SetSectorSizeInBytes(uint32_t size, bool sasi)
|
||||||
{
|
{
|
||||||
set<uint32_t> sector_sizes = DeviceFactory::instance().GetSectorSizes(GetType());
|
unordered_set<uint32_t> sector_sizes = DeviceFactory::instance().GetSectorSizes(GetType());
|
||||||
if (!sector_sizes.empty() && sector_sizes.find(size) == sector_sizes.end()) {
|
if (!sector_sizes.empty() && sector_sizes.find(size) == sector_sizes.end()) {
|
||||||
throw io_exception("Invalid block size of " + to_string(size) + " bytes");
|
throw io_exception("Invalid block size of " + to_string(size) + " bytes");
|
||||||
}
|
}
|
||||||
@ -1153,7 +1126,7 @@ bool Disk::IsSectorSizeConfigurable() const
|
|||||||
return !sector_sizes.empty();
|
return !sector_sizes.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::SetSectorSizes(const set<uint32_t>& sector_sizes)
|
void Disk::SetSectorSizes(const unordered_set<uint32_t>& sector_sizes)
|
||||||
{
|
{
|
||||||
this->sector_sizes = sector_sizes;
|
this->sector_sizes = sector_sizes;
|
||||||
}
|
}
|
||||||
@ -1167,7 +1140,7 @@ bool Disk::SetConfiguredSectorSize(uint32_t configured_sector_size)
|
|||||||
{
|
{
|
||||||
DeviceFactory& device_factory = DeviceFactory::instance();
|
DeviceFactory& device_factory = DeviceFactory::instance();
|
||||||
|
|
||||||
set<uint32_t> sector_sizes = device_factory.GetSectorSizes(GetType());
|
unordered_set<uint32_t> sector_sizes = device_factory.GetSectorSizes(GetType());
|
||||||
if (sector_sizes.find(configured_sector_size) == sector_sizes.end()) {
|
if (sector_sizes.find(configured_sector_size) == sector_sizes.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1177,7 +1150,7 @@ bool Disk::SetConfiguredSectorSize(uint32_t configured_sector_size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk::SetGeometries(const map<uint64_t, Geometry>& geometries)
|
void Disk::SetGeometries(const unordered_map<uint64_t, Geometry>& geometries)
|
||||||
{
|
{
|
||||||
this->geometries = geometries;
|
this->geometries = geometries;
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
#include "interfaces/scsi_block_commands.h"
|
#include "interfaces/scsi_block_commands.h"
|
||||||
#include "mode_page_device.h"
|
#include "mode_page_device.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -39,11 +39,11 @@ private:
|
|||||||
enum access_mode { RW6, RW10, RW16 };
|
enum access_mode { RW6, RW10, RW16 };
|
||||||
|
|
||||||
// The supported configurable block sizes, empty if not configurable
|
// The supported configurable block sizes, empty if not configurable
|
||||||
set<uint32_t> sector_sizes;
|
unordered_set<uint32_t> sector_sizes;
|
||||||
uint32_t configured_sector_size;
|
uint32_t configured_sector_size;
|
||||||
|
|
||||||
// The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction
|
// The mapping of supported capacities to block sizes and block counts, empty if there is no capacity restriction
|
||||||
map<uint64_t, Geometry> geometries;
|
unordered_map<uint64_t, Geometry> geometries;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
|
uint32_t size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
|
||||||
@ -108,33 +108,30 @@ public:
|
|||||||
void Seek6(SASIDEV *);
|
void Seek6(SASIDEV *);
|
||||||
|
|
||||||
// Command helpers
|
// Command helpers
|
||||||
virtual int Inquiry(const DWORD *cdb, BYTE *buf) = 0; // INQUIRY command
|
virtual int WriteCheck(DWORD block);
|
||||||
virtual int WriteCheck(DWORD block); // WRITE check
|
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block);
|
||||||
virtual bool Write(const DWORD *cdb, const BYTE *buf, DWORD block); // WRITE command
|
bool StartStop(const DWORD *cdb);
|
||||||
bool StartStop(const DWORD *cdb); // START STOP UNIT command
|
bool SendDiag(const DWORD *cdb) const;
|
||||||
bool SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
|
|
||||||
|
|
||||||
virtual int Read(const DWORD *cdb, BYTE *buf, uint64_t block);
|
virtual int Read(const DWORD *cdb, BYTE *buf, uint64_t block);
|
||||||
int ReadDefectData10(const DWORD *, BYTE *, int);
|
|
||||||
|
|
||||||
uint32_t GetSectorSizeInBytes() const;
|
uint32_t GetSectorSizeInBytes() const;
|
||||||
void SetSectorSizeInBytes(uint32_t, bool);
|
void SetSectorSizeInBytes(uint32_t, bool);
|
||||||
uint32_t GetSectorSizeShiftCount() const;
|
uint32_t GetSectorSizeShiftCount() const;
|
||||||
void SetSectorSizeShiftCount(uint32_t);
|
void SetSectorSizeShiftCount(uint32_t);
|
||||||
bool IsSectorSizeConfigurable() const;
|
bool IsSectorSizeConfigurable() const;
|
||||||
set<uint32_t> GetSectorSizes() const;
|
unordered_set<uint32_t> GetSectorSizes() const;
|
||||||
void SetSectorSizes(const set<uint32_t>&);
|
void SetSectorSizes(const unordered_set<uint32_t>&);
|
||||||
uint32_t GetConfiguredSectorSize() const;
|
uint32_t GetConfiguredSectorSize() const;
|
||||||
bool SetConfiguredSectorSize(uint32_t);
|
bool SetConfiguredSectorSize(uint32_t);
|
||||||
void SetGeometries(const map<uint64_t, Geometry>&);
|
void SetGeometries(const unordered_map<uint64_t, Geometry>&);
|
||||||
bool SetGeometryForCapacity(uint64_t);
|
bool SetGeometryForCapacity(uint64_t);
|
||||||
uint64_t GetBlockCount() const;
|
uint64_t GetBlockCount() const;
|
||||||
void SetBlockCount(uint32_t);
|
void SetBlockCount(uint32_t);
|
||||||
bool CheckBlockAddress(SASIDEV *, access_mode);
|
|
||||||
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
|
|
||||||
void FlushCache();
|
void FlushCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
int ModeSense6(const DWORD *cdb, BYTE *buf);
|
||||||
int ModeSense10(const DWORD *cdb, BYTE *buf, int);
|
int ModeSense10(const DWORD *cdb, BYTE *buf, int);
|
||||||
virtual void SetDeviceParameters(BYTE *);
|
virtual void SetDeviceParameters(BYTE *);
|
||||||
@ -149,6 +146,7 @@ protected:
|
|||||||
disk_t disk;
|
disk_t disk;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Read(SASIDEV *, uint64_t);
|
void Read(SASIDEV *, uint64_t);
|
||||||
void Write(SASIDEV *, uint64_t);
|
void Write(SASIDEV *, uint64_t);
|
||||||
void Verify(SASIDEV *, uint64_t);
|
void Verify(SASIDEV *, uint64_t);
|
||||||
@ -156,4 +154,7 @@ private:
|
|||||||
void ReadWriteLong16(SASIDEV *);
|
void ReadWriteLong16(SASIDEV *);
|
||||||
void ReadCapacity16_ReadLong16(SASIDEV *);
|
void ReadCapacity16_ReadLong16(SASIDEV *);
|
||||||
bool Format(const DWORD *cdb);
|
bool Format(const DWORD *cdb);
|
||||||
|
|
||||||
|
bool ValidateBlockAddress(SASIDEV *, access_mode);
|
||||||
|
bool GetStartAndCount(SASIDEV *, uint64_t&, uint32_t&, access_mode);
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "scsi.h"
|
#include "scsi.h"
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class SASIDEV;
|
class SASIDEV;
|
||||||
class SCSIDEV;
|
class SCSIDEV;
|
||||||
@ -40,7 +40,7 @@ public:
|
|||||||
|
|
||||||
_command_t(const char* _name, void (T::*_execute)(U *)) : name(_name), execute(_execute) { };
|
_command_t(const char* _name, void (T::*_execute)(U *)) : name(_name), execute(_execute) { };
|
||||||
} command_t;
|
} command_t;
|
||||||
map<scsi_command, command_t*> commands;
|
unordered_map<scsi_command, command_t*> commands;
|
||||||
|
|
||||||
void AddCommand(scsi_command opcode, const char* name, void (T::*execute)(U *))
|
void AddCommand(scsi_command opcode, const char* name, void (T::*execute)(U *))
|
||||||
{
|
{
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include "file_support.h"
|
#include "file_support.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
map<string, id_set> FileSupport::reserved_files;
|
unordered_map<string, id_set> FileSupport::reserved_files;
|
||||||
|
|
||||||
void FileSupport::ReserveFile(const Filepath& path, int id, int lun)
|
void FileSupport::ReserveFile(const Filepath& path, int id, int lun)
|
||||||
{
|
{
|
||||||
@ -27,8 +25,9 @@ void FileSupport::UnreserveFile()
|
|||||||
|
|
||||||
bool FileSupport::GetIdsForReservedFile(const Filepath& path, int& id, int& unit)
|
bool FileSupport::GetIdsForReservedFile(const Filepath& path, int& id, int& unit)
|
||||||
{
|
{
|
||||||
if (reserved_files.find(path.GetPath()) != reserved_files.end()) {
|
const auto& it = reserved_files.find(path.GetPath());
|
||||||
const id_set ids = reserved_files[path.GetPath()];
|
if (it != reserved_files.end()) {
|
||||||
|
const id_set ids = it->second;
|
||||||
id = ids.first;
|
id = ids.first;
|
||||||
unit = ids.second;
|
unit = ids.second;
|
||||||
return true;
|
return true;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "filepath.h"
|
#include "filepath.h"
|
||||||
|
|
||||||
@ -25,20 +25,21 @@ private:
|
|||||||
Filepath diskpath;
|
Filepath diskpath;
|
||||||
|
|
||||||
// The list of image files in use and the IDs and LUNs using these files
|
// The list of image files in use and the IDs and LUNs using these files
|
||||||
static map<string, id_set> reserved_files;
|
static unordered_map<string, id_set> reserved_files;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FileSupport() {};
|
FileSupport() {}
|
||||||
virtual ~FileSupport() {};
|
virtual ~FileSupport() {}
|
||||||
|
|
||||||
void GetPath(Filepath& path) const { path = diskpath; }
|
void GetPath(Filepath& path) const { path = diskpath; }
|
||||||
void SetPath(const Filepath& path) { diskpath = path; }
|
void SetPath(const Filepath& path) { diskpath = path; }
|
||||||
static const map<string, id_set> GetReservedFiles(){ return reserved_files; }
|
|
||||||
static void SetReservedFiles(const map<string, id_set>& files_in_use) { FileSupport::reserved_files = files_in_use; }
|
|
||||||
void ReserveFile(const Filepath&, int, int);
|
void ReserveFile(const Filepath&, int, int);
|
||||||
void UnreserveFile();
|
void UnreserveFile();
|
||||||
|
|
||||||
|
static const unordered_map<string, id_set> GetReservedFiles() { return reserved_files; }
|
||||||
|
static void SetReservedFiles(const unordered_map<string, id_set>& files_in_use)
|
||||||
|
{ FileSupport::reserved_files = files_in_use; }
|
||||||
static bool GetIdsForReservedFile(const Filepath&, int&, int&);
|
static bool GetIdsForReservedFile(const Filepath&, int&, int&);
|
||||||
static void UnreserveAll();
|
static void UnreserveAll();
|
||||||
|
|
||||||
|
@ -57,10 +57,10 @@ void HostServices::TestUnitReady(SCSIDEV *controller)
|
|||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
int HostServices::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> HostServices::Inquiry() const
|
||||||
{
|
{
|
||||||
// Processor device, SPC-5, not removable
|
// Processor device, SPC-5, not removable
|
||||||
return PrimaryDevice::Inquiry(3, 7, false, cdb, buf);
|
return PrimaryDevice::Inquiry(3, 7, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostServices::StartStopUnit(SCSIDEV *controller)
|
void HostServices::StartStopUnit(SCSIDEV *controller)
|
||||||
@ -96,7 +96,7 @@ void HostServices::StartStopUnit(SCSIDEV *controller)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf)
|
int HostServices::ModeSense6(const DWORD *cdb, BYTE *buf)
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
|
|
||||||
virtual bool Dispatch(SCSIDEV *) override;
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
int Inquiry(const DWORD *, BYTE *) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
void TestUnitReady(SCSIDEV *);
|
void TestUnitReady(SCSIDEV *);
|
||||||
void StartStopUnit(SCSIDEV *);
|
void StartStopUnit(SCSIDEV *);
|
||||||
|
|
||||||
|
@ -45,12 +45,22 @@ void PrimaryDevice::TestUnitReady(SASIDEV *controller)
|
|||||||
|
|
||||||
void PrimaryDevice::Inquiry(SASIDEV *controller)
|
void PrimaryDevice::Inquiry(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
ctrl->length = Inquiry(ctrl->cmd, ctrl->buffer);
|
// EVPD and page code check
|
||||||
if (ctrl->length <= 0) {
|
if ((ctrl->cmd[1] & 0x01) || ctrl->cmd[2]) {
|
||||||
controller->Error();
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<BYTE> buf = Inquiry();
|
||||||
|
|
||||||
|
size_t allocation_length = ctrl->cmd[4] + (ctrl->cmd[3] << 8);
|
||||||
|
if (allocation_length > buf.size()) {
|
||||||
|
allocation_length = buf.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctrl->buffer, buf.data(), allocation_length);
|
||||||
|
ctrl->length = allocation_length;
|
||||||
|
|
||||||
int lun = controller->GetEffectiveLun();
|
int lun = controller->GetEffectiveLun();
|
||||||
|
|
||||||
// Report if the device does not support the requested LUN
|
// Report if the device does not support the requested LUN
|
||||||
@ -66,27 +76,25 @@ void PrimaryDevice::Inquiry(SASIDEV *controller)
|
|||||||
|
|
||||||
void PrimaryDevice::ReportLuns(SASIDEV *controller)
|
void PrimaryDevice::ReportLuns(SASIDEV *controller)
|
||||||
{
|
{
|
||||||
BYTE *buf = ctrl->buffer;
|
|
||||||
|
|
||||||
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
int allocation_length = (ctrl->cmd[6] << 24) + (ctrl->cmd[7] << 16) + (ctrl->cmd[8] << 8) + ctrl->cmd[9];
|
||||||
|
|
||||||
|
BYTE *buf = ctrl->buffer;
|
||||||
memset(buf, 0, allocation_length);
|
memset(buf, 0, allocation_length);
|
||||||
|
|
||||||
// Count number of available LUNs for the current device
|
int size = 0;
|
||||||
int luns;
|
for (int lun = 0; lun < controller->GetCtrl()->device->GetSupportedLuns(); lun++) {
|
||||||
for (luns = 0; luns < controller->GetCtrl()->device->GetSupportedLuns(); luns++) {
|
if (controller->GetCtrl()->unit[lun]) {
|
||||||
if (!controller->GetCtrl()->unit[luns]) {
|
size += 8;
|
||||||
break;
|
buf[size + 7] = lun;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LUN list length, 8 bytes per LUN
|
buf[2] = size >> 8;
|
||||||
// SCSI standard: The contents of the LUN LIST LENGTH field are not altered based on the allocation length
|
buf[3] = size;
|
||||||
buf[0] = (luns * 8) >> 24;
|
|
||||||
buf[1] = (luns * 8) >> 16;
|
|
||||||
buf[2] = (luns * 8) >> 8;
|
|
||||||
buf[3] = luns * 8;
|
|
||||||
|
|
||||||
ctrl->length = allocation_length < 8 + luns * 8 ? allocation_length : 8 + luns * 8;
|
size += 8;
|
||||||
|
|
||||||
|
ctrl->length = allocation_length < size ? allocation_length : size;
|
||||||
|
|
||||||
controller->DataIn();
|
controller->DataIn();
|
||||||
}
|
}
|
||||||
@ -101,12 +109,21 @@ void PrimaryDevice::RequestSense(SASIDEV *controller)
|
|||||||
// LUN 0 can be assumed to be present (required to call RequestSense() below)
|
// LUN 0 can be assumed to be present (required to call RequestSense() below)
|
||||||
lun = 0;
|
lun = 0;
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN);
|
||||||
ctrl->status = 0x00;
|
ctrl->status = 0x00;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl->length = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(ctrl->cmd, ctrl->buffer);
|
size_t allocation_length = ctrl->cmd[4];
|
||||||
assert(ctrl->length > 0);
|
|
||||||
|
vector<BYTE> buf = ((PrimaryDevice *)ctrl->unit[lun])->RequestSense(allocation_length);
|
||||||
|
|
||||||
|
if (allocation_length > buf.size()) {
|
||||||
|
allocation_length = buf.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctrl->buffer, buf.data(), allocation_length);
|
||||||
|
ctrl->length = allocation_length;
|
||||||
|
|
||||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, ctrl->status, ctrl->buffer[2], ctrl->buffer[12]);
|
||||||
|
|
||||||
@ -144,19 +161,9 @@ bool PrimaryDevice::CheckReady()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DWORD *cdb, BYTE *buf)
|
vector<BYTE> PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable) const
|
||||||
{
|
{
|
||||||
// EVPD and page code check
|
vector<BYTE> buf = vector<BYTE>(0x1F + 5);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
// Basic data
|
||||||
// buf[0] ... SCSI Device type
|
// buf[0] ... SCSI Device type
|
||||||
@ -164,51 +171,39 @@ int PrimaryDevice::Inquiry(int type, int scsi_level, bool is_removable, const DW
|
|||||||
// buf[2] ... SCSI-2 compliant command system
|
// buf[2] ... SCSI-2 compliant command system
|
||||||
// buf[3] ... SCSI-2 compliant Inquiry response
|
// buf[3] ... SCSI-2 compliant Inquiry response
|
||||||
// buf[4] ... Inquiry additional data
|
// buf[4] ... Inquiry additional data
|
||||||
memset(buf, 0, allocation_length);
|
|
||||||
buf[0] = type;
|
buf[0] = type;
|
||||||
buf[1] = is_removable ? 0x80 : 0x00;
|
buf[1] = is_removable ? 0x80 : 0x00;
|
||||||
buf[2] = scsi_level;
|
buf[2] = scsi_level;
|
||||||
// Response data format is SCSI-2 for devices supporting SCSI-2 or newer, otherwise it is SCSI-1-CCS
|
// 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[3] = scsi_level >= 2 ? 2 : 1;
|
||||||
buf[4] = 0x1F;
|
buf[4] = 0x1F;
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
// Padded vendor, product, revision
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
||||||
}
|
|
||||||
|
|
||||||
return allocation_length;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PrimaryDevice::RequestSense(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> PrimaryDevice::RequestSense(int)
|
||||||
{
|
{
|
||||||
// Return not ready only if there are no errors
|
// Return not ready only if there are no errors
|
||||||
if (GetStatusCode() == STATUS_NOERROR && !IsReady()) {
|
if (GetStatusCode() == STATUS_NOERROR && !IsReady()) {
|
||||||
SetStatusCode(STATUS_NOTREADY);
|
SetStatusCode(STATUS_NOTREADY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size determination (according to allocation length)
|
|
||||||
int size = (int)cdb[4];
|
|
||||||
assert(size >= 0 && size < 0x100);
|
|
||||||
|
|
||||||
// For SCSI-1, transfer 4 bytes when the size is 0
|
|
||||||
if (size == 0) {
|
|
||||||
size = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the buffer
|
|
||||||
memset(buf, 0, size);
|
|
||||||
|
|
||||||
// Set 18 bytes including extended sense data
|
// Set 18 bytes including extended sense data
|
||||||
|
|
||||||
|
vector<BYTE> buf(18);
|
||||||
|
|
||||||
// Current error
|
// Current error
|
||||||
buf[0] = 0x70;
|
buf[0] = 0x70;
|
||||||
|
|
||||||
buf[2] = (BYTE)(GetStatusCode() >> 16);
|
buf[2] = GetStatusCode() >> 16;
|
||||||
buf[7] = 10;
|
buf[7] = 10;
|
||||||
buf[12] = (BYTE)(GetStatusCode() >> 8);
|
buf[12] = GetStatusCode() >> 8;
|
||||||
buf[13] = (BYTE)GetStatusCode();
|
buf[13] = GetStatusCode();
|
||||||
|
|
||||||
return size;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrimaryDevice::WriteBytes(BYTE *buf, uint32_t length)
|
bool PrimaryDevice::WriteBytes(BYTE *buf, uint32_t length)
|
||||||
|
@ -34,14 +34,14 @@ public:
|
|||||||
void SetCtrl(SASIDEV::ctrl_t *ctrl) { this->ctrl = ctrl; }
|
void SetCtrl(SASIDEV::ctrl_t *ctrl) { this->ctrl = ctrl; }
|
||||||
|
|
||||||
bool CheckReady();
|
bool CheckReady();
|
||||||
virtual int Inquiry(const DWORD *, BYTE *) = 0;
|
virtual vector<BYTE> Inquiry() const = 0;
|
||||||
virtual int RequestSense(const DWORD *, BYTE *);
|
virtual vector<BYTE> RequestSense(int);
|
||||||
virtual bool WriteBytes(BYTE *, uint32_t);
|
virtual bool WriteBytes(BYTE *, uint32_t);
|
||||||
virtual int GetSendDelay() { return BUS::SEND_NO_DELAY; }
|
virtual int GetSendDelay() const { return BUS::SEND_NO_DELAY; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int Inquiry(int, int, bool, const DWORD *, BYTE *);
|
vector<BYTE> Inquiry(int, int, bool) const;
|
||||||
|
|
||||||
SASIDEV::ctrl_t *ctrl;
|
SASIDEV::ctrl_t *ctrl;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
SASIHD::SASIHD(const set<uint32_t>& sector_sizes) : Disk("SAHD")
|
SASIHD::SASIHD(const unordered_set<uint32_t>& sector_sizes) : Disk("SAHD")
|
||||||
{
|
{
|
||||||
SetSectorSizes(sector_sizes);
|
SetSectorSizes(sector_sizes);
|
||||||
}
|
}
|
||||||
@ -81,27 +81,20 @@ void SASIHD::Open(const Filepath& path)
|
|||||||
FileSupport::SetPath(path);
|
FileSupport::SetPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SASIHD::Inquiry(const DWORD* /*cdb*/, BYTE* /*buf*/)
|
vector<BYTE> SASIHD::Inquiry() const
|
||||||
{
|
{
|
||||||
SetStatusCode(STATUS_INVALIDCMD);
|
assert(false);
|
||||||
return 0;
|
return vector<BYTE>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SASIHD::RequestSense(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SASIHD::RequestSense(int allocation_length)
|
||||||
{
|
{
|
||||||
// Size decision
|
// Transfer 4 bytes when size is 0 (Shugart Associates System Interface specification)
|
||||||
int size = (int)cdb[4];
|
vector<BYTE> buf(allocation_length ? allocation_length : 4);
|
||||||
assert(size >= 0 && size < 0x100);
|
|
||||||
|
|
||||||
// Transfer 4 bytes when size 0 (Shugart Associates System Interface specification)
|
|
||||||
if (size == 0) {
|
|
||||||
size = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SASI fixed to non-extended format
|
// SASI fixed to non-extended format
|
||||||
memset(buf, 0, size);
|
|
||||||
buf[0] = (BYTE)(GetStatusCode() >> 16);
|
buf[0] = (BYTE)(GetStatusCode() >> 16);
|
||||||
buf[1] = (BYTE)(GetLun() << 5);
|
buf[1] = (BYTE)(GetLun() << 5);
|
||||||
|
|
||||||
return size;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,12 @@
|
|||||||
class SASIHD : public Disk, public FileSupport
|
class SASIHD : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SASIHD(const set<uint32_t>&);
|
SASIHD(const unordered_set<uint32_t>&);
|
||||||
~SASIHD() {}
|
~SASIHD() {}
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath&) override;
|
||||||
|
|
||||||
// Commands
|
vector<BYTE> RequestSense(int) override;
|
||||||
int RequestSense(const DWORD *cdb, BYTE *buf) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
|
||||||
};
|
};
|
||||||
|
@ -64,7 +64,7 @@ bool SCSIDaynaPort::Dispatch(SCSIDEV *controller)
|
|||||||
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIDaynaPort::Init(const map<string, string>& params)
|
bool SCSIDaynaPort::Init(const unordered_map<string, string>& params)
|
||||||
{
|
{
|
||||||
SetParams(params);
|
SetParams(params);
|
||||||
|
|
||||||
@ -112,10 +112,10 @@ void SCSIDaynaPort::Open(const Filepath& path)
|
|||||||
m_tap->OpenDump(path);
|
m_tap->OpenDump(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIDaynaPort::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSIDaynaPort::Inquiry() const
|
||||||
{
|
{
|
||||||
// Processor device, SCSI-2, not removable
|
// Processor device, SCSI-2, not removable
|
||||||
return PrimaryDevice::Inquiry(3, 2, false, cdb, buf);
|
return PrimaryDevice::Inquiry(3, 2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -444,7 +444,7 @@ void SCSIDaynaPort::Read6(SASIDEV *controller)
|
|||||||
// generated by the DaynaPort driver so ignore them
|
// generated by the DaynaPort driver so ignore them
|
||||||
if (ctrl->cmd[5] != 0xc0 && ctrl->cmd[5] != 0x80) {
|
if (ctrl->cmd[5] != 0xc0 && ctrl->cmd[5] != 0x80) {
|
||||||
LOGTRACE("%s Control value %d, (%04X), returning invalid CDB", __PRETTY_FUNCTION__, ctrl->cmd[5], ctrl->cmd[5]);
|
LOGTRACE("%s Control value %d, (%04X), returning invalid CDB", __PRETTY_FUNCTION__, ctrl->cmd[5], ctrl->cmd[5]);
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +584,7 @@ void SCSIDaynaPort::EnableInterface(SASIDEV *controller)
|
|||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIDaynaPort::GetSendDelay()
|
int SCSIDaynaPort::GetSendDelay() const
|
||||||
{
|
{
|
||||||
// The Daynaport needs to have a delay after the size/flags field
|
// The Daynaport needs to have a delay after the size/flags field
|
||||||
// of the read response. In the MacOS driver, it looks like the
|
// of the read response. In the MacOS driver, it looks like the
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "ctapdriver.h"
|
#include "ctapdriver.h"
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -46,11 +45,11 @@ public:
|
|||||||
SCSIDaynaPort();
|
SCSIDaynaPort();
|
||||||
~SCSIDaynaPort();
|
~SCSIDaynaPort();
|
||||||
|
|
||||||
bool Init(const map<string, string>&) override;
|
bool Init(const unordered_map<string, string>&) override;
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buffer) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override;
|
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override;
|
||||||
bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) override;
|
bool Write(const DWORD *cdb, const BYTE *buf, DWORD block) override;
|
||||||
int WriteCheck(DWORD block) override; // WRITE check
|
int WriteCheck(DWORD block) override; // WRITE check
|
||||||
@ -67,7 +66,7 @@ public:
|
|||||||
void SetInterfaceMode(SASIDEV *);
|
void SetInterfaceMode(SASIDEV *);
|
||||||
void SetMcastAddr(SASIDEV *);
|
void SetMcastAddr(SASIDEV *);
|
||||||
void EnableInterface(SASIDEV *);
|
void EnableInterface(SASIDEV *);
|
||||||
int GetSendDelay() override;
|
int GetSendDelay() const override;
|
||||||
|
|
||||||
bool Dispatch(SCSIDEV *) override;
|
bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ SCSIBR::~SCSIBR()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIBR::Init(const map<string, string>& params)
|
bool SCSIBR::Init(const unordered_map<string, string>& params)
|
||||||
{
|
{
|
||||||
SetParams(params);
|
SetParams(params);
|
||||||
|
|
||||||
@ -99,32 +99,16 @@ bool SCSIBR::Dispatch(SCSIDEV *controller)
|
|||||||
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
vector<BYTE> SCSIBR::Inquiry() const
|
||||||
//
|
|
||||||
// INQUIRY
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
|
||||||
{
|
{
|
||||||
// EVPD check
|
// Communications device, SCSI-2, not removable
|
||||||
if (cdb[1] & 0x01) {
|
vector<BYTE> b = PrimaryDevice::Inquiry(9, 2, false);
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
// The bridge returns 6 more additional bytes than the other devices
|
||||||
// buf[0] ... Communication Device
|
vector<BYTE> buf = vector<BYTE>(0x1F + 8 + 5);
|
||||||
// buf[2] ... SCSI-2 compliant command system
|
memcpy(buf.data(), b.data(), b.size());
|
||||||
// buf[3] ... SCSI-2 compliant Inquiry response
|
|
||||||
// buf[4] ... Inquiry additional data
|
|
||||||
memset(buf, 0, 8);
|
|
||||||
buf[0] = 0x09;
|
|
||||||
buf[2] = 0x02;
|
|
||||||
buf[3] = 0x02;
|
|
||||||
buf[4] = 0x1F + 8; // required + 8 byte extension
|
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
buf[4] = 0x1F + 8;
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
|
||||||
|
|
||||||
// Optional function valid flag
|
// Optional function valid flag
|
||||||
buf[36] = '0';
|
buf[36] = '0';
|
||||||
@ -137,16 +121,7 @@ int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
// CFileSys Enable
|
// CFileSys Enable
|
||||||
buf[38] = '1';
|
buf[38] = '1';
|
||||||
|
|
||||||
// Size of data that can be returned
|
return buf;
|
||||||
int size = (buf[4] + 5);
|
|
||||||
|
|
||||||
// Limit if the other buffer is small
|
|
||||||
if (size > (int)cdb[4]) {
|
|
||||||
size = (int)cdb[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIBR::TestUnitReady(SASIDEV *controller)
|
void SCSIBR::TestUnitReady(SASIDEV *controller)
|
||||||
|
@ -36,13 +36,13 @@ public:
|
|||||||
SCSIBR();
|
SCSIBR();
|
||||||
~SCSIBR();
|
~SCSIBR();
|
||||||
|
|
||||||
bool Init(const map<string, string>&) override;
|
bool Init(const unordered_map<string, string>&) override;
|
||||||
bool Dispatch(SCSIDEV *) override;
|
bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override; // INQUIRY command
|
vector<BYTE> Inquiry() const override;
|
||||||
int GetMessage10(const DWORD *cdb, BYTE *buf); // GET MESSAGE10 command
|
int GetMessage10(const DWORD *cdb, BYTE *buf);
|
||||||
bool SendMessage10(const DWORD *cdb, BYTE *buf); // SEND MESSAGE10 command
|
bool SendMessage10(const DWORD *cdb, BYTE *buf);
|
||||||
void TestUnitReady(SASIDEV *) override;
|
void TestUnitReady(SASIDEV *) override;
|
||||||
void GetMessage10(SASIDEV *);
|
void GetMessage10(SASIDEV *);
|
||||||
void SendMessage10(SASIDEV *);
|
void SendMessage10(SASIDEV *);
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include "controllers/scsidev_ctrl.h"
|
#include "controllers/scsidev_ctrl.h"
|
||||||
#include "../rasutil.h"
|
#include "../rasutil.h"
|
||||||
#include "scsi_printer.h"
|
#include "scsi_printer.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define NOT_RESERVED -2
|
#define NOT_RESERVED -2
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ SCSIPrinter::~SCSIPrinter()
|
|||||||
Cleanup();
|
Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIPrinter::Init(const map<string, string>& params)
|
bool SCSIPrinter::Init(const unordered_map<string, string>& params)
|
||||||
{
|
{
|
||||||
SetParams(params);
|
SetParams(params);
|
||||||
|
|
||||||
@ -104,10 +103,10 @@ void SCSIPrinter::TestUnitReady(SCSIDEV *controller)
|
|||||||
controller->Status();
|
controller->Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIPrinter::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSIPrinter::Inquiry() const
|
||||||
{
|
{
|
||||||
// Printer device, SCSI-2, not removable
|
// Printer device, SCSI-2, not removable
|
||||||
return PrimaryDevice::Inquiry(2, 2, false, cdb, buf);
|
return PrimaryDevice::Inquiry(2, 2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIPrinter::ReserveUnit(SCSIDEV *controller)
|
void SCSIPrinter::ReserveUnit(SCSIDEV *controller)
|
||||||
@ -172,7 +171,7 @@ void SCSIPrinter::Print(SCSIDEV *controller)
|
|||||||
if (length > (uint32_t)ctrl->bufsize) {
|
if (length > (uint32_t)ctrl->bufsize) {
|
||||||
LOGERROR("Transfer buffer overflow");
|
LOGERROR("Transfer buffer overflow");
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,8 +278,8 @@ bool SCSIPrinter::CheckReservation(SCSIDEV *controller)
|
|||||||
LOGTRACE("Unknown initiator tries to access reserved device ID %d, LUN %d", GetId(), GetLun());
|
LOGTRACE("Unknown initiator tries to access reserved device ID %d, LUN %d", GetId(), GetLun());
|
||||||
}
|
}
|
||||||
|
|
||||||
controller->Error(ERROR_CODES::sense_key::ABORTED_COMMAND, ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
controller->Error(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION,
|
||||||
ERROR_CODES::status::RESERVATION_CONFLICT);
|
status::RESERVATION_CONFLICT);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "interfaces/scsi_printer_commands.h"
|
#include "interfaces/scsi_printer_commands.h"
|
||||||
#include "primary_device.h"
|
#include "primary_device.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -29,9 +29,9 @@ public:
|
|||||||
|
|
||||||
virtual bool Dispatch(SCSIDEV *) override;
|
virtual bool Dispatch(SCSIDEV *) override;
|
||||||
|
|
||||||
bool Init(const map<string, string>&);
|
bool Init(const unordered_map<string, string>&);
|
||||||
|
|
||||||
int Inquiry(const DWORD *, BYTE *) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
void TestUnitReady(SCSIDEV *);
|
void TestUnitReady(SCSIDEV *);
|
||||||
void ReserveUnit(SCSIDEV *);
|
void ReserveUnit(SCSIDEV *);
|
||||||
void ReleaseUnit(SCSIDEV *);
|
void ReleaseUnit(SCSIDEV *);
|
||||||
|
@ -176,7 +176,7 @@ bool CDTrack::IsAudio() const
|
|||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
SCSICD::SCSICD(const set<uint32_t>& sector_sizes) : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
|
SCSICD::SCSICD(const unordered_set<uint32_t>& sector_sizes) : Disk("SCCD"), ScsiMmcCommands(), FileSupport()
|
||||||
{
|
{
|
||||||
SetSectorSizes(sector_sizes);
|
SetSectorSizes(sector_sizes);
|
||||||
|
|
||||||
@ -397,32 +397,10 @@ void SCSICD::ReadToc(SASIDEV *controller)
|
|||||||
controller->DataIn();
|
controller->DataIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSICD::Inquiry() const
|
||||||
{
|
{
|
||||||
// EVPD check
|
// CD-ROM device, SCSI-2, removable
|
||||||
if (cdb[1] & 0x01) {
|
return PrimaryDevice::Inquiry(5, 2, true);
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
|
||||||
// buf[0] ... CD-ROM Device
|
|
||||||
// buf[1] ... Removable
|
|
||||||
// buf[2] ... SCSI-2 compliant command system
|
|
||||||
// buf[3] ... SCSI-2 compliant Inquiry response
|
|
||||||
// buf[4] ... Inquiry additional data
|
|
||||||
memset(buf, 0, 8);
|
|
||||||
buf[0] = 0x05;
|
|
||||||
buf[1] = 0x80;
|
|
||||||
buf[2] = 0x02;
|
|
||||||
buf[3] = 0x02;
|
|
||||||
buf[4] = 0x1F;
|
|
||||||
|
|
||||||
// Fill with blanks
|
|
||||||
memset(&buf[8], 0x20, buf[4] - 3);
|
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following code worked with the modified Apple CD-ROM drivers. Need to
|
// The following code worked with the modified Apple CD-ROM drivers. Need to
|
||||||
@ -446,16 +424,6 @@ int SCSICD::Inquiry(const DWORD *cdb, BYTE *buf)
|
|||||||
// //strcpy(&buf[35],"A1.9a");
|
// //strcpy(&buf[35],"A1.9a");
|
||||||
// buf[36]=0x20;
|
// buf[36]=0x20;
|
||||||
// memcpy(&buf[37],"1999/01/01",10);
|
// memcpy(&buf[37],"1999/01/01",10);
|
||||||
|
|
||||||
// Size of data that can be returned
|
|
||||||
int size = (buf[4] + 5);
|
|
||||||
|
|
||||||
// Limit if the other buffer is small
|
|
||||||
if (size > (int)cdb[4]) {
|
|
||||||
size = (int)cdb[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSICD::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
void SCSICD::AddModePages(map<int, vector<BYTE>>& pages, int page, bool changeable) const
|
||||||
@ -658,12 +626,12 @@ void SCSICD::GetEventStatusNotification(SASIDEV *controller)
|
|||||||
{
|
{
|
||||||
if (!(ctrl->cmd[1] & 0x01)) {
|
if (!(ctrl->cmd[1] & 0x01)) {
|
||||||
// Asynchronous notification is optional and not supported by rascsi
|
// Asynchronous notification is optional and not supported by rascsi
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGTRACE("Received request for event polling, which is currently not supported");
|
LOGTRACE("Received request for event polling, which is currently not supported");
|
||||||
controller->Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_FIELD_IN_CDB);
|
controller->Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -76,7 +76,7 @@ public:
|
|||||||
TrackMax = 96 // Maximum number of tracks
|
TrackMax = 96 // Maximum number of tracks
|
||||||
};
|
};
|
||||||
|
|
||||||
SCSICD(const set<uint32_t>&);
|
SCSICD(const unordered_set<uint32_t>&);
|
||||||
~SCSICD();
|
~SCSICD();
|
||||||
|
|
||||||
bool Dispatch(SCSIDEV *) override;
|
bool Dispatch(SCSIDEV *) override;
|
||||||
@ -84,9 +84,9 @@ public:
|
|||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override; // INQUIRY command
|
vector<BYTE> Inquiry() const override;
|
||||||
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override; // READ command
|
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override;
|
||||||
int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
|
int ReadToc(const DWORD *cdb, BYTE *buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
SCSIHD::SCSIHD(const set<uint32_t>& sector_sizes, bool removable) : Disk(removable ? "SCRM" : "SCHD")
|
SCSIHD::SCSIHD(const unordered_set<uint32_t>& sector_sizes, bool removable) : Disk(removable ? "SCRM" : "SCHD")
|
||||||
{
|
{
|
||||||
SetSectorSizes(sector_sizes);
|
SetSectorSizes(sector_sizes);
|
||||||
}
|
}
|
||||||
@ -98,38 +98,10 @@ void SCSIHD::Open(const Filepath& path)
|
|||||||
FinalizeSetup(path, size);
|
FinalizeSetup(path, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIHD::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSIHD::Inquiry() const
|
||||||
{
|
{
|
||||||
// EVPD check
|
// Direct access device, SCSI-2
|
||||||
if (cdb[1] & 0x01) {
|
return PrimaryDevice::Inquiry(0, 2, IsRemovable());
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
|
||||||
// buf[0] ... Direct Access Device
|
|
||||||
// buf[1] ... Bit 7 set means removable
|
|
||||||
// buf[2] ... SCSI-2 compliant command system
|
|
||||||
// buf[3] ... SCSI-2 compliant Inquiry response
|
|
||||||
// buf[4] ... Inquiry additional data
|
|
||||||
memset(buf, 0, 8);
|
|
||||||
buf[1] = IsRemovable() ? 0x80 : 0x00;
|
|
||||||
buf[2] = 0x02;
|
|
||||||
buf[3] = 0x02;
|
|
||||||
buf[4] = 0x1F;
|
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
|
||||||
|
|
||||||
// Size of data that can be returned
|
|
||||||
int size = (buf[4] + 5);
|
|
||||||
|
|
||||||
// Limit if the other buffer is small
|
|
||||||
if (size > (int)cdb[4]) {
|
|
||||||
size = (int)cdb[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
bool SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
|
||||||
@ -221,7 +193,7 @@ void SCSIHD::AddVendorPage(map<int, vector<BYTE>>& pages, int page, bool changea
|
|||||||
|
|
||||||
// No changeable area
|
// No changeable area
|
||||||
if (!changeable) {
|
if (!changeable) {
|
||||||
memcpy(&buf.data()[0xa], "APPLE COMPUTER, INC.", 20);
|
memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
pages[48] = buf;
|
pages[48] = buf;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
class SCSIHD : public Disk, public FileSupport
|
class SCSIHD : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIHD(const set<uint32_t>&, bool);
|
SCSIHD(const unordered_set<uint32_t>&, bool);
|
||||||
virtual ~SCSIHD() {}
|
virtual ~SCSIHD() {}
|
||||||
|
|
||||||
void FinalizeSetup(const Filepath&, off_t);
|
void FinalizeSetup(const Filepath&, off_t);
|
||||||
@ -31,7 +31,7 @@ public:
|
|||||||
virtual void Open(const Filepath&) override;
|
virtual void Open(const Filepath&) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
virtual int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
virtual vector<BYTE> Inquiry() const override;
|
||||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||||
|
|
||||||
void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const override;
|
void AddVendorPage(map<int, vector<BYTE>>&, int, bool) const override;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
SCSIHD_NEC::SCSIHD_NEC(const set<uint32_t>& sector_sizes) : SCSIHD(sector_sizes, false)
|
SCSIHD_NEC::SCSIHD_NEC(const unordered_set<uint32_t>& sector_sizes) : SCSIHD(sector_sizes, false)
|
||||||
{
|
{
|
||||||
// Work initialization
|
// Work initialization
|
||||||
cylinders = 0;
|
cylinders = 0;
|
||||||
@ -135,15 +135,10 @@ void SCSIHD_NEC::Open(const Filepath& path)
|
|||||||
FinalizeSetup(path, size);
|
FinalizeSetup(path, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIHD_NEC::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSIHD_NEC::Inquiry() const
|
||||||
{
|
{
|
||||||
int size = SCSIHD::Inquiry(cdb, buf);
|
// Direct access device, SCSI-1-CCS, not removable
|
||||||
|
return PrimaryDevice::Inquiry(0, 1, false);
|
||||||
// This drive is a SCSI-1 SCCS drive
|
|
||||||
buf[2] = 0x01;
|
|
||||||
buf[3] = 0x01;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIHD_NEC::AddErrorPage(map<int, vector<BYTE>>& pages, bool) const
|
void SCSIHD_NEC::AddErrorPage(map<int, vector<BYTE>>& pages, bool) const
|
||||||
|
@ -25,13 +25,13 @@
|
|||||||
class SCSIHD_NEC : public SCSIHD
|
class SCSIHD_NEC : public SCSIHD
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIHD_NEC(const set<uint32_t>&);
|
SCSIHD_NEC(const unordered_set<uint32_t>&);
|
||||||
~SCSIHD_NEC() {}
|
~SCSIHD_NEC() {}
|
||||||
|
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
|
|
||||||
void AddErrorPage(map<int, vector<BYTE>>&, bool) const override;
|
void AddErrorPage(map<int, vector<BYTE>>&, bool) const override;
|
||||||
void AddFormatPage(map<int, vector<BYTE>>&, bool) const override;
|
void AddFormatPage(map<int, vector<BYTE>>&, bool) const override;
|
||||||
|
@ -14,12 +14,11 @@
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "scsimo.h"
|
|
||||||
|
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
#include "scsimo.h"
|
||||||
|
|
||||||
SCSIMO::SCSIMO(const set<uint32_t>& sector_sizes, const map<uint64_t, Geometry>& geometries) : Disk("SCMO")
|
SCSIMO::SCSIMO(const unordered_set<uint32_t>& sector_sizes, const unordered_map<uint64_t, Geometry>& geometries) : Disk("SCMO")
|
||||||
{
|
{
|
||||||
SetSectorSizes(sector_sizes);
|
SetSectorSizes(sector_sizes);
|
||||||
SetGeometries(geometries);
|
SetGeometries(geometries);
|
||||||
@ -41,6 +40,7 @@ void SCSIMO::Open(const Filepath& path)
|
|||||||
fio.Close();
|
fio.Close();
|
||||||
|
|
||||||
// For some priorities there are hard-coded, well-defined sector sizes and block counts
|
// For some priorities there are hard-coded, well-defined sector sizes and block counts
|
||||||
|
// TODO Find a more flexible solution
|
||||||
if (!SetGeometryForCapacity(size)) {
|
if (!SetGeometryForCapacity(size)) {
|
||||||
// Sector size (default 512 bytes) and number of blocks
|
// Sector size (default 512 bytes) and number of blocks
|
||||||
SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512, true);
|
SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512, true);
|
||||||
@ -63,39 +63,10 @@ void SCSIMO::Open(const Filepath& path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCSIMO::Inquiry(const DWORD *cdb, BYTE *buf)
|
vector<BYTE> SCSIMO::Inquiry() const
|
||||||
{
|
{
|
||||||
// EVPD check
|
// Optical memory device, SCSI-2, removable
|
||||||
if (cdb[1] & 0x01) {
|
return PrimaryDevice::Inquiry(7, 2, true);
|
||||||
SetStatusCode(STATUS_INVALIDCDB);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic data
|
|
||||||
// buf[0] ... Optical Memory Device
|
|
||||||
// buf[1] ... Removable
|
|
||||||
// buf[2] ... SCSI-2 compliant command system
|
|
||||||
// buf[3] ... SCSI-2 compliant Inquiry response
|
|
||||||
// buf[4] ... Inquiry additional data
|
|
||||||
memset(buf, 0, 8);
|
|
||||||
buf[0] = 0x07;
|
|
||||||
buf[1] = 0x80;
|
|
||||||
buf[2] = 0x02;
|
|
||||||
buf[3] = 0x02;
|
|
||||||
buf[4] = 0x1F;
|
|
||||||
|
|
||||||
// Padded vendor, product, revision
|
|
||||||
memcpy(&buf[8], GetPaddedName().c_str(), 28);
|
|
||||||
|
|
||||||
// Size return data
|
|
||||||
int size = (buf[4] + 5);
|
|
||||||
|
|
||||||
// Limit the size if the buffer is too small
|
|
||||||
if (size > (int)cdb[4]) {
|
|
||||||
size = (int)cdb[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSIMO::SetDeviceParameters(BYTE *buf)
|
void SCSIMO::SetDeviceParameters(BYTE *buf)
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
class SCSIMO : public Disk, public FileSupport
|
class SCSIMO : public Disk, public FileSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SCSIMO(const set<uint32_t>&, const map<uint64_t, Geometry>&);
|
SCSIMO(const unordered_set<uint32_t>&, const unordered_map<uint64_t, Geometry>&);
|
||||||
~SCSIMO() {}
|
~SCSIMO() {}
|
||||||
|
|
||||||
void Open(const Filepath& path) override;
|
void Open(const Filepath& path) override;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
int Inquiry(const DWORD *cdb, BYTE *buf) override;
|
vector<BYTE> Inquiry() const override;
|
||||||
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
bool ModeSelect(const DWORD *cdb, const BYTE *buf, int length) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "localizer.h"
|
#include "localizer.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
@ -146,7 +145,7 @@ string Localizer::Localize(LocalizationKey key, const string& locale, const stri
|
|||||||
string locale_lower = locale;
|
string locale_lower = locale;
|
||||||
transform(locale_lower.begin(), locale_lower.end(), locale_lower.begin(), ::tolower);
|
transform(locale_lower.begin(), locale_lower.end(), locale_lower.begin(), ::tolower);
|
||||||
|
|
||||||
map<LocalizationKey, string> messages = localized_messages[locale_lower];
|
unordered_map<LocalizationKey, string> messages = localized_messages[locale_lower];
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
// Try to fall back to country-indepedent locale (e.g. "en" instead of "en_US")
|
// Try to fall back to country-indepedent locale (e.g. "en" instead of "en_US")
|
||||||
if (locale_lower.length() > 2) {
|
if (locale_lower.length() > 2) {
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
void Add(LocalizationKey, const string&, const string&);
|
void Add(LocalizationKey, const string&, const string&);
|
||||||
map<string, map<LocalizationKey, string>> localized_messages;
|
unordered_map<string, unordered_map<LocalizationKey, string>> localized_messages;
|
||||||
|
|
||||||
set<string> supported_languages;
|
unordered_set<string> supported_languages;
|
||||||
};
|
};
|
||||||
|
@ -68,7 +68,7 @@ pthread_mutex_t ctrl_mutex; // Semaphore for the ctrl array
|
|||||||
static void *MonThread(void *param);
|
static void *MonThread(void *param);
|
||||||
string current_log_level; // Some versions of spdlog do not support get_log_level()
|
string current_log_level; // Some versions of spdlog do not support get_log_level()
|
||||||
string access_token;
|
string access_token;
|
||||||
set<int> reserved_ids;
|
unordered_set<int> reserved_ids;
|
||||||
DeviceFactory& device_factory = DeviceFactory::instance();
|
DeviceFactory& device_factory = DeviceFactory::instance();
|
||||||
RascsiImage rascsi_image;
|
RascsiImage rascsi_image;
|
||||||
RascsiResponse rascsi_response(&device_factory, &rascsi_image);
|
RascsiResponse rascsi_response(&device_factory, &rascsi_image);
|
||||||
@ -428,22 +428,10 @@ string ValidateLunSetup(const PbCommand& command, const vector<Device *>& existi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LUNs must be consecutive
|
// LUN 0 must exist for all devices
|
||||||
for (auto const& [id, lun]: luns) {
|
for (auto const& [id, lun]: luns) {
|
||||||
bool is_consecutive = false;
|
if (!(lun & 0x01)) {
|
||||||
|
return "LUN 0 is missing for device ID " + to_string(id);
|
||||||
uint32_t lun_vector = 0;
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
lun_vector |= 1 << i;
|
|
||||||
|
|
||||||
if (lun == lun_vector) {
|
|
||||||
is_consecutive = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_consecutive) {
|
|
||||||
return "LUNs for device ID " + to_string(id) + " are not consecutive";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +493,7 @@ string SetReservedIds(const string& ids)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set<int> reserved;
|
unordered_set<int> reserved;
|
||||||
for (string id_to_reserve : ids_to_reserve) {
|
for (string id_to_reserve : ids_to_reserve) {
|
||||||
int id;
|
int id;
|
||||||
if (!GetAsInt(id_to_reserve, id) || id > 7) {
|
if (!GetAsInt(id_to_reserve, id) || id > 7) {
|
||||||
@ -694,7 +682,7 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<string, string> params = { pb_device.params().begin(), pb_device.params().end() };
|
unordered_map<string, string> params = { pb_device.params().begin(), pb_device.params().end() };
|
||||||
if (!device->SupportsFile()) {
|
if (!device->SupportsFile()) {
|
||||||
params.erase("file");
|
params.erase("file");
|
||||||
}
|
}
|
||||||
@ -728,20 +716,24 @@ bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
|||||||
|
|
||||||
bool Detach(const CommandContext& context, Device *device, Device *map[], bool dryRun)
|
bool Detach(const CommandContext& context, Device *device, Device *map[], bool dryRun)
|
||||||
{
|
{
|
||||||
if (!dryRun) {
|
if (!device->GetLun()) {
|
||||||
for (auto const& d : devices) {
|
for (auto const& d : devices) {
|
||||||
// Detach all LUNs equal to or higher than the LUN specified
|
// LUN 0 can only be detached if there is no other lUN anymore
|
||||||
if (d && d->GetId() == device->GetId() && d->GetLun() >= device->GetLun()) {
|
if (d && d->GetId() == device->GetId() && d->GetLun()) {
|
||||||
map[d->GetId() * UnitNum + d->GetLun()] = NULL;
|
return ReturnStatus(context, false, "LUN 0 cannot be detached as long as there is still another LUN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FileSupport *file_support = dynamic_cast<FileSupport *>(d);
|
if (!dryRun) {
|
||||||
|
map[device->GetId() * UnitNum + device->GetLun()] = NULL;
|
||||||
|
|
||||||
|
FileSupport *file_support = dynamic_cast<FileSupport *>(device);
|
||||||
if (file_support) {
|
if (file_support) {
|
||||||
file_support->UnreserveFile();
|
file_support->UnreserveFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGINFO("Detached %s device with ID %d, unit %d", d->GetType().c_str(), d->GetId(), d->GetLun());
|
LOGINFO("Detached %s device with ID %d, unit %d", device->GetType().c_str(), device->GetId(), device->GetLun());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-map the controller
|
// Re-map the controller
|
||||||
MapController(map);
|
MapController(map);
|
||||||
|
@ -220,7 +220,7 @@ void RascsiResponse::GetAvailableImages(PbResult& result, PbServerInfo& server_i
|
|||||||
result.set_status(true);
|
result.set_status(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
PbReservedIdsInfo *RascsiResponse::GetReservedIds(PbResult& result, const set<int>& ids)
|
PbReservedIdsInfo *RascsiResponse::GetReservedIds(PbResult& result, const unordered_set<int>& ids)
|
||||||
{
|
{
|
||||||
PbReservedIdsInfo *reserved_ids_info = new PbReservedIdsInfo();
|
PbReservedIdsInfo *reserved_ids_info = new PbReservedIdsInfo();
|
||||||
for (int id : ids) {
|
for (int id : ids) {
|
||||||
@ -289,8 +289,9 @@ PbDeviceTypesInfo *RascsiResponse::GetDeviceTypesInfo(PbResult& result, const Pb
|
|||||||
return device_types_info;
|
return device_types_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vector<Device *>& devices, const set<int>& reserved_ids,
|
PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vector<Device *>& devices,
|
||||||
const string& current_log_level, const string& folder_pattern, const string& file_pattern, int scan_depth)
|
const unordered_set<int>& reserved_ids, const string& current_log_level, const string& folder_pattern,
|
||||||
|
const string& file_pattern, int scan_depth)
|
||||||
{
|
{
|
||||||
PbServerInfo *server_info = new PbServerInfo();
|
PbServerInfo *server_info = new PbServerInfo();
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ public:
|
|||||||
|
|
||||||
bool GetImageFile(PbImageFile *, const string&);
|
bool GetImageFile(PbImageFile *, const string&);
|
||||||
PbImageFilesInfo *GetAvailableImages(PbResult&, const string&, const string&, int);
|
PbImageFilesInfo *GetAvailableImages(PbResult&, const string&, const string&, int);
|
||||||
PbReservedIdsInfo *GetReservedIds(PbResult&, const set<int>&);
|
PbReservedIdsInfo *GetReservedIds(PbResult&, const unordered_set<int>&);
|
||||||
void GetDevices(PbServerInfo&, const vector<Device *>&);
|
void GetDevices(PbServerInfo&, const vector<Device *>&);
|
||||||
void GetDevicesInfo(PbResult&, const PbCommand&, const vector<Device *>&, int);
|
void GetDevicesInfo(PbResult&, const PbCommand&, const vector<Device *>&, int);
|
||||||
PbDeviceTypesInfo *GetDeviceTypesInfo(PbResult&, const PbCommand&);
|
PbDeviceTypesInfo *GetDeviceTypesInfo(PbResult&, const PbCommand&);
|
||||||
PbVersionInfo *GetVersionInfo(PbResult&);
|
PbVersionInfo *GetVersionInfo(PbResult&);
|
||||||
PbServerInfo *GetServerInfo(PbResult&, const vector<Device *>&, const set<int>&, const string&, const string&,
|
PbServerInfo *GetServerInfo(PbResult&, const vector<Device *>&, const unordered_set<int>&, const string&,
|
||||||
const string&, int);
|
const string&, const string&, int);
|
||||||
PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&);
|
PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&);
|
||||||
PbMappingInfo *GetMappingInfo(PbResult&);
|
PbMappingInfo *GetMappingInfo(PbResult&);
|
||||||
PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&);
|
PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&);
|
||||||
|
@ -12,57 +12,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// Status byte codes, Sense Keys and Additional Sense Codes
|
|
||||||
// (See https://www.t10.org/lists/1spc-lst.htm)
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
class ERROR_CODES
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum status : int {
|
|
||||||
GOOD = 0x00,
|
|
||||||
CHECK_CONDITION = 0x02,
|
|
||||||
CONDITION_MET = 0x04,
|
|
||||||
BUSY = 0x08,
|
|
||||||
INTERMEDIATE = 0x10,
|
|
||||||
INTERMEDIATE_CONDITION_MET = 0x14,
|
|
||||||
RESERVATION_CONFLICT = 0x18,
|
|
||||||
COMMAND_TERMINATED = 0x22,
|
|
||||||
QUEUE_FULL = 0x28
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sense_key : int {
|
|
||||||
NO_SENSE = 0x00,
|
|
||||||
RECOVERED_ERROR = 0x01,
|
|
||||||
NOT_READY = 0x02,
|
|
||||||
MEDIUM_ERROR = 0x03,
|
|
||||||
HARDWARE_ERROR = 0x04,
|
|
||||||
ILLEGAL_REQUEST = 0x05,
|
|
||||||
UNIT_ATTENTION = 0x06,
|
|
||||||
DATA_PROTECT = 0x07,
|
|
||||||
BLANK_CHECK = 0x08,
|
|
||||||
VENDOR_SPECIFIC = 0x09,
|
|
||||||
COPY_ABORTED = 0x0a,
|
|
||||||
ABORTED_COMMAND = 0x0b,
|
|
||||||
VOLUME_OVERFLOW = 0x0d,
|
|
||||||
MISCOMPARE = 0x0e,
|
|
||||||
COMPLETED = 0x0f
|
|
||||||
};
|
|
||||||
|
|
||||||
enum asc : int {
|
|
||||||
NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
|
|
||||||
INVALID_COMMAND_OPERATION_CODE = 0x20,
|
|
||||||
LBA_OUT_OF_RANGE = 0x21,
|
|
||||||
INVALID_FIELD_IN_CDB = 0x24,
|
|
||||||
INVALID_LUN = 0x25,
|
|
||||||
WRITE_PROTECTED = 0x27,
|
|
||||||
NOT_READY_TO_READY_CHANGE = 0x28,
|
|
||||||
MEDIUM_NOT_PRESENT = 0x3a
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// SASI/SCSI Bus
|
// SASI/SCSI Bus
|
||||||
@ -94,8 +43,8 @@ public:
|
|||||||
reserved // Unused
|
reserved // Unused
|
||||||
};
|
};
|
||||||
|
|
||||||
BUS() { };
|
BUS() {}
|
||||||
virtual ~BUS() { };
|
virtual ~BUS() {}
|
||||||
|
|
||||||
// Basic Functions
|
// Basic Functions
|
||||||
virtual BOOL Init(mode_e mode) = 0;
|
virtual BOOL Init(mode_e mode) = 0;
|
||||||
@ -108,8 +57,8 @@ public:
|
|||||||
return phase_table[mci];
|
return phase_table[mci];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* GetPhaseStrRaw(phase_t current_phase);
|
|
||||||
// Get the string phase name, based upon the raw data
|
// Get the string phase name, based upon the raw data
|
||||||
|
static const char* GetPhaseStrRaw(phase_t current_phase);
|
||||||
|
|
||||||
// Extract as specific pin field from a raw data capture
|
// Extract as specific pin field from a raw data capture
|
||||||
static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num)
|
static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num)
|
||||||
@ -168,6 +117,12 @@ private:
|
|||||||
static const char* phase_str_table[];
|
static const char* phase_str_table[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// For Status byte codes, Sense Keys and Additional Sense Codes
|
||||||
|
// See https://www.t10.org/lists/1spc-lst.htm
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
namespace scsi_defs {
|
namespace scsi_defs {
|
||||||
enum scsi_command : int {
|
enum scsi_command : int {
|
||||||
eCmdTestUnitReady = 0x00,
|
eCmdTestUnitReady = 0x00,
|
||||||
@ -220,4 +175,45 @@ namespace scsi_defs {
|
|||||||
eCmdWriteLong16 = 0x9F,
|
eCmdWriteLong16 = 0x9F,
|
||||||
eCmdReportLuns = 0xA0
|
eCmdReportLuns = 0xA0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum status : int {
|
||||||
|
GOOD = 0x00,
|
||||||
|
CHECK_CONDITION = 0x02,
|
||||||
|
CONDITION_MET = 0x04,
|
||||||
|
BUSY = 0x08,
|
||||||
|
INTERMEDIATE = 0x10,
|
||||||
|
INTERMEDIATE_CONDITION_MET = 0x14,
|
||||||
|
RESERVATION_CONFLICT = 0x18,
|
||||||
|
COMMAND_TERMINATED = 0x22,
|
||||||
|
QUEUE_FULL = 0x28
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sense_key : int {
|
||||||
|
NO_SENSE = 0x00,
|
||||||
|
RECOVERED_ERROR = 0x01,
|
||||||
|
NOT_READY = 0x02,
|
||||||
|
MEDIUM_ERROR = 0x03,
|
||||||
|
HARDWARE_ERROR = 0x04,
|
||||||
|
ILLEGAL_REQUEST = 0x05,
|
||||||
|
UNIT_ATTENTION = 0x06,
|
||||||
|
DATA_PROTECT = 0x07,
|
||||||
|
BLANK_CHECK = 0x08,
|
||||||
|
VENDOR_SPECIFIC = 0x09,
|
||||||
|
COPY_ABORTED = 0x0a,
|
||||||
|
ABORTED_COMMAND = 0x0b,
|
||||||
|
VOLUME_OVERFLOW = 0x0d,
|
||||||
|
MISCOMPARE = 0x0e,
|
||||||
|
COMPLETED = 0x0f
|
||||||
|
};
|
||||||
|
|
||||||
|
enum asc : int {
|
||||||
|
NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
|
||||||
|
INVALID_COMMAND_OPERATION_CODE = 0x20,
|
||||||
|
LBA_OUT_OF_RANGE = 0x21,
|
||||||
|
INVALID_FIELD_IN_CDB = 0x24,
|
||||||
|
INVALID_LUN = 0x25,
|
||||||
|
WRITE_PROTECTED = 0x27,
|
||||||
|
NOT_READY_TO_READY_CHANGE = 0x28,
|
||||||
|
MEDIUM_NOT_PRESENT = 0x3a
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user