mirror of
https://github.com/akuker/RASCSI.git
synced 2026-04-21 18:17:07 +00:00
Improve code sharing and dependencies, address code duplication (#976)
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Various Operation Settings
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define USE_SEL_EVENT_ENABLE // Check SEL signal by event
|
||||
// This avoids an indefinite loop with warnings if there is no RaSCSI hardware
|
||||
// and thus helps with running rasctl and unit test on x86 hardware.
|
||||
#if defined(__x86_64__) || defined(__X86__) || !defined(__linux__)
|
||||
#undef USE_SEL_EVENT_ENABLE
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
// Copyright (C) 2020 akuker
|
||||
// [ Logging utilities ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
static const int LOGBUF_SIZE = 512;
|
||||
|
||||
#define SPDLOGWRAPPER(loglevel, ...) \
|
||||
{ \
|
||||
char logbuf[LOGBUF_SIZE]; \
|
||||
snprintf(logbuf, sizeof(logbuf), __VA_ARGS__); \
|
||||
spdlog::log(loglevel, logbuf); \
|
||||
};
|
||||
|
||||
#define LOGTRACE(...) SPDLOGWRAPPER(spdlog::level::trace, __VA_ARGS__)
|
||||
#define LOGDEBUG(...) SPDLOGWRAPPER(spdlog::level::debug, __VA_ARGS__)
|
||||
#define LOGINFO(...) SPDLOGWRAPPER(spdlog::level::info, __VA_ARGS__)
|
||||
#define LOGWARN(...) SPDLOGWRAPPER(spdlog::level::warn, __VA_ARGS__)
|
||||
#define LOGERROR(...) SPDLOGWRAPPER(spdlog::level::err, __VA_ARGS__)
|
||||
@@ -0,0 +1,80 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "shared/protobuf_serializer.h"
|
||||
#include "shared/rascsi_exceptions.h"
|
||||
#include "generated/rascsi_interface.pb.h"
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace rascsi_interface;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Serialize/Deserialize protobuf message: Length followed by the actual data.
|
||||
// A little endian platform is assumed.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void ProtobufSerializer::SerializeMessage(int fd, const google::protobuf::Message& message) const
|
||||
{
|
||||
string data;
|
||||
message.SerializeToString(&data);
|
||||
|
||||
// Write the size of the protobuf data as a header
|
||||
auto size = static_cast<int32_t>(data.length());
|
||||
if (write(fd, &size, sizeof(size)) != sizeof(size)) {
|
||||
throw io_exception("Can't write protobuf message header");
|
||||
}
|
||||
|
||||
// Write the actual protobuf data
|
||||
if (write(fd, data.data(), size) != size) {
|
||||
throw io_exception("Can't write protobuf message data");
|
||||
}
|
||||
}
|
||||
|
||||
void ProtobufSerializer::DeserializeMessage(int fd, google::protobuf::Message& message) const
|
||||
{
|
||||
// Read the header with the size of the protobuf data
|
||||
vector<byte> header_buf(4);
|
||||
if (ReadBytes(fd, header_buf) < header_buf.size()) {
|
||||
throw io_exception("Invalid protobuf message header");
|
||||
}
|
||||
|
||||
const int size = (static_cast<int>(header_buf[3]) << 24) + (static_cast<int>(header_buf[2]) << 16)
|
||||
+ (static_cast<int>(header_buf[1]) << 8) + static_cast<int>(header_buf[0]);
|
||||
if (size < 0) {
|
||||
throw io_exception("Invalid protobuf message header");
|
||||
}
|
||||
|
||||
// Read the binary protobuf data
|
||||
vector<byte> data_buf(size);
|
||||
if (ReadBytes(fd, data_buf) < data_buf.size()) {
|
||||
throw io_exception("Missing protobuf message data");
|
||||
}
|
||||
|
||||
// Create protobuf message
|
||||
string data((const char *)data_buf.data(), size);
|
||||
message.ParseFromString(data);
|
||||
}
|
||||
|
||||
size_t ProtobufSerializer::ReadBytes(int fd, vector<byte>& buf) const
|
||||
{
|
||||
size_t offset = 0;
|
||||
while (offset < buf.size()) {
|
||||
const ssize_t len = read(fd, &buf.data()[offset], buf.size() - offset);
|
||||
if (len <= 0) {
|
||||
return len;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2022 Uwe Seimet
|
||||
//
|
||||
// Helper for serializing/deserializing protobuf messages
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "google/protobuf/message.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ProtobufSerializer
|
||||
{
|
||||
public:
|
||||
|
||||
ProtobufSerializer() = default;
|
||||
~ProtobufSerializer() = default;
|
||||
|
||||
void SerializeMessage(int, const google::protobuf::Message&) const;
|
||||
void DeserializeMessage(int, google::protobuf::Message&) const;
|
||||
size_t ReadBytes(int, vector<byte>&) const;
|
||||
};
|
||||
@@ -0,0 +1,146 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2021-2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "log.h"
|
||||
#include "rasutil.h"
|
||||
#include "protobuf_serializer.h"
|
||||
#include "protobuf_util.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace ras_util;
|
||||
using namespace rascsi_interface;
|
||||
|
||||
#define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ )
|
||||
|
||||
void protobuf_util::ParseParameters(PbDeviceDefinition& device, const string& params)
|
||||
{
|
||||
if (params.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Old style parameter (filename), for backwards compatibility only
|
||||
if (params.find(KEY_VALUE_SEPARATOR) == string::npos) {
|
||||
SetParam(device, "file", params);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
stringstream ss(params);
|
||||
string p;
|
||||
while (getline(ss, p, COMPONENT_SEPARATOR)) {
|
||||
if (!p.empty()) {
|
||||
const size_t separator_pos = p.find(KEY_VALUE_SEPARATOR);
|
||||
if (separator_pos != string::npos) {
|
||||
SetParam(device, p.substr(0, separator_pos), string_view(p).substr(separator_pos + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string protobuf_util::GetParam(const PbCommand& command, const string& key)
|
||||
{
|
||||
const auto& it = command.params().find(key);
|
||||
return it != command.params().end() ? it->second : "";
|
||||
}
|
||||
|
||||
string protobuf_util::GetParam(const PbDeviceDefinition& device, const string& key)
|
||||
{
|
||||
const auto& it = device.params().find(key);
|
||||
return it != device.params().end() ? it->second : "";
|
||||
}
|
||||
|
||||
void protobuf_util::SetParam(PbCommand& command, const string& key, string_view value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *command.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void protobuf_util::SetParam(PbDevice& device, const string& key, string_view value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *device.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void protobuf_util::SetParam(PbDeviceDefinition& device, const string& key, string_view value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *device.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void protobuf_util::SetPatternParams(PbCommand& command, string_view patterns)
|
||||
{
|
||||
string folder_pattern;
|
||||
string file_pattern;
|
||||
if (const size_t separator_pos = patterns.find(COMPONENT_SEPARATOR); separator_pos != string::npos) {
|
||||
folder_pattern = patterns.substr(0, separator_pos);
|
||||
file_pattern = patterns.substr(separator_pos + 1);
|
||||
}
|
||||
else {
|
||||
file_pattern = patterns;
|
||||
}
|
||||
|
||||
SetParam(command, "folder_pattern", folder_pattern);
|
||||
SetParam(command, "file_pattern", file_pattern);
|
||||
}
|
||||
|
||||
string protobuf_util::ListDevices(const list<PbDevice>& pb_devices)
|
||||
{
|
||||
if (pb_devices.empty()) {
|
||||
return "No devices currently attached.\n";
|
||||
}
|
||||
|
||||
ostringstream s;
|
||||
s << "+----+-----+------+-------------------------------------\n"
|
||||
<< "| ID | LUN | TYPE | IMAGE FILE\n"
|
||||
<< "+----+-----+------+-------------------------------------\n";
|
||||
|
||||
list<PbDevice> devices = pb_devices;
|
||||
devices.sort([](const auto& a, const auto& b) { return a.id() < b.id() || a.unit() < b.unit(); });
|
||||
|
||||
for (const auto& device : devices) {
|
||||
string filename;
|
||||
switch (device.type()) {
|
||||
case SCBR:
|
||||
filename = "X68000 HOST BRIDGE";
|
||||
break;
|
||||
|
||||
case SCDP:
|
||||
filename = "DaynaPort SCSI/Link";
|
||||
break;
|
||||
|
||||
case SCHS:
|
||||
filename = "Host Services";
|
||||
break;
|
||||
|
||||
case SCLP:
|
||||
filename = "SCSI Printer";
|
||||
break;
|
||||
|
||||
default:
|
||||
filename = device.file().name();
|
||||
break;
|
||||
}
|
||||
|
||||
s << "| " << device.id() << " | " << device.unit() << " | " << PbDeviceType_Name(device.type()) << " | "
|
||||
<< (filename.empty() ? "NO MEDIUM" : filename)
|
||||
<< (!device.status().removed() && (device.properties().read_only() || device.status().protected_()) ? " (READ-ONLY)" : "")
|
||||
<< '\n';
|
||||
}
|
||||
|
||||
s << "+----+-----+------+-------------------------------------\n";
|
||||
|
||||
return s.str();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2021-2022 Uwe Seimet
|
||||
//
|
||||
// Helper methods for setting up/evaluating protobuf messages
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "google/protobuf/message.h"
|
||||
#include "generated/rascsi_interface.pb.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
using namespace rascsi_interface;
|
||||
|
||||
namespace protobuf_util
|
||||
{
|
||||
static const char KEY_VALUE_SEPARATOR = '=';
|
||||
|
||||
void ParseParameters(PbDeviceDefinition&, const string&);
|
||||
string GetParam(const PbCommand&, const string&);
|
||||
string GetParam(const PbDeviceDefinition&, const string&);
|
||||
void SetParam(PbCommand&, const string&, string_view);
|
||||
void SetParam(PbDevice&, const string&, string_view);
|
||||
void SetParam(PbDeviceDefinition&, const string&, string_view);
|
||||
void SetPatternParams(PbCommand&, string_view);
|
||||
string ListDevices(const list<PbDevice>&);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2021-2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scsi.h"
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class parser_exception : public runtime_error
|
||||
{
|
||||
using runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
class io_exception : public runtime_error
|
||||
{
|
||||
using runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
class file_not_found_exception : public io_exception
|
||||
{
|
||||
using io_exception::io_exception;
|
||||
};
|
||||
|
||||
class scsi_exception : public exception
|
||||
{
|
||||
scsi_defs::sense_key sense_key;
|
||||
scsi_defs::asc asc;
|
||||
|
||||
public:
|
||||
|
||||
scsi_exception(scsi_defs::sense_key sense_key, scsi_defs::asc asc = scsi_defs::asc::NO_ADDITIONAL_SENSE_INFORMATION)
|
||||
: sense_key(sense_key), asc(asc) {}
|
||||
~scsi_exception() override = default;
|
||||
|
||||
scsi_defs::sense_key get_sense_key() const { return sense_key; }
|
||||
scsi_defs::asc get_asc() const { return asc; }
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2020 akuker
|
||||
// [ Define the version string ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "rascsi_version.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
// The following should be updated for each release
|
||||
const int rascsi_major_version = 22; // Last two digits of year
|
||||
const int rascsi_minor_version = 11; // Month
|
||||
const int rascsi_patch_version = -1; // Patch number - increment for each update
|
||||
|
||||
using namespace std;
|
||||
|
||||
string rascsi_get_version_string()
|
||||
{
|
||||
stringstream s;
|
||||
|
||||
s << setw(2) << setfill('0') << rascsi_major_version << '.' << rascsi_minor_version;
|
||||
|
||||
if (rascsi_patch_version < 0) {
|
||||
s << " --DEVELOPMENT BUILD--";
|
||||
}
|
||||
else {
|
||||
s << '.' << rascsi_patch_version;
|
||||
}
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2020 akuker
|
||||
// [ Define the version string ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
extern const int rascsi_major_version; // Last two digits of year
|
||||
extern const int rascsi_minor_version; // Month
|
||||
extern const int rascsi_patch_version; // Patch number
|
||||
|
||||
std::string rascsi_get_version_string();
|
||||
@@ -0,0 +1,95 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2021-2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "rascsi_exceptions.h"
|
||||
#include "rascsi_version.h"
|
||||
#include "rasutil.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool ras_util::GetAsUnsignedInt(const string& value, int& result)
|
||||
{
|
||||
if (value.find_first_not_of("0123456789") != string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
auto v = stoul(value);
|
||||
result = (int)v;
|
||||
}
|
||||
catch(const invalid_argument&) {
|
||||
return false;
|
||||
}
|
||||
catch(const out_of_range&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ras_util::ProcessId(const string& id_spec, int max_luns, int& id, int& lun)
|
||||
{
|
||||
if (const size_t separator_pos = id_spec.find(COMPONENT_SEPARATOR); separator_pos == string::npos) {
|
||||
if (!GetAsUnsignedInt(id_spec, id) || id >= 8) {
|
||||
throw parser_exception("Invalid device ID (0-7)");
|
||||
}
|
||||
|
||||
lun = 0;
|
||||
}
|
||||
else if (!GetAsUnsignedInt(id_spec.substr(0, separator_pos), id) || id > 7 ||
|
||||
!GetAsUnsignedInt(id_spec.substr(separator_pos + 1), lun) || lun >= max_luns) {
|
||||
throw parser_exception("Invalid LUN (0-" + to_string(max_luns - 1) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
string ras_util::Banner(const string& app)
|
||||
{
|
||||
ostringstream s;
|
||||
|
||||
s << "SCSI Target Emulator RaSCSI " << app << " version " << rascsi_get_version_string()
|
||||
<< " (" << __DATE__ << ' ' << __TIME__ << ")\n";
|
||||
s << "Powered by XM6 TypeG Technology / ";
|
||||
s << "Copyright (C) 2016-2020 GIMONS\n";
|
||||
s << "Copyright (C) 2020-2022 Contributors to the RaSCSI Reloaded project\n";
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
string ras_util::GetExtensionLowerCase(const string& filename)
|
||||
{
|
||||
string ext;
|
||||
if (const size_t separator = filename.rfind('.'); separator != string::npos) {
|
||||
ext = filename.substr(separator + 1);
|
||||
}
|
||||
transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c){ return std::tolower(c); });
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
// Pin the thread to a specific CPU
|
||||
// TODO Check whether just using a single CPU really makes sense
|
||||
void ras_util::FixCpu(int cpu)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Get the number of CPUs
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
sched_getaffinity(0, sizeof(cpu_set_t), &mask);
|
||||
const int cpus = CPU_COUNT(&mask);
|
||||
|
||||
// Set the thread affinity
|
||||
if (cpu < cpus) {
|
||||
CPU_ZERO(&mask);
|
||||
CPU_SET(cpu, &mask);
|
||||
sched_setaffinity(0, sizeof(cpu_set_t), &mask);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2021-2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ras_util
|
||||
{
|
||||
// Separator for compound options like ID:LUN
|
||||
static const char COMPONENT_SEPARATOR = ':';
|
||||
|
||||
bool GetAsUnsignedInt(const string&, int&);
|
||||
void ProcessId(const string&, int, int&, int&);
|
||||
string Banner(const string&);
|
||||
|
||||
string GetExtensionLowerCase(const string&);
|
||||
|
||||
void FixCpu(int);
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// X68000 EMULATOR "XM6"
|
||||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace scsi_defs {
|
||||
enum class scsi_level : int {
|
||||
SCSI_1_CCS = 1,
|
||||
SCSI_2 = 2,
|
||||
SPC = 3,
|
||||
SPC_2 = 4,
|
||||
SPC_3 = 5,
|
||||
SPC_4 = 6,
|
||||
SPC_5 = 7,
|
||||
SPC_6 = 8
|
||||
};
|
||||
|
||||
enum class device_type : int {
|
||||
DIRECT_ACCESS = 0,
|
||||
PRINTER = 2,
|
||||
PROCESSOR = 3,
|
||||
CD_ROM = 5,
|
||||
OPTICAL_MEMORY = 7,
|
||||
COMMUNICATIONS = 9
|
||||
};
|
||||
|
||||
enum class scsi_command : int {
|
||||
eCmdTestUnitReady = 0x00,
|
||||
eCmdRezero = 0x01,
|
||||
eCmdRequestSense = 0x03,
|
||||
eCmdFormatUnit = 0x04,
|
||||
eCmdReassignBlocks = 0x07,
|
||||
eCmdRead6 = 0x08,
|
||||
// Bridge specific command
|
||||
eCmdGetMessage10 = 0x08,
|
||||
// DaynaPort specific command
|
||||
eCmdRetrieveStats = 0x09,
|
||||
eCmdWrite6 = 0x0A,
|
||||
// Bridge specific ommand
|
||||
eCmdSendMessage10 = 0x0A,
|
||||
eCmdPrint = 0x0A,
|
||||
eCmdSeek6 = 0x0B,
|
||||
// DaynaPort specific command
|
||||
eCmdSetIfaceMode = 0x0C,
|
||||
// DaynaPort specific command
|
||||
eCmdSetMcastAddr = 0x0D,
|
||||
// DaynaPort specific command
|
||||
eCmdEnableInterface = 0x0E,
|
||||
eCmdSynchronizeBuffer = 0x10,
|
||||
eCmdInquiry = 0x12,
|
||||
eCmdModeSelect6 = 0x15,
|
||||
eCmdReserve6 = 0x16,
|
||||
eCmdRelease6 = 0x17,
|
||||
eCmdModeSense6 = 0x1A,
|
||||
eCmdStartStop = 0x1B,
|
||||
eCmdStopPrint = 0x1B,
|
||||
eCmdSendDiagnostic = 0x1D,
|
||||
eCmdPreventAllowMediumRemoval = 0x1E,
|
||||
eCmdReadCapacity10 = 0x25,
|
||||
eCmdRead10 = 0x28,
|
||||
eCmdWrite10 = 0x2A,
|
||||
eCmdSeek10 = 0x2B,
|
||||
eCmdVerify10 = 0x2F,
|
||||
eCmdSynchronizeCache10 = 0x35,
|
||||
eCmdReadDefectData10 = 0x37,
|
||||
eCmdReadLong10 = 0x3E,
|
||||
eCmdWriteLong10 = 0x3F,
|
||||
eCmdReadToc = 0x43,
|
||||
eCmdGetEventStatusNotification = 0x4A,
|
||||
eCmdModeSelect10 = 0x55,
|
||||
eCmdModeSense10 = 0x5A,
|
||||
eCmdRead16 = 0x88,
|
||||
eCmdWrite16 = 0x8A,
|
||||
eCmdVerify16 = 0x8F,
|
||||
eCmdSynchronizeCache16 = 0x91,
|
||||
eCmdReadCapacity16_ReadLong16 = 0x9E,
|
||||
eCmdWriteLong16 = 0x9F,
|
||||
eCmdReportLuns = 0xA0
|
||||
};
|
||||
|
||||
enum class status : int {
|
||||
GOOD = 0x00,
|
||||
CHECK_CONDITION = 0x02,
|
||||
RESERVATION_CONFLICT = 0x18
|
||||
};
|
||||
|
||||
enum class sense_key : int {
|
||||
NO_SENSE = 0x00,
|
||||
NOT_READY = 0x02,
|
||||
MEDIUM_ERROR = 0x03,
|
||||
ILLEGAL_REQUEST = 0x05,
|
||||
UNIT_ATTENTION = 0x06,
|
||||
DATA_PROTECT = 0x07,
|
||||
ABORTED_COMMAND = 0x0b
|
||||
};
|
||||
|
||||
enum class asc : int {
|
||||
NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
|
||||
WRITE_FAULT = 0x03,
|
||||
READ_FAULT = 0x11,
|
||||
INVALID_COMMAND_OPERATION_CODE = 0x20,
|
||||
LBA_OUT_OF_RANGE = 0x21,
|
||||
INVALID_FIELD_IN_CDB = 0x24,
|
||||
INVALID_LUN = 0x25,
|
||||
INVALID_FIELD_IN_PARAMETER_LIST = 0x26,
|
||||
WRITE_PROTECTED = 0x27,
|
||||
NOT_READY_TO_READY_CHANGE = 0x28,
|
||||
POWER_ON_OR_RESET = 0x29,
|
||||
MEDIUM_NOT_PRESENT = 0x3a,
|
||||
LOAD_OR_EJECT_FAILED = 0x53
|
||||
};
|
||||
|
||||
static const unordered_map<scsi_command, pair<int, const char *>> command_mapping = {
|
||||
{ scsi_command::eCmdTestUnitReady, make_pair(6, "TestUnitReady") },
|
||||
{ scsi_command::eCmdRezero, make_pair(6, "Rezero") },
|
||||
{ scsi_command::eCmdRequestSense, make_pair(6, "RequestSense") },
|
||||
{ scsi_command::eCmdFormatUnit, make_pair(6, "FormatUnit") },
|
||||
{ scsi_command::eCmdReassignBlocks, make_pair(6, "ReassignBlocks") },
|
||||
{ scsi_command::eCmdRead6, make_pair(6, "Read6/GetMessage10") },
|
||||
{ scsi_command::eCmdRetrieveStats,make_pair( 6, "RetrieveStats") },
|
||||
{ scsi_command::eCmdWrite6, make_pair(6, "Write6/Print/SendMessage10") },
|
||||
{ scsi_command::eCmdSeek6, make_pair(6, "Seek6") },
|
||||
{ scsi_command::eCmdSetIfaceMode, make_pair(6, "SetIfaceMode") },
|
||||
{ scsi_command::eCmdSetMcastAddr, make_pair(6, "SetMcastAddr") },
|
||||
{ scsi_command::eCmdEnableInterface, make_pair(6, "EnableInterface") },
|
||||
{ scsi_command::eCmdSynchronizeBuffer, make_pair(6, "SynchronizeBuffer") },
|
||||
{ scsi_command::eCmdInquiry, make_pair(6, "Inquiry") },
|
||||
{ scsi_command::eCmdModeSelect6, make_pair(6, "ModeSelect6") },
|
||||
{ scsi_command::eCmdReserve6, make_pair(6, "Reserve6") },
|
||||
{ scsi_command::eCmdRelease6, make_pair(6, "Release6") },
|
||||
{ scsi_command::eCmdModeSense6, make_pair(6, "ModeSense6") },
|
||||
{ scsi_command::eCmdStartStop, make_pair(6, "StartStop") },
|
||||
{ scsi_command::eCmdStopPrint, make_pair(6, "StopPrint") },
|
||||
{ scsi_command::eCmdSendDiagnostic, make_pair(6, "SendDiagnostic") },
|
||||
{ scsi_command::eCmdPreventAllowMediumRemoval, make_pair(6, "PreventAllowMediumRemoval") },
|
||||
{ scsi_command::eCmdReadCapacity10, make_pair(10, "ReadCapacity10") },
|
||||
{ scsi_command::eCmdRead10, make_pair(10, "Read10") },
|
||||
{ scsi_command::eCmdWrite10, make_pair(10, "Write10") },
|
||||
{ scsi_command::eCmdSeek10, make_pair(10, "Seek10") },
|
||||
{ scsi_command::eCmdVerify10, make_pair(10, "Verify10") },
|
||||
{ scsi_command::eCmdSynchronizeCache10, make_pair(10, "SynchronizeCache10") },
|
||||
{ scsi_command::eCmdReadDefectData10, make_pair(10, "ReadDefectData10") },
|
||||
{ scsi_command::eCmdReadLong10, make_pair(10, "ReadLong10") },
|
||||
{ scsi_command::eCmdWriteLong10, make_pair(10, "WriteLong10") },
|
||||
{ scsi_command::eCmdReadToc, make_pair(10, "ReadToc") },
|
||||
{ scsi_command::eCmdGetEventStatusNotification, make_pair(10, "GetEventStatusNotification") },
|
||||
{ scsi_command::eCmdModeSelect10, make_pair(10, "ModeSelect10") },
|
||||
{ scsi_command::eCmdModeSense10, make_pair(10, "ModeSense10") },
|
||||
{ scsi_command::eCmdRead16, make_pair(16, "Read16") },
|
||||
{ scsi_command::eCmdWrite16, make_pair(16, "Write16") },
|
||||
{ scsi_command::eCmdVerify16, make_pair(16, "Verify16") },
|
||||
{ scsi_command::eCmdSynchronizeCache16, make_pair(16, "SynchronizeCache16") },
|
||||
{ scsi_command::eCmdReadCapacity16_ReadLong16, make_pair(16, "ReadCapacity16/ReadLong16") },
|
||||
{ scsi_command::eCmdWriteLong16, make_pair(16, "WriteLong16") },
|
||||
{ scsi_command::eCmdReportLuns, make_pair(12, "ReportLuns") }
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user