mirror of https://github.com/akuker/RASCSI.git
Merge branch 'develop' into feature_bpi3
This commit is contained in:
commit
4b7b8eec92
|
@ -7,7 +7,6 @@ core
|
|||
__pycache__
|
||||
current
|
||||
rascsi_interface_pb2.py
|
||||
src/raspberrypi/hfdisk/
|
||||
*~
|
||||
messages.pot
|
||||
messages.mo
|
||||
|
@ -27,3 +26,10 @@ s.sh
|
|||
|
||||
# temporary kicad files
|
||||
*-backups
|
||||
|
||||
# VSCode temp file
|
||||
settings.json
|
||||
|
||||
# submodules
|
||||
hfdisk*
|
||||
mac-hard-disk-drivers
|
||||
|
|
12
cpp/bus.h
12
cpp/bus.h
|
@ -9,8 +9,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "os.h"
|
||||
#include "scsi.h"
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include "hal/board_type.h"
|
||||
|
@ -87,14 +87,14 @@ public:
|
|||
virtual bool GetREQ() const = 0;
|
||||
virtual void SetREQ(bool ast) = 0;
|
||||
|
||||
virtual BYTE GetDAT() = 0;
|
||||
virtual void SetDAT(BYTE dat) = 0;
|
||||
virtual uint8_t GetDAT() = 0;
|
||||
virtual void SetDAT(uint8_t dat) = 0;
|
||||
virtual bool GetDP() const = 0; // Get parity signal
|
||||
|
||||
virtual uint32_t Acquire() = 0;
|
||||
virtual int CommandHandShake(BYTE *buf) = 0;
|
||||
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
|
||||
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 0;
|
||||
virtual int CommandHandShake(uint8_t *buf) = 0;
|
||||
virtual int ReceiveHandShake(uint8_t *buf, int count) = 0;
|
||||
virtual int SendHandShake(uint8_t *buf, int count, int delay_after_bytes) = 0;
|
||||
|
||||
virtual bool GetSignal(board_type::pi_physical_pin_e pin) const = 0;
|
||||
// Get SCSI input signal value
|
||||
|
|
|
@ -121,16 +121,11 @@ bool AbstractController::AddDevice(shared_ptr<PrimaryDevice> device)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AbstractController::RemoveDevice(const shared_ptr<PrimaryDevice> device)
|
||||
bool AbstractController::RemoveDevice(shared_ptr<PrimaryDevice> device)
|
||||
{
|
||||
const size_t count = luns.erase(device->GetLun());
|
||||
assert (count == 1);
|
||||
device->SetController(nullptr);
|
||||
|
||||
if (count == 1) {
|
||||
device->SetController(nullptr);
|
||||
}
|
||||
|
||||
return count == 1;
|
||||
return luns.erase(device->GetLun()) == 1;
|
||||
}
|
||||
|
||||
bool AbstractController::HasDeviceForLun(int lun) const
|
||||
|
|
|
@ -25,12 +25,6 @@ class PrimaryDevice;
|
|||
|
||||
class AbstractController : public PhaseHandler
|
||||
{
|
||||
friend class PrimaryDevice;
|
||||
friend class ScsiController;
|
||||
|
||||
// Logical units of this controller mapped to their LUN numbers
|
||||
unordered_map<int, shared_ptr<PrimaryDevice>> luns;
|
||||
|
||||
public:
|
||||
|
||||
enum class rascsi_shutdown_mode {
|
||||
|
@ -40,21 +34,6 @@ public:
|
|||
RESTART_PI
|
||||
};
|
||||
|
||||
using ctrl_t = struct _ctrl_t {
|
||||
// Command data, dynamically resized if required
|
||||
vector<int> cmd = vector<int>(16);
|
||||
|
||||
scsi_defs::status status; // Status data
|
||||
int message; // Message data
|
||||
|
||||
// Transfer
|
||||
vector<BYTE> buffer; // Transfer data buffer
|
||||
uint32_t blocks; // Number of transfer blocks
|
||||
uint64_t next; // Next record
|
||||
uint32_t offset; // Transfer offset
|
||||
uint32_t length; // Transfer remaining length
|
||||
};
|
||||
|
||||
AbstractController(shared_ptr<BUS> bus, int target_id, int max_luns) : target_id(target_id), bus(bus), max_luns(max_luns) {}
|
||||
~AbstractController() override = default;
|
||||
|
||||
|
@ -70,42 +49,76 @@ public:
|
|||
|
||||
int GetTargetId() const { return target_id; }
|
||||
int GetMaxLuns() const { return max_luns; }
|
||||
int GetLunCount() const { return (int)luns.size(); }
|
||||
int GetLunCount() const { return static_cast<int>(luns.size()); }
|
||||
|
||||
unordered_set<shared_ptr<PrimaryDevice>> GetDevices() const;
|
||||
shared_ptr<PrimaryDevice> GetDeviceForLun(int) const;
|
||||
bool AddDevice(shared_ptr<PrimaryDevice>);
|
||||
bool RemoveDevice(const shared_ptr<PrimaryDevice>);
|
||||
bool RemoveDevice(shared_ptr<PrimaryDevice>);
|
||||
bool HasDeviceForLun(int) const;
|
||||
int ExtractInitiatorId(int) const;
|
||||
|
||||
// TODO These should probably be extracted into a new TransferHandler class
|
||||
void AllocateBuffer(size_t);
|
||||
vector<BYTE>& GetBuffer() { return ctrl.buffer; }
|
||||
vector<uint8_t>& GetBuffer() { return ctrl.buffer; }
|
||||
scsi_defs::status GetStatus() const { return ctrl.status; }
|
||||
void SetStatus(scsi_defs::status s) { ctrl.status = s; }
|
||||
uint32_t GetLength() const { return ctrl.length; }
|
||||
|
||||
void SetLength(uint32_t l) { ctrl.length = l; }
|
||||
uint32_t GetBlocks() const { return ctrl.blocks; }
|
||||
void SetBlocks(uint32_t b) { ctrl.blocks = b; }
|
||||
void DecrementBlocks() { --ctrl.blocks; }
|
||||
uint64_t GetNext() const { return ctrl.next; }
|
||||
void SetNext(uint64_t n) { ctrl.next = n; }
|
||||
void IncrementNext() { ++ctrl.next; }
|
||||
int GetMessage() const { return ctrl.message; }
|
||||
void SetMessage(int m) { ctrl.message = m; }
|
||||
vector<int>& GetCmd() { return ctrl.cmd; }
|
||||
int GetCmd(int index) const { return ctrl.cmd[index]; }
|
||||
bool IsByteTransfer() const { return is_byte_transfer; }
|
||||
void SetByteTransfer(bool);
|
||||
uint32_t GetBytesToTransfer() const { return bytes_to_transfer; }
|
||||
void SetBytesToTransfer(uint32_t b) { bytes_to_transfer = b; }
|
||||
|
||||
protected:
|
||||
|
||||
inline shared_ptr<BUS> GetBus() const { return bus; }
|
||||
|
||||
scsi_defs::scsi_command GetOpcode() const { return static_cast<scsi_defs::scsi_command>(ctrl.cmd[0]); }
|
||||
int GetLun() const { return (ctrl.cmd[1] >> 5) & 0x07; }
|
||||
|
||||
void ProcessPhase();
|
||||
|
||||
vector<int>& GetCmd() { return ctrl.cmd; }
|
||||
void AllocateCmd(size_t);
|
||||
|
||||
// TODO These should probably be extracted into a new TransferHandler class
|
||||
bool HasValidLength() const { return ctrl.length != 0; }
|
||||
int GetOffset() const { return ctrl.offset; }
|
||||
void ResetOffset() { ctrl.offset = 0; }
|
||||
void SetLength(uint32_t l) { ctrl.length = l; }
|
||||
void UpdateOffsetAndLength() { ctrl.offset += ctrl.length; ctrl.length = 0; }
|
||||
|
||||
private:
|
||||
|
||||
using ctrl_t = struct _ctrl_t {
|
||||
// Command data, dynamically resized if required
|
||||
vector<int> cmd = vector<int>(16);
|
||||
|
||||
scsi_defs::status status; // Status data
|
||||
int message; // Message data
|
||||
|
||||
// Transfer
|
||||
vector<uint8_t> buffer; // Transfer data buffer
|
||||
uint32_t blocks; // Number of transfer blocks
|
||||
uint64_t next; // Next record
|
||||
uint32_t offset; // Transfer offset
|
||||
uint32_t length; // Transfer remaining length
|
||||
};
|
||||
|
||||
ctrl_t ctrl = {};
|
||||
|
||||
// Logical units of this controller mapped to their LUN numbers
|
||||
unordered_map<int, shared_ptr<PrimaryDevice>> luns;
|
||||
|
||||
int target_id;
|
||||
|
||||
shared_ptr<BUS> bus;
|
||||
|
@ -114,7 +127,4 @@ private:
|
|||
|
||||
bool is_byte_transfer = false;
|
||||
uint32_t bytes_to_transfer = 0;
|
||||
|
||||
ctrl_t ctrl = {};
|
||||
ctrl_t* GetCtrl() { return &ctrl; }
|
||||
};
|
||||
|
|
|
@ -23,13 +23,13 @@ class PrimaryDevice;
|
|||
|
||||
class ControllerManager
|
||||
{
|
||||
std::shared_ptr<BUS> bus;
|
||||
shared_ptr<BUS> bus;
|
||||
|
||||
unordered_map<int, shared_ptr<AbstractController>> controllers;
|
||||
|
||||
public:
|
||||
|
||||
explicit ControllerManager(std::shared_ptr<BUS> bus) : bus(bus) {}
|
||||
explicit ControllerManager(shared_ptr<BUS> bus) : bus(bus) {}
|
||||
~ControllerManager() = default;
|
||||
|
||||
// Maximum number of controller devices
|
||||
|
|
|
@ -16,8 +16,9 @@
|
|||
#include "hal/gpiobus.h"
|
||||
#include "hal/systimer.h"
|
||||
#include "rascsi_exceptions.h"
|
||||
#include "devices/scsi_host_bridge.h"
|
||||
#include "devices/scsi_daynaport.h"
|
||||
#include "devices/interfaces/byte_writer.h"
|
||||
#include "devices/mode_page_device.h"
|
||||
#include "devices/disk.h"
|
||||
#include "scsi_controller.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
@ -27,8 +28,6 @@
|
|||
|
||||
using namespace scsi_defs;
|
||||
|
||||
const int ScsiController::LUN_MAX = 32;
|
||||
|
||||
ScsiController::ScsiController(shared_ptr<BUS> bus, int target_id) : AbstractController(bus, target_id, LUN_MAX)
|
||||
{
|
||||
// The initial buffer size will default to either the default buffer size OR
|
||||
|
@ -53,17 +52,17 @@ void ScsiController::Reset()
|
|||
BUS::phase_t ScsiController::Process(int id)
|
||||
{
|
||||
// Get bus information
|
||||
bus->Acquire();
|
||||
GetBus()->Acquire();
|
||||
|
||||
// Check to see if the reset signal was asserted
|
||||
if (bus->GetRST()) {
|
||||
if (GetBus()->GetRST()) {
|
||||
LOGWARN("RESET signal received!")
|
||||
|
||||
// Reset the controller
|
||||
Reset();
|
||||
|
||||
// Reset the bus
|
||||
bus->Reset();
|
||||
GetBus()->Reset();
|
||||
|
||||
return GetPhase();
|
||||
}
|
||||
|
@ -85,7 +84,7 @@ BUS::phase_t ScsiController::Process(int id)
|
|||
LOGERROR("%s Unhandled SCSI error, resetting controller and bus and entering bus free phase", __PRETTY_FUNCTION__)
|
||||
|
||||
Reset();
|
||||
bus->Reset();
|
||||
GetBus()->Reset();
|
||||
|
||||
BusFree();
|
||||
}
|
||||
|
@ -100,15 +99,15 @@ void ScsiController::BusFree()
|
|||
|
||||
SetPhase(BUS::phase_t::busfree);
|
||||
|
||||
bus->SetREQ(false);
|
||||
bus->SetMSG(false);
|
||||
bus->SetCD(false);
|
||||
bus->SetIO(false);
|
||||
bus->SetBSY(false);
|
||||
GetBus()->SetREQ(false);
|
||||
GetBus()->SetMSG(false);
|
||||
GetBus()->SetCD(false);
|
||||
GetBus()->SetIO(false);
|
||||
GetBus()->SetBSY(false);
|
||||
|
||||
// Initialize status and message
|
||||
SetStatus(status::GOOD);
|
||||
ctrl.message = 0x00;
|
||||
SetMessage(0x00);
|
||||
|
||||
// Initialize ATN message reception status
|
||||
scsi.atnmsg = false;
|
||||
|
@ -147,7 +146,7 @@ void ScsiController::BusFree()
|
|||
}
|
||||
|
||||
// Move to selection phase
|
||||
if (bus->GetSEL() && !bus->GetBSY()) {
|
||||
if (GetBus()->GetSEL() && !GetBus()->GetBSY()) {
|
||||
Selection();
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,7 @@ void ScsiController::Selection()
|
|||
{
|
||||
if (!IsSelection()) {
|
||||
// A different device controller was selected
|
||||
if (int id = 1 << GetTargetId(); ((int)bus->GetDAT() & id) == 0) {
|
||||
if (int id = 1 << GetTargetId(); (static_cast<int>(GetBus()->GetDAT()) & id) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,14 +169,14 @@ void ScsiController::Selection()
|
|||
SetPhase(BUS::phase_t::selection);
|
||||
|
||||
// Raise BSY and respond
|
||||
bus->SetBSY(true);
|
||||
GetBus()->SetBSY(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Selection completed
|
||||
if (!bus->GetSEL() && bus->GetBSY()) {
|
||||
if (!GetBus()->GetSEL() && GetBus()->GetBSY()) {
|
||||
// Message out phase if ATN=1, otherwise command phase
|
||||
if (bus->GetATN()) {
|
||||
if (GetBus()->GetATN()) {
|
||||
MsgOut();
|
||||
} else {
|
||||
Command();
|
||||
|
@ -192,11 +191,12 @@ void ScsiController::Command()
|
|||
|
||||
SetPhase(BUS::phase_t::command);
|
||||
|
||||
bus->SetMSG(false);
|
||||
bus->SetCD(true);
|
||||
bus->SetIO(false);
|
||||
GetBus()->SetMSG(false);
|
||||
GetBus()->SetCD(true);
|
||||
GetBus()->SetIO(false);
|
||||
|
||||
const int actual_count = bus->CommandHandShake(GetBuffer().data());
|
||||
const int actual_count = GetBus()->CommandHandShake(GetBuffer().data());
|
||||
// TODO Try to move GetCommandByteCount() to BUS, so that the controller does not need to know GPIOBUS
|
||||
const int command_byte_count = GPIOBUS::GetCommandByteCount(GetBuffer()[0]);
|
||||
|
||||
// If not able to receive all, move to the status phase
|
||||
|
@ -212,8 +212,8 @@ void ScsiController::Command()
|
|||
// Command data transfer
|
||||
stringstream s;
|
||||
for (int i = 0; i < command_byte_count; i++) {
|
||||
ctrl.cmd[i] = GetBuffer()[i];
|
||||
s << setfill('0') << setw(2) << hex << ctrl.cmd[i];
|
||||
GetCmd()[i] = GetBuffer()[i];
|
||||
s << setfill('0') << setw(2) << hex << GetCmd(i);
|
||||
}
|
||||
LOGTRACE("%s CDB=$%s",__PRETTY_FUNCTION__, s.str().c_str())
|
||||
|
||||
|
@ -225,11 +225,11 @@ void ScsiController::Command()
|
|||
|
||||
void ScsiController::Execute()
|
||||
{
|
||||
LOGDEBUG("++++ CMD ++++ %s Executing command $%02X", __PRETTY_FUNCTION__, (int)GetOpcode())
|
||||
LOGDEBUG("++++ CMD ++++ %s Executing command $%02X", __PRETTY_FUNCTION__, static_cast<int>(GetOpcode()))
|
||||
|
||||
// Initialization for data transfer
|
||||
ResetOffset();
|
||||
ctrl.blocks = 1;
|
||||
SetBlocks(1);
|
||||
execstart = SysTimer::GetTimerLow();
|
||||
|
||||
// Discard pending sense data from the previous command if the current command is not REQUEST SENSE
|
||||
|
@ -267,13 +267,13 @@ void ScsiController::Execute()
|
|||
device->SetStatusCode(0);
|
||||
}
|
||||
|
||||
if (!device->CheckReservation(initiator_id, GetOpcode(), ctrl.cmd[4] & 0x01)) {
|
||||
if (!device->CheckReservation(initiator_id, GetOpcode(), GetCmd(4) & 0x01)) {
|
||||
Error(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, status::RESERVATION_CONFLICT);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if (!device->Dispatch(GetOpcode())) {
|
||||
LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetTargetId(), lun, (int)GetOpcode())
|
||||
LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetTargetId(), lun, static_cast<int>(GetOpcode()))
|
||||
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
}
|
||||
|
@ -305,20 +305,20 @@ void ScsiController::Status()
|
|||
SysTimer::SleepUsec(5);
|
||||
}
|
||||
|
||||
LOGTRACE("%s Status Phase, status is $%02X",__PRETTY_FUNCTION__, (int)GetStatus())
|
||||
LOGTRACE("%s Status Phase, status is $%02X",__PRETTY_FUNCTION__, static_cast<int>(GetStatus()))
|
||||
|
||||
SetPhase(BUS::phase_t::status);
|
||||
|
||||
// Signal line operated by the target
|
||||
bus->SetMSG(false);
|
||||
bus->SetCD(true);
|
||||
bus->SetIO(true);
|
||||
GetBus()->SetMSG(false);
|
||||
GetBus()->SetCD(true);
|
||||
GetBus()->SetIO(true);
|
||||
|
||||
// Data transfer is 1 byte x 1 block
|
||||
ResetOffset();
|
||||
SetLength(1);
|
||||
ctrl.blocks = 1;
|
||||
GetBuffer()[0] = (BYTE)GetStatus();
|
||||
SetBlocks(1);
|
||||
GetBuffer()[0] = (uint8_t)GetStatus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -333,9 +333,9 @@ void ScsiController::MsgIn()
|
|||
|
||||
SetPhase(BUS::phase_t::msgin);
|
||||
|
||||
bus->SetMSG(true);
|
||||
bus->SetCD(true);
|
||||
bus->SetIO(true);
|
||||
GetBus()->SetMSG(true);
|
||||
GetBus()->SetCD(true);
|
||||
GetBus()->SetIO(true);
|
||||
|
||||
ResetOffset();
|
||||
return;
|
||||
|
@ -360,14 +360,14 @@ void ScsiController::MsgOut()
|
|||
|
||||
SetPhase(BUS::phase_t::msgout);
|
||||
|
||||
bus->SetMSG(true);
|
||||
bus->SetCD(true);
|
||||
bus->SetIO(false);
|
||||
GetBus()->SetMSG(true);
|
||||
GetBus()->SetCD(true);
|
||||
GetBus()->SetIO(false);
|
||||
|
||||
// Data transfer is 1 byte x 1 block
|
||||
ResetOffset();
|
||||
SetLength(1);
|
||||
ctrl.blocks = 1;
|
||||
SetBlocks(1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -393,9 +393,9 @@ void ScsiController::DataIn()
|
|||
|
||||
SetPhase(BUS::phase_t::datain);
|
||||
|
||||
bus->SetMSG(false);
|
||||
bus->SetCD(false);
|
||||
bus->SetIO(true);
|
||||
GetBus()->SetMSG(false);
|
||||
GetBus()->SetCD(false);
|
||||
GetBus()->SetIO(true);
|
||||
|
||||
ResetOffset();
|
||||
|
||||
|
@ -424,9 +424,9 @@ void ScsiController::DataOut()
|
|||
SetPhase(BUS::phase_t::dataout);
|
||||
|
||||
// Signal line operated by the target
|
||||
bus->SetMSG(false);
|
||||
bus->SetCD(false);
|
||||
bus->SetIO(false);
|
||||
GetBus()->SetMSG(false);
|
||||
GetBus()->SetCD(false);
|
||||
GetBus()->SetIO(false);
|
||||
|
||||
ResetOffset();
|
||||
return;
|
||||
|
@ -438,12 +438,12 @@ void ScsiController::DataOut()
|
|||
void ScsiController::Error(sense_key sense_key, asc asc, status status)
|
||||
{
|
||||
// Get bus information
|
||||
bus->Acquire();
|
||||
GetBus()->Acquire();
|
||||
|
||||
// Reset check
|
||||
if (bus->GetRST()) {
|
||||
if (GetBus()->GetRST()) {
|
||||
Reset();
|
||||
bus->Reset();
|
||||
GetBus()->Reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status)
|
|||
LOGERROR("No LUN 0 for device %d", GetTargetId())
|
||||
|
||||
SetStatus(status);
|
||||
ctrl.message = 0x00;
|
||||
SetMessage(0x00);
|
||||
|
||||
Status();
|
||||
|
||||
|
@ -471,14 +471,14 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status)
|
|||
}
|
||||
|
||||
if (sense_key != sense_key::NO_SENSE || asc != asc::NO_ADDITIONAL_SENSE_INFORMATION) {
|
||||
LOGDEBUG("Error status: Sense Key $%02X, ASC $%02X", (int)sense_key, (int)asc)
|
||||
LOGDEBUG("Error status: Sense Key $%02X, ASC $%02X", static_cast<int>(sense_key), static_cast<int>(asc))
|
||||
|
||||
// Set Sense Key and ASC for a subsequent REQUEST SENSE
|
||||
GetDeviceForLun(lun)->SetStatusCode(((int)sense_key << 16) | ((int)asc << 8));
|
||||
GetDeviceForLun(lun)->SetStatusCode((static_cast<int>(sense_key) << 16) | (static_cast<int>(asc) << 8));
|
||||
}
|
||||
|
||||
SetStatus(status);
|
||||
ctrl.message = 0x00;
|
||||
SetMessage(0x00);
|
||||
|
||||
LOGTRACE("%s Error (to status phase)", __PRETTY_FUNCTION__)
|
||||
|
||||
|
@ -487,18 +487,18 @@ void ScsiController::Error(sense_key sense_key, asc asc, status status)
|
|||
|
||||
void ScsiController::Send()
|
||||
{
|
||||
assert(!bus->GetREQ());
|
||||
assert(bus->GetIO());
|
||||
assert(!GetBus()->GetREQ());
|
||||
assert(GetBus()->GetIO());
|
||||
|
||||
if (HasValidLength()) {
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(GetOffset()) + ", length "
|
||||
+ to_string(ctrl.length)).c_str())
|
||||
+ to_string(GetLength())).c_str())
|
||||
|
||||
// TODO The delay has to be taken from ctrl.unit[lun], but as there are currently no Daynaport drivers for
|
||||
// LUNs other than 0 this work-around works.
|
||||
if (const int len = bus->SendHandShake(GetBuffer().data() + ctrl.offset, ctrl.length,
|
||||
if (const int len = GetBus()->SendHandShake(GetBuffer().data() + GetOffset(), GetLength(),
|
||||
HasDeviceForLun(0) ? GetDeviceForLun(0)->GetSendDelay() : 0);
|
||||
len != (int)ctrl.length) {
|
||||
len != static_cast<int>(GetLength())) {
|
||||
// If you cannot send all, move to status phase
|
||||
Error(sense_key::ABORTED_COMMAND);
|
||||
return;
|
||||
|
@ -510,14 +510,14 @@ void ScsiController::Send()
|
|||
}
|
||||
|
||||
// Block subtraction, result initialization
|
||||
ctrl.blocks--;
|
||||
DecrementBlocks();
|
||||
bool result = true;
|
||||
|
||||
// Processing after data collection (read/data-in only)
|
||||
if (IsDataIn() && ctrl.blocks != 0) {
|
||||
if (IsDataIn() && GetBlocks() != 0) {
|
||||
// set next buffer (set offset, length)
|
||||
result = XferIn(GetBuffer());
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Processing after data collection. Blocks: " + to_string(ctrl.blocks)).c_str())
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Processing after data collection. Blocks: " + to_string(GetBlocks())).c_str())
|
||||
}
|
||||
|
||||
// If result FALSE, move to status phase
|
||||
|
@ -527,10 +527,10 @@ void ScsiController::Send()
|
|||
}
|
||||
|
||||
// Continue sending if block !=0
|
||||
if (ctrl.blocks != 0){
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Continuing to send. Blocks: " + to_string(ctrl.blocks)).c_str())
|
||||
if (GetBlocks() != 0){
|
||||
LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Continuing to send. Blocks: " + to_string(GetBlocks())).c_str())
|
||||
assert(HasValidLength());
|
||||
assert(ctrl.offset == 0);
|
||||
assert(GetOffset() == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -562,8 +562,8 @@ void ScsiController::Send()
|
|||
case BUS::phase_t::status:
|
||||
// Message in phase
|
||||
SetLength(1);
|
||||
ctrl.blocks = 1;
|
||||
GetBuffer()[0] = (BYTE)ctrl.message;
|
||||
SetBlocks(1);
|
||||
GetBuffer()[0] = (uint8_t)GetMessage();
|
||||
MsgIn();
|
||||
break;
|
||||
|
||||
|
@ -583,17 +583,17 @@ void ScsiController::Receive()
|
|||
LOGTRACE("%s",__PRETTY_FUNCTION__)
|
||||
|
||||
// REQ is low
|
||||
assert(!bus->GetREQ());
|
||||
assert(!bus->GetIO());
|
||||
assert(!GetBus()->GetREQ());
|
||||
assert(!GetBus()->GetIO());
|
||||
|
||||
// Length != 0 if received
|
||||
if (HasValidLength()) {
|
||||
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, ctrl.length)
|
||||
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, GetLength())
|
||||
|
||||
// If not able to receive all, move to status phase
|
||||
if (int len = bus->ReceiveHandShake(GetBuffer().data() + GetOffset(), ctrl.length);
|
||||
len != (int)ctrl.length) {
|
||||
LOGERROR("%s Not able to receive %d bytes of data, only received %d",__PRETTY_FUNCTION__, ctrl.length, len)
|
||||
if (int len = GetBus()->ReceiveHandShake(GetBuffer().data() + GetOffset(), GetLength());
|
||||
len != static_cast<int>(GetLength())) {
|
||||
LOGERROR("%s Not able to receive %d bytes of data, only received %d",__PRETTY_FUNCTION__, GetLength(), len)
|
||||
Error(sense_key::ABORTED_COMMAND);
|
||||
return;
|
||||
}
|
||||
|
@ -604,14 +604,14 @@ void ScsiController::Receive()
|
|||
}
|
||||
|
||||
// Block subtraction, result initialization
|
||||
ctrl.blocks--;
|
||||
DecrementBlocks();
|
||||
bool result = true;
|
||||
|
||||
// Processing after receiving data (by phase)
|
||||
LOGTRACE("%s Phase: %s",__PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(GetPhase()))
|
||||
switch (GetPhase()) {
|
||||
case BUS::phase_t::dataout:
|
||||
if (ctrl.blocks == 0) {
|
||||
if (GetBlocks() == 0) {
|
||||
// End with this buffer
|
||||
result = XferOut(false);
|
||||
} else {
|
||||
|
@ -621,15 +621,15 @@ void ScsiController::Receive()
|
|||
break;
|
||||
|
||||
case BUS::phase_t::msgout:
|
||||
ctrl.message = GetBuffer()[0];
|
||||
if (!XferMsg(ctrl.message)) {
|
||||
SetMessage(GetBuffer()[0]);
|
||||
if (!XferMsg(GetMessage())) {
|
||||
// Immediately free the bus if message output fails
|
||||
BusFree();
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear message data in preparation for message-in
|
||||
ctrl.message = 0x00;
|
||||
SetMessage(0x00);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -637,16 +637,15 @@ void ScsiController::Receive()
|
|||
}
|
||||
|
||||
// If result FALSE, move to status phase
|
||||
// TODO Check whether we can raise scsi_exception here in order to simplify the error handling
|
||||
if (!result) {
|
||||
Error(sense_key::ABORTED_COMMAND);
|
||||
return;
|
||||
}
|
||||
|
||||
// Continue to receive if block !=0
|
||||
if (ctrl.blocks != 0) {
|
||||
// Continue to receive if block != 0
|
||||
if (GetBlocks() != 0) {
|
||||
assert(HasValidLength());
|
||||
assert(ctrl.offset == 0);
|
||||
assert(GetOffset() == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -679,7 +678,7 @@ bool ScsiController::XferMsg(int msg)
|
|||
|
||||
// Save message out data
|
||||
if (scsi.atnmsg) {
|
||||
scsi.msb[scsi.msc] = (BYTE)msg;
|
||||
scsi.msb[scsi.msc] = (uint8_t)msg;
|
||||
scsi.msc++;
|
||||
scsi.msc %= 256;
|
||||
}
|
||||
|
@ -689,22 +688,21 @@ bool ScsiController::XferMsg(int msg)
|
|||
|
||||
void ScsiController::ReceiveBytes()
|
||||
{
|
||||
assert(!bus->GetREQ());
|
||||
assert(!bus->GetIO());
|
||||
assert(!GetBus()->GetREQ());
|
||||
assert(!GetBus()->GetIO());
|
||||
|
||||
if (HasValidLength()) {
|
||||
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, ctrl.length)
|
||||
LOGTRACE("%s Length is %d bytes", __PRETTY_FUNCTION__, GetLength())
|
||||
|
||||
// If not able to receive all, move to status phase
|
||||
if (uint32_t len = bus->ReceiveHandShake(GetBuffer().data() + GetOffset(), ctrl.length);
|
||||
len != ctrl.length) {
|
||||
if (uint32_t len = GetBus()->ReceiveHandShake(GetBuffer().data() + GetOffset(), GetLength()); len != GetLength()) {
|
||||
LOGERROR("%s Not able to receive %d bytes of data, only received %d",
|
||||
__PRETTY_FUNCTION__, ctrl.length, len)
|
||||
__PRETTY_FUNCTION__, GetLength(), len)
|
||||
Error(sense_key::ABORTED_COMMAND);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_to_transfer = ctrl.length;
|
||||
SetBytesToTransfer(GetLength());
|
||||
|
||||
UpdateOffsetAndLength();
|
||||
|
||||
|
@ -722,15 +720,15 @@ void ScsiController::ReceiveBytes()
|
|||
break;
|
||||
|
||||
case BUS::phase_t::msgout:
|
||||
ctrl.message = GetBuffer()[0];
|
||||
if (!XferMsg(ctrl.message)) {
|
||||
SetMessage(GetBuffer()[0]);
|
||||
if (!XferMsg(GetMessage())) {
|
||||
// Immediately free the bus if message output fails
|
||||
BusFree();
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear message data in preparation for message-in
|
||||
ctrl.message = 0x00;
|
||||
SetMessage(0x00);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -771,11 +769,11 @@ bool ScsiController::XferOut(bool cont)
|
|||
return XferOutBlockOriented(cont);
|
||||
}
|
||||
|
||||
const uint32_t length = bytes_to_transfer;
|
||||
const uint32_t count = GetBytesToTransfer();
|
||||
SetByteTransfer(false);
|
||||
|
||||
auto device = GetDeviceForLun(GetEffectiveLun());
|
||||
return device != nullptr ? device->WriteByteSequence(GetBuffer(), length) : false;
|
||||
return device != nullptr ? device->WriteByteSequence(GetBuffer(), count) : false;
|
||||
}
|
||||
|
||||
void ScsiController::DataOutNonBlockOriented()
|
||||
|
@ -795,10 +793,9 @@ void ScsiController::DataOutNonBlockOriented()
|
|||
|
||||
case scsi_command::eCmdModeSelect6:
|
||||
case scsi_command::eCmdModeSelect10: {
|
||||
// TODO Try to get rid of this cast
|
||||
if (auto device = dynamic_pointer_cast<ModePageDevice>(GetDeviceForLun(GetEffectiveLun()));
|
||||
device != nullptr) {
|
||||
device->ModeSelect(GetOpcode(), ctrl.cmd, GetBuffer(), GetOffset());
|
||||
device->ModeSelect(GetOpcode(), GetCmd(), GetBuffer(), GetOffset());
|
||||
}
|
||||
else {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
|
@ -811,7 +808,7 @@ void ScsiController::DataOutNonBlockOriented()
|
|||
break;
|
||||
|
||||
default:
|
||||
LOGWARN("Unexpected Data Out phase for command $%02X", (int)GetOpcode())
|
||||
LOGWARN("Unexpected Data Out phase for command $%02X", static_cast<int>(GetOpcode()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -822,11 +819,11 @@ void ScsiController::DataOutNonBlockOriented()
|
|||
// *Reset offset and length
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool ScsiController::XferIn(vector<BYTE>& buf)
|
||||
bool ScsiController::XferIn(vector<uint8_t>& buf)
|
||||
{
|
||||
assert(IsDataIn());
|
||||
|
||||
LOGTRACE("%s command=%02X", __PRETTY_FUNCTION__, (int)GetOpcode())
|
||||
LOGTRACE("%s command=%02X", __PRETTY_FUNCTION__, static_cast<int>(GetOpcode()))
|
||||
|
||||
int lun = GetEffectiveLun();
|
||||
if (!HasDeviceForLun(lun)) {
|
||||
|
@ -840,14 +837,14 @@ bool ScsiController::XferIn(vector<BYTE>& buf)
|
|||
case scsi_command::eCmdRead16:
|
||||
// Read from disk
|
||||
try {
|
||||
SetLength(dynamic_pointer_cast<Disk>(GetDeviceForLun(lun))->Read(ctrl.cmd, buf, ctrl.next));
|
||||
SetLength(dynamic_pointer_cast<Disk>(GetDeviceForLun(lun))->Read(GetCmd(), buf, GetNext()));
|
||||
}
|
||||
catch(const scsi_exception&) {
|
||||
// If there is an error, go to the status phase
|
||||
return false;
|
||||
}
|
||||
|
||||
ctrl.next++;
|
||||
IncrementNext();
|
||||
|
||||
// If things are normal, work setting
|
||||
ResetOffset();
|
||||
|
@ -867,26 +864,33 @@ bool ScsiController::XferIn(vector<BYTE>& buf)
|
|||
// Data transfer OUT
|
||||
// *If cont=true, reset the offset and length
|
||||
//
|
||||
// TODO Try to use less casts
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool ScsiController::XferOutBlockOriented(bool cont)
|
||||
{
|
||||
auto disk = dynamic_pointer_cast<Disk>(GetDeviceForLun(GetEffectiveLun()));
|
||||
if (disk == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto device = GetDeviceForLun(GetEffectiveLun());
|
||||
|
||||
// Limited to write commands
|
||||
switch (GetOpcode()) {
|
||||
case scsi_command::eCmdModeSelect6:
|
||||
case scsi_command::eCmdModeSelect10:
|
||||
{
|
||||
auto mode_page_device = dynamic_pointer_cast<ModePageDevice>(device);
|
||||
if (mode_page_device == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
disk->ModeSelect(GetOpcode(), ctrl.cmd, GetBuffer(), GetOffset());
|
||||
mode_page_device->ModeSelect(GetOpcode(), GetCmd(), GetBuffer(), GetOffset());
|
||||
}
|
||||
catch(const scsi_exception& e) {
|
||||
Error(e.get_sense_key(), e.get_asc());
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case scsi_command::eCmdWrite6:
|
||||
case scsi_command::eCmdWrite10:
|
||||
|
@ -895,11 +899,9 @@ bool ScsiController::XferOutBlockOriented(bool cont)
|
|||
case scsi_command::eCmdVerify10:
|
||||
case scsi_command::eCmdVerify16:
|
||||
{
|
||||
// Special case Write function for bridge
|
||||
// TODO This class must not know about SCSIBR
|
||||
if (auto bridge = dynamic_pointer_cast<SCSIBR>(disk); bridge) {
|
||||
if (!bridge->WriteBytes(ctrl.cmd, GetBuffer(), ctrl.length)) {
|
||||
// Write failed
|
||||
// Special case for SCBR and SCDP
|
||||
if (auto byte_writer = dynamic_pointer_cast<ByteWriter>(device); byte_writer) {
|
||||
if (!byte_writer->WriteBytes(GetCmd(), GetBuffer(), GetLength())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -907,38 +909,31 @@ bool ScsiController::XferOutBlockOriented(bool cont)
|
|||
break;
|
||||
}
|
||||
|
||||
// Special case Write function for DaynaPort
|
||||
// TODO This class must not know about DaynaPort
|
||||
if (auto daynaport = dynamic_pointer_cast<SCSIDaynaPort>(disk); daynaport) {
|
||||
daynaport->WriteBytes(ctrl.cmd, GetBuffer(), 0);
|
||||
|
||||
ResetOffset();
|
||||
ctrl.blocks = 0;
|
||||
break;
|
||||
auto disk = dynamic_pointer_cast<Disk>(device);
|
||||
if (disk == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
disk->Write(ctrl.cmd, GetBuffer(), ctrl.next - 1);
|
||||
disk->Write(GetCmd(), GetBuffer(), GetNext() - 1);
|
||||
}
|
||||
catch(const scsi_exception& e) {
|
||||
Error(e.get_sense_key(), e.get_asc());
|
||||
|
||||
// Write failed
|
||||
return false;
|
||||
}
|
||||
|
||||
// If you do not need the next block, end here
|
||||
ctrl.next++;
|
||||
IncrementNext();
|
||||
if (!cont) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check the next block
|
||||
try {
|
||||
SetLength(disk->WriteCheck(ctrl.next - 1));
|
||||
SetLength(disk->WriteCheck(GetNext() - 1));
|
||||
}
|
||||
catch(const scsi_exception&) {
|
||||
// Cannot write
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -951,7 +946,7 @@ bool ScsiController::XferOutBlockOriented(bool cont)
|
|||
break;
|
||||
|
||||
default:
|
||||
LOGWARN("Received an unexpected command ($%02X) in %s", (int)GetOpcode(), __PRETTY_FUNCTION__)
|
||||
LOGWARN("Received an unexpected command ($%02X) in %s", static_cast<int>(GetOpcode()), __PRETTY_FUNCTION__)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -965,8 +960,8 @@ void ScsiController::ProcessCommand()
|
|||
stringstream s;
|
||||
s << setfill('0') << setw(2) << hex;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
ctrl.cmd[i] = GetBuffer()[i];
|
||||
s << ctrl.cmd[i];
|
||||
GetCmd()[i] = GetBuffer()[i];
|
||||
s << GetCmd(i);
|
||||
}
|
||||
LOGTRACE("%s CDB=$%s",__PRETTY_FUNCTION__, s.str().c_str())
|
||||
|
||||
|
@ -977,7 +972,7 @@ void ScsiController::ParseMessage()
|
|||
{
|
||||
int i = 0;
|
||||
while (i < scsi.msc) {
|
||||
const BYTE message_type = scsi.msb[i];
|
||||
const uint8_t message_type = scsi.msb[i];
|
||||
|
||||
if (message_type == 0x06) {
|
||||
LOGTRACE("Received ABORT message")
|
||||
|
@ -996,7 +991,7 @@ void ScsiController::ParseMessage()
|
|||
}
|
||||
|
||||
if (message_type >= 0x80) {
|
||||
identified_lun = (int)message_type & 0x1F;
|
||||
identified_lun = static_cast<int>(message_type) & 0x1F;
|
||||
LOGTRACE("Received IDENTIFY message for LUN %d", identified_lun)
|
||||
}
|
||||
|
||||
|
@ -1006,7 +1001,7 @@ void ScsiController::ParseMessage()
|
|||
// Check only when synchronous transfer is possible
|
||||
if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) {
|
||||
SetLength(1);
|
||||
ctrl.blocks = 1;
|
||||
SetBlocks(1);
|
||||
GetBuffer()[0] = 0x07;
|
||||
MsgIn();
|
||||
return;
|
||||
|
@ -1024,7 +1019,7 @@ void ScsiController::ParseMessage()
|
|||
|
||||
// STDR response message generation
|
||||
SetLength(5);
|
||||
ctrl.blocks = 1;
|
||||
SetBlocks(1);
|
||||
GetBuffer()[0] = 0x01;
|
||||
GetBuffer()[1] = 0x03;
|
||||
GetBuffer()[2] = 0x01;
|
||||
|
@ -1042,11 +1037,11 @@ void ScsiController::ParseMessage()
|
|||
void ScsiController::ProcessMessage()
|
||||
{
|
||||
// Continue message out phase as long as ATN keeps asserting
|
||||
if (bus->GetATN()) {
|
||||
if (GetBus()->GetATN()) {
|
||||
// Data transfer is 1 byte x 1 block
|
||||
ResetOffset();
|
||||
SetLength(1);
|
||||
ctrl.blocks = 1;
|
||||
SetBlocks(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "abstract_controller.h"
|
||||
#include "os.h"
|
||||
#include "scsi.h"
|
||||
#include <array>
|
||||
|
||||
|
@ -30,7 +29,7 @@ class ScsiController : public AbstractController
|
|||
static const int MAX_SYNC_PERIOD = 50;
|
||||
|
||||
// REQ/ACK offset(limited to 16)
|
||||
static const BYTE MAX_SYNC_OFFSET = 16;
|
||||
static const uint8_t MAX_SYNC_OFFSET = 16;
|
||||
|
||||
static const int UNKNOWN_INITIATOR_ID = -1;
|
||||
|
||||
|
@ -39,20 +38,20 @@ class ScsiController : public AbstractController
|
|||
using scsi_t = struct _scsi_t {
|
||||
// Synchronous transfer
|
||||
bool syncenable; // Synchronous transfer possible
|
||||
BYTE syncperiod = MAX_SYNC_PERIOD; // Synchronous transfer period
|
||||
BYTE syncoffset; // Synchronous transfer offset
|
||||
uint8_t syncperiod = MAX_SYNC_PERIOD; // Synchronous transfer period
|
||||
uint8_t syncoffset; // Synchronous transfer offset
|
||||
int syncack; // Number of synchronous transfer ACKs
|
||||
|
||||
// ATN message
|
||||
bool atnmsg;
|
||||
int msc;
|
||||
std::array<BYTE, 256> msb;
|
||||
std::array<uint8_t, 256> msb;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// Maximum number of logical units
|
||||
static const int LUN_MAX;
|
||||
static inline const int LUN_MAX = 32;
|
||||
|
||||
ScsiController(shared_ptr<BUS>, int);
|
||||
~ScsiController() override = default;
|
||||
|
@ -98,7 +97,7 @@ private:
|
|||
// Data transfer
|
||||
void Send();
|
||||
bool XferMsg(int);
|
||||
bool XferIn(vector<BYTE>&);
|
||||
bool XferIn(vector<uint8_t>&);
|
||||
bool XferOut(bool);
|
||||
bool XferOutBlockOriented(bool);
|
||||
void ReceiveBytes();
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include "log.h"
|
||||
#include "cfilesystem.h"
|
||||
#include <dirent.h>
|
||||
|
@ -107,12 +106,12 @@ static char* U2S(const char *utf8)
|
|||
/// A 66 byte buffer is required for writing.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Human68k::namests_t::GetCopyPath(BYTE* szPath) const
|
||||
void Human68k::namests_t::GetCopyPath(uint8_t* szPath) const
|
||||
{
|
||||
assert(szPath);
|
||||
|
||||
BYTE* p = szPath;
|
||||
for (BYTE c : path) {
|
||||
uint8_t* p = szPath;
|
||||
for (uint8_t c : path) {
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c == 0x09) {
|
||||
|
@ -132,16 +131,16 @@ void Human68k::namests_t::GetCopyPath(BYTE* szPath) const
|
|||
/// A 23 byte buffer is required for writing.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const
|
||||
void Human68k::namests_t::GetCopyFilename(uint8_t* szFilename) const
|
||||
{
|
||||
assert(szFilename);
|
||||
|
||||
size_t i;
|
||||
BYTE* p = szFilename;
|
||||
uint8_t* p = szFilename;
|
||||
|
||||
// Transfer the base file name
|
||||
for (i = 0; i < 8; i++) {
|
||||
BYTE c = name[i];
|
||||
uint8_t c = name[i];
|
||||
if (c == ' ') {
|
||||
// Check that the file name continues after a space is detected
|
||||
/// TODO: Should change this function to be compatible with 8+3 chars and TwentyOne
|
||||
|
@ -165,7 +164,7 @@ void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const
|
|||
if (i >= 8) {
|
||||
// Transfer the extraneous part
|
||||
for (i = 0; i < 10; i++) {
|
||||
const BYTE c = add[i];
|
||||
const uint8_t c = add[i];
|
||||
if (c == '\0')
|
||||
break;
|
||||
*p++ = c;
|
||||
|
@ -177,7 +176,7 @@ void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const
|
|||
if (ext[0] != ' ' || ext[1] != ' ' || ext[2] != ' ') {
|
||||
*p++ = '.';
|
||||
for (i = 0; i < 3; i++) {
|
||||
const BYTE c = ext[i];
|
||||
const uint8_t c = ext[i];
|
||||
if (c == ' ') {
|
||||
// Check that the file extension continues after a space is detected
|
||||
/// TODO: Should change this function to be compatible with 8+3 chars and TwentyOne
|
||||
|
@ -290,7 +289,7 @@ bool CHostDrv::isMediaOffline() const
|
|||
// Get media bytes
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BYTE CHostDrv::GetMediaByte() const
|
||||
uint8_t CHostDrv::GetMediaByte() const
|
||||
{
|
||||
return Human68k::MEDIA_REMOTE;
|
||||
}
|
||||
|
@ -474,7 +473,7 @@ void CHostDrv::CleanCache() const
|
|||
/// Update the cache for the specified path
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostDrv::CleanCache(const BYTE* szHumanPath)
|
||||
void CHostDrv::CleanCache(const uint8_t* szHumanPath)
|
||||
{
|
||||
assert(szHumanPath);
|
||||
|
||||
|
@ -490,7 +489,7 @@ void CHostDrv::CleanCache(const BYTE* szHumanPath)
|
|||
/// Update the cache below and including the specified path
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostDrv::CleanCacheChild(const BYTE* szHumanPath) const
|
||||
void CHostDrv::CleanCacheChild(const uint8_t* szHumanPath) const
|
||||
{
|
||||
assert(szHumanPath);
|
||||
|
||||
|
@ -507,7 +506,7 @@ void CHostDrv::CleanCacheChild(const BYTE* szHumanPath) const
|
|||
/// Delete the cache for the specified path
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostDrv::DeleteCache(const BYTE* szHumanPath)
|
||||
void CHostDrv::DeleteCache(const uint8_t* szHumanPath)
|
||||
{
|
||||
auto p = FindCache(szHumanPath);
|
||||
if (p) {
|
||||
|
@ -526,7 +525,7 @@ void CHostDrv::DeleteCache(const BYTE* szHumanPath)
|
|||
/// Make sure to lock from the top.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
CHostPath* CHostDrv::FindCache(const BYTE* szHuman)
|
||||
CHostPath* CHostDrv::FindCache(const uint8_t* szHuman)
|
||||
{
|
||||
assert(szHuman);
|
||||
|
||||
|
@ -602,7 +601,7 @@ CHostPath* CHostDrv::MakeCache(CHostFiles* pFiles)
|
|||
assert(m_szBase);
|
||||
assert(strlen(m_szBase) < FILEPATH_MAX);
|
||||
|
||||
BYTE szHumanPath[HUMAN68K_PATH_MAX]; // Path names are entered in order from the route
|
||||
uint8_t szHumanPath[HUMAN68K_PATH_MAX]; // Path names are entered in order from the route
|
||||
szHumanPath[0] = '\0';
|
||||
size_t nHumanPath = 0;
|
||||
|
||||
|
@ -611,7 +610,7 @@ CHostPath* CHostDrv::MakeCache(CHostFiles* pFiles)
|
|||
size_t nHostPath = strlen(szHostPath);
|
||||
|
||||
CHostPath* pPath;
|
||||
const BYTE* p = pFiles->GetHumanPath();
|
||||
const uint8_t* p = pFiles->GetHumanPath();
|
||||
for (;;) {
|
||||
// Add path separators
|
||||
if (nHumanPath + 1 >= HUMAN68K_PATH_MAX)
|
||||
|
@ -624,7 +623,7 @@ CHostPath* CHostDrv::MakeCache(CHostFiles* pFiles)
|
|||
szHostPath[nHostPath] = '\0';
|
||||
|
||||
// Insert one file
|
||||
BYTE szHumanFilename[24]; // File name part
|
||||
uint8_t szHumanFilename[24]; // File name part
|
||||
p = SeparateCopyFilename(p, szHumanFilename);
|
||||
if (p == nullptr)
|
||||
return nullptr; // Error: Failed to read file name
|
||||
|
@ -767,13 +766,13 @@ void CHostFilename::SetHost(const TCHAR* szHost)
|
|||
/// Copy the Human68k file name elements
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BYTE* CHostFilename::CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast) // static
|
||||
uint8_t* CHostFilename::CopyName(uint8_t* pWrite, const uint8_t* pFirst, const uint8_t* pLast) // static
|
||||
{
|
||||
assert(pWrite);
|
||||
assert(pFirst);
|
||||
assert(pLast);
|
||||
|
||||
for (const BYTE* p = pFirst; p < pLast; p++) {
|
||||
for (const uint8_t* p = pFirst; p < pLast; p++) {
|
||||
*pWrite++ = *p;
|
||||
}
|
||||
|
||||
|
@ -812,42 +811,42 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
nMax = 8;
|
||||
|
||||
// Preparations to adjust the base name segment
|
||||
BYTE szNumber[8];
|
||||
BYTE* pNumber = nullptr;
|
||||
uint8_t szNumber[8];
|
||||
uint8_t* pNumber = nullptr;
|
||||
if (nCount >= 0) {
|
||||
pNumber = &szNumber[8];
|
||||
for (uint32_t i = 0; i < 5; i++) { // Max 5+1 digits (always leave the first 2 bytes of the base name)
|
||||
int n = nCount % 36;
|
||||
nMax--;
|
||||
pNumber--;
|
||||
*pNumber = (BYTE)(n + (n < 10 ? '0' : 'A' - 10));
|
||||
*pNumber = (uint8_t)(n + (n < 10 ? '0' : 'A' - 10));
|
||||
nCount /= 36;
|
||||
if (nCount == 0)
|
||||
break;
|
||||
}
|
||||
nMax--;
|
||||
pNumber--;
|
||||
auto c = (BYTE)((nOption >> 24) & 0x7F);
|
||||
auto c = (uint8_t)((nOption >> 24) & 0x7F);
|
||||
if (c == 0)
|
||||
c = XM6_HOST_FILENAME_MARK;
|
||||
*pNumber = c;
|
||||
}
|
||||
|
||||
// Char conversion
|
||||
BYTE szHuman[FILEPATH_MAX];
|
||||
const BYTE* pFirst = szHuman;
|
||||
BYTE* pLast;
|
||||
BYTE* pExt = nullptr;
|
||||
uint8_t szHuman[FILEPATH_MAX];
|
||||
const uint8_t* pFirst = szHuman;
|
||||
uint8_t* pLast;
|
||||
uint8_t* pExt = nullptr;
|
||||
|
||||
{
|
||||
char szHost[FILEPATH_MAX];
|
||||
strcpy(szHost, m_szHost);
|
||||
auto pRead = (const BYTE*)szHost;
|
||||
BYTE* pWrite = szHuman;
|
||||
auto pRead = (const uint8_t*)szHost;
|
||||
uint8_t* pWrite = szHuman;
|
||||
const auto pPeriod = SeparateExt(pRead);
|
||||
|
||||
for (bool bFirst = true;; bFirst = false) {
|
||||
BYTE c = *pRead++;
|
||||
uint8_t c = *pRead++;
|
||||
switch (c) {
|
||||
case ' ':
|
||||
if (nOption & WINDRV_OPT_REDUCED_SPACE)
|
||||
|
@ -938,11 +937,11 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
// The above example becomes "This.Long.Filename.txt" after conversion
|
||||
|
||||
// Evaluate first char
|
||||
const BYTE* pCut = pFirst;
|
||||
const BYTE* pStop = pExt - nMax; // Allow for up to 17 bytes for extension (leave base name)
|
||||
const uint8_t* pCut = pFirst;
|
||||
const uint8_t* pStop = pExt - nMax; // Allow for up to 17 bytes for extension (leave base name)
|
||||
if (pFirst < pExt) {
|
||||
pCut++; // 1 byte always uses the base name
|
||||
BYTE c = *pFirst;
|
||||
uint8_t c = *pFirst;
|
||||
if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // Specifically 0x81~0x9F 0xE0~0xEF
|
||||
pCut++; // Base name. At least 2 bytes.
|
||||
pStop++; // File extension. Max 16 bytes.
|
||||
|
@ -952,15 +951,15 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
pStop = pFirst;
|
||||
|
||||
// Evaluate base name
|
||||
pCut = (const BYTE*)strchr((const char*)pCut, '.'); // The 2nd byte of Shift-JIS is always 0x40 or higher, so this is ok
|
||||
pCut = (const uint8_t*)strchr((const char*)pCut, '.'); // The 2nd byte of Shift-JIS is always 0x40 or higher, so this is ok
|
||||
if (pCut == nullptr)
|
||||
pCut = pLast;
|
||||
if ((size_t)(pCut - pFirst) > nMax)
|
||||
pCut = pFirst + nMax; // Execute Shift-JIS 2 byte evaluation/adjustment later. Not allowed to do it here.
|
||||
|
||||
// Evaluate extension
|
||||
const BYTE* pSecond = pExt;
|
||||
const BYTE* p;
|
||||
const uint8_t* pSecond = pExt;
|
||||
const uint8_t* p;
|
||||
for (p = pExt - 1; pStop < p; p--) {
|
||||
if (*p == '.')
|
||||
pSecond = p; // The 2nd byte of Shift-JIS is always 0x40 or higher, so this is ok
|
||||
|
@ -972,7 +971,7 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
pCut = pFirst + nMax - nExt;
|
||||
// If in the middle of a 2 byte char, shorten even further
|
||||
for (p = pFirst; p < pCut; p++) {
|
||||
BYTE c = *p;
|
||||
uint8_t c = *p;
|
||||
if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // Specifically 0x81~0x9F 0xE0~0xEF
|
||||
p++;
|
||||
if (p >= pCut) {
|
||||
|
@ -983,7 +982,7 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
}
|
||||
|
||||
// Joining the name
|
||||
BYTE* pWrite = m_szHuman;
|
||||
uint8_t* pWrite = m_szHuman;
|
||||
pWrite = CopyName(pWrite, pFirst, pCut); // Transfer the base name
|
||||
if (pNumber)
|
||||
pWrite = CopyName(pWrite, pNumber, &szNumber[8]); // Transfer the adjustment char
|
||||
|
@ -1019,7 +1018,7 @@ void CHostFilename::ConvertHuman(int nCount)
|
|||
/// Duplicates the file name segment data, then executes the correspoding initialization with ConvertHuman().
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostFilename::CopyHuman(const BYTE* szHuman)
|
||||
void CHostFilename::CopyHuman(const uint8_t* szHuman)
|
||||
{
|
||||
assert(szHuman);
|
||||
assert(strlen((const char*)szHuman) < 23);
|
||||
|
@ -1040,7 +1039,7 @@ void CHostFilename::CopyHuman(const BYTE* szHuman)
|
|||
void CHostFilename::SetEntryName()
|
||||
{
|
||||
// Set file name
|
||||
const BYTE* p = m_szHuman;
|
||||
const uint8_t* p = m_szHuman;
|
||||
size_t i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (p < m_pszHumanExt)
|
||||
|
@ -1059,7 +1058,7 @@ void CHostFilename::SetEntryName()
|
|||
if (*p == '.')
|
||||
p++;
|
||||
for (i = 0; i < 3; i++) {
|
||||
BYTE c = *p;
|
||||
uint8_t c = *p;
|
||||
if (c)
|
||||
p++;
|
||||
m_dirHuman.ext[i] = c;
|
||||
|
@ -1083,7 +1082,7 @@ bool CHostFilename::isReduce() const
|
|||
//---------------------------------------------------------------------------
|
||||
int CHostFilename::CheckAttribute(uint32_t nHumanAttribute) const
|
||||
{
|
||||
BYTE nAttribute = m_dirHuman.attr;
|
||||
uint8_t nAttribute = m_dirHuman.attr;
|
||||
if ((nAttribute & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0)
|
||||
nAttribute |= Human68k::AT_ARCHIVE;
|
||||
|
||||
|
@ -1095,15 +1094,15 @@ int CHostFilename::CheckAttribute(uint32_t nHumanAttribute) const
|
|||
/// Split the extension from Human68k file name
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const BYTE* CHostFilename::SeparateExt(const BYTE* szHuman) // static
|
||||
const uint8_t* CHostFilename::SeparateExt(const uint8_t* szHuman) // static
|
||||
{
|
||||
// Obtain the file name length
|
||||
const size_t nLength = strlen((const char*)szHuman);
|
||||
const BYTE* pFirst = szHuman;
|
||||
const BYTE* pLast = pFirst + nLength;
|
||||
const uint8_t* pFirst = szHuman;
|
||||
const uint8_t* pLast = pFirst + nLength;
|
||||
|
||||
// Confirm the position of the Human68k extension
|
||||
auto pExt = (const BYTE*)strrchr((const char*)pFirst, '.'); // The 2nd byte of Shift-JIS is always 0x40 or higher, so this is ok
|
||||
auto pExt = (const uint8_t*)strrchr((const char*)pFirst, '.'); // The 2nd byte of Shift-JIS is always 0x40 or higher, so this is ok
|
||||
if (pExt == nullptr)
|
||||
pExt = pLast;
|
||||
// Special handling of the pattern where the file name is 20~22 chars, and the 19th char is '.' or ends with '.'
|
||||
|
@ -1186,7 +1185,7 @@ void CHostPath::Clean()
|
|||
/// Specify Human68k side names directly
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostPath::SetHuman(const BYTE* szHuman)
|
||||
void CHostPath::SetHuman(const uint8_t* szHuman)
|
||||
{
|
||||
assert(szHuman);
|
||||
assert(strlen((const char*)szHuman) < HUMAN68K_PATH_MAX);
|
||||
|
@ -1212,7 +1211,7 @@ void CHostPath::SetHost(const TCHAR* szHost)
|
|||
/// Compare arrays (supports wildcards)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int CHostPath::Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast)
|
||||
int CHostPath::Compare(const uint8_t* pFirst, const uint8_t* pLast, const uint8_t* pBufFirst, const uint8_t* pBufLast)
|
||||
{
|
||||
assert(pFirst);
|
||||
assert(pLast);
|
||||
|
@ -1222,10 +1221,10 @@ int CHostPath::Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFi
|
|||
// Compare chars
|
||||
bool bSkip0 = false;
|
||||
bool bSkip1 = false;
|
||||
for (const BYTE* p = pFirst; p < pLast; p++) {
|
||||
for (const uint8_t* p = pFirst; p < pLast; p++) {
|
||||
// Read 1 char
|
||||
BYTE c = *p;
|
||||
BYTE d = '\0';
|
||||
uint8_t c = *p;
|
||||
uint8_t d = '\0';
|
||||
if (pBufFirst < pBufLast)
|
||||
d = *pBufFirst++;
|
||||
|
||||
|
@ -1289,7 +1288,7 @@ int CHostPath::Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFi
|
|||
/// Compare Human68k side name
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool CHostPath::isSameHuman(const BYTE* szHuman) const
|
||||
bool CHostPath::isSameHuman(const uint8_t* szHuman) const
|
||||
{
|
||||
assert(szHuman);
|
||||
|
||||
|
@ -1305,7 +1304,7 @@ bool CHostPath::isSameHuman(const BYTE* szHuman) const
|
|||
return Compare(m_szHuman, m_szHuman + nLength, szHuman, szHuman + n) == 0;
|
||||
}
|
||||
|
||||
bool CHostPath::isSameChild(const BYTE* szHuman) const
|
||||
bool CHostPath::isSameChild(const uint8_t* szHuman) const
|
||||
{
|
||||
assert(szHuman);
|
||||
|
||||
|
@ -1330,14 +1329,14 @@ bool CHostPath::isSameChild(const BYTE* szHuman) const
|
|||
/// Make sure to lock from the top.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, uint32_t nHumanAttribute) const
|
||||
const CHostFilename* CHostPath::FindFilename(const uint8_t* szHuman, uint32_t nHumanAttribute) const
|
||||
{
|
||||
assert(szHuman);
|
||||
|
||||
// Calulate number of chars
|
||||
const BYTE* pFirst = szHuman;
|
||||
const uint8_t* pFirst = szHuman;
|
||||
size_t nLength = strlen((const char*)pFirst);
|
||||
const BYTE* pLast = pFirst + nLength;
|
||||
const uint8_t* pLast = pFirst + nLength;
|
||||
|
||||
// Find something that matches perfectly with either of the stored file names
|
||||
const ring_t* p = (ring_t*)m_cRing.Next();
|
||||
|
@ -1345,8 +1344,8 @@ const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, uint32_t nHuma
|
|||
if (p->f.CheckAttribute(nHumanAttribute) == 0)
|
||||
continue;
|
||||
// Calulate number of chars
|
||||
const BYTE* pBufFirst = p->f.GetHuman();
|
||||
const BYTE* pBufLast = p->f.GetHumanLast();
|
||||
const uint8_t* pBufFirst = p->f.GetHuman();
|
||||
const uint8_t* pBufLast = p->f.GetHumanLast();
|
||||
// Check number of chars
|
||||
if (size_t nBufLength = pBufLast - pBufFirst; nLength != nBufLength)
|
||||
continue;
|
||||
|
@ -1367,15 +1366,15 @@ const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, uint32_t nHuma
|
|||
/// Make sure to lock from the top.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, uint32_t nHumanAttribute, find_t* pFind) const
|
||||
const CHostFilename* CHostPath::FindFilenameWildcard(const uint8_t* szHuman, uint32_t nHumanAttribute, find_t* pFind) const
|
||||
{
|
||||
assert(szHuman);
|
||||
assert(pFind);
|
||||
|
||||
// Split the base file name and Human68k file extension
|
||||
const BYTE* pFirst = szHuman;
|
||||
const BYTE* pLast = pFirst + strlen((const char*)pFirst);
|
||||
const BYTE* pExt = CHostFilename::SeparateExt(pFirst);
|
||||
const uint8_t* pFirst = szHuman;
|
||||
const uint8_t* pLast = pFirst + strlen((const char*)pFirst);
|
||||
const uint8_t* pExt = CHostFilename::SeparateExt(pFirst);
|
||||
|
||||
// Move to the start position
|
||||
auto p = (const ring_t*)m_cRing.Next();
|
||||
|
@ -1416,9 +1415,9 @@ const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, uint32
|
|||
continue;
|
||||
|
||||
// Split the base file name and Human68k file extension
|
||||
const BYTE* pBufFirst = p->f.GetHuman();
|
||||
const BYTE* pBufLast = p->f.GetHumanLast();
|
||||
const BYTE* pBufExt = p->f.GetHumanExt();
|
||||
const uint8_t* pBufFirst = p->f.GetHuman();
|
||||
const uint8_t* pBufLast = p->f.GetHumanLast();
|
||||
const uint8_t* pBufExt = p->f.GetHumanExt();
|
||||
|
||||
// Compare base file name
|
||||
if (Compare(pFirst, pExt, pBufFirst, pBufExt))
|
||||
|
@ -1575,7 +1574,7 @@ void CHostPath::Refresh()
|
|||
if (stat(S2U(szPath), &sb))
|
||||
continue;
|
||||
|
||||
BYTE nHumanAttribute = Human68k::AT_ARCHIVE;
|
||||
uint8_t nHumanAttribute = Human68k::AT_ARCHIVE;
|
||||
if (S_ISDIR(sb.st_mode))
|
||||
nHumanAttribute = Human68k::AT_DIRECTORY;
|
||||
if ((sb.st_mode & 0200) == 0)
|
||||
|
@ -1772,7 +1771,7 @@ void CHostEntry::CleanCache(uint32_t nUnit) const
|
|||
/// Update the cache for the specified path
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostEntry::CleanCache(uint32_t nUnit, const BYTE* szHumanPath) const
|
||||
void CHostEntry::CleanCache(uint32_t nUnit, const uint8_t* szHumanPath) const
|
||||
{
|
||||
assert(szHumanPath);
|
||||
assert(nUnit < DRIVE_MAX);
|
||||
|
@ -1786,7 +1785,7 @@ void CHostEntry::CleanCache(uint32_t nUnit, const BYTE* szHumanPath) const
|
|||
/// Update all cache for the specified path and below
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostEntry::CleanCacheChild(uint32_t nUnit, const BYTE* szHumanPath) const
|
||||
void CHostEntry::CleanCacheChild(uint32_t nUnit, const uint8_t* szHumanPath) const
|
||||
{
|
||||
assert(szHumanPath);
|
||||
assert(nUnit < DRIVE_MAX);
|
||||
|
@ -1800,7 +1799,7 @@ void CHostEntry::CleanCacheChild(uint32_t nUnit, const BYTE* szHumanPath) const
|
|||
/// Delete cache for the specified path
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void CHostEntry::DeleteCache(uint32_t nUnit, const BYTE* szHumanPath) const
|
||||
void CHostEntry::DeleteCache(uint32_t nUnit, const uint8_t* szHumanPath) const
|
||||
{
|
||||
assert(szHumanPath);
|
||||
assert(nUnit < DRIVE_MAX);
|
||||
|
@ -1880,7 +1879,7 @@ bool CHostEntry::isMediaOffline(uint32_t nUnit) const
|
|||
/// Get media byte
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BYTE CHostEntry::GetMediaByte(uint32_t nUnit) const
|
||||
uint8_t CHostEntry::GetMediaByte(uint32_t nUnit) const
|
||||
{
|
||||
assert(nUnit < DRIVE_MAX);
|
||||
assert(m_pDrv[nUnit]);
|
||||
|
@ -1990,15 +1989,15 @@ bool CHostEntry::GetCapacityCache(uint32_t nUnit, Human68k::capacity_t* pCapacit
|
|||
/// If the array ends with a '/' treat it as an empty array and don't trow an error.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const BYTE* CHostDrv::SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer) // static
|
||||
const uint8_t* CHostDrv::SeparateCopyFilename(const uint8_t* szHuman, uint8_t* szBuffer) // static
|
||||
{
|
||||
assert(szHuman);
|
||||
assert(szBuffer);
|
||||
|
||||
const size_t nMax = 22;
|
||||
const BYTE* p = szHuman;
|
||||
const uint8_t* p = szHuman;
|
||||
|
||||
BYTE c = *p++; // Read
|
||||
uint8_t c = *p++; // Read
|
||||
if (c != '/' && c != '\\')
|
||||
return nullptr; // Error: Invalid path name
|
||||
|
||||
|
@ -2263,7 +2262,7 @@ void CHostFcb::SetFilename(const TCHAR* szFilename)
|
|||
strcpy(m_szFilename, szFilename);
|
||||
}
|
||||
|
||||
void CHostFcb::SetHumanPath(const BYTE* szHumanPath)
|
||||
void CHostFcb::SetHumanPath(const uint8_t* szHumanPath)
|
||||
{
|
||||
assert(szHumanPath);
|
||||
assert(strlen((const char*)szHumanPath) < HUMAN68K_PATH_MAX);
|
||||
|
@ -2327,12 +2326,12 @@ bool CHostFcb::Open()
|
|||
/// Return -1 if error is thrown.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
uint32_t CHostFcb::Read(BYTE* pBuffer, uint32_t nSize)
|
||||
uint32_t CHostFcb::Read(uint8_t* pBuffer, uint32_t nSize)
|
||||
{
|
||||
assert(pBuffer);
|
||||
assert(m_pFile);
|
||||
|
||||
size_t nResult = fread(pBuffer, sizeof(BYTE), nSize, m_pFile);
|
||||
size_t nResult = fread(pBuffer, sizeof(uint8_t), nSize, m_pFile);
|
||||
if (ferror(m_pFile))
|
||||
nResult = (size_t)-1;
|
||||
|
||||
|
@ -2347,12 +2346,12 @@ uint32_t CHostFcb::Read(BYTE* pBuffer, uint32_t nSize)
|
|||
/// Return -1 if error is thrown.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
uint32_t CHostFcb::Write(const BYTE* pBuffer, uint32_t nSize)
|
||||
uint32_t CHostFcb::Write(const uint8_t* pBuffer, uint32_t nSize)
|
||||
{
|
||||
assert(pBuffer);
|
||||
assert(m_pFile);
|
||||
|
||||
size_t nResult = fwrite(pBuffer, sizeof(BYTE), nSize, m_pFile);
|
||||
size_t nResult = fwrite(pBuffer, sizeof(uint8_t), nSize, m_pFile);
|
||||
if (ferror(m_pFile))
|
||||
nResult = (size_t)-1;
|
||||
|
||||
|
@ -2752,7 +2751,7 @@ int CFileSys::RemoveDir(uint32_t nUnit, const Human68k::namests_t* pNamests) con
|
|||
return FS_DIRNOTFND;
|
||||
|
||||
// Delete cache
|
||||
BYTE szHuman[HUMAN68K_PATH_MAX + 24];
|
||||
uint8_t szHuman[HUMAN68K_PATH_MAX + 24];
|
||||
assert(strlen((const char*)f.GetHumanPath()) +
|
||||
strlen((const char*)f.GetHumanFilename()) < HUMAN68K_PATH_MAX + 24);
|
||||
strcpy((char*)szHuman, (const char*)f.GetHumanPath());
|
||||
|
@ -3006,7 +3005,7 @@ int CFileSys::Files(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pN
|
|||
}
|
||||
|
||||
// Store search results
|
||||
pFiles->attr = (BYTE)pHostFiles->GetAttribute();
|
||||
pFiles->attr = (uint8_t)pHostFiles->GetAttribute();
|
||||
pFiles->date = pHostFiles->GetDate();
|
||||
pFiles->time = pHostFiles->GetTime();
|
||||
pFiles->size = pHostFiles->GetSize();
|
||||
|
@ -3054,7 +3053,7 @@ int CFileSys::NFiles(uint32_t nUnit, uint32_t nKey, Human68k::files_t* pFiles)
|
|||
assert(pFiles->offset == 0);
|
||||
|
||||
// Store search results
|
||||
pFiles->attr = (BYTE)pHostFiles->GetAttribute();
|
||||
pFiles->attr = (uint8_t)pHostFiles->GetAttribute();
|
||||
pFiles->date = pHostFiles->GetDate();
|
||||
pFiles->time = pHostFiles->GetTime();
|
||||
pFiles->size = pHostFiles->GetSize();
|
||||
|
@ -3245,7 +3244,7 @@ int CFileSys::Close(uint32_t nUnit, uint32_t nKey, const Human68k::fcb_t* /* pFc
|
|||
/// Clean exit when 0 bytes are read.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int CFileSys::Read(uint32_t nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, uint32_t nSize)
|
||||
int CFileSys::Read(uint32_t nKey, Human68k::fcb_t* pFcb, uint8_t* pBuffer, uint32_t nSize)
|
||||
{
|
||||
assert(nKey);
|
||||
assert(pFcb);
|
||||
|
@ -3284,7 +3283,7 @@ int CFileSys::Read(uint32_t nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, uint32_t
|
|||
/// Truncate file if 0 bytes are written.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int CFileSys::Write(uint32_t nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, uint32_t nSize)
|
||||
int CFileSys::Write(uint32_t nKey, Human68k::fcb_t* pFcb, const uint8_t* pBuffer, uint32_t nSize)
|
||||
{
|
||||
assert(nKey);
|
||||
assert(pFcb);
|
||||
|
@ -3462,7 +3461,7 @@ int CFileSys::CtrlDrive(uint32_t nUnit, Human68k::ctrldrive_t* pCtrlDrive) const
|
|||
switch (pCtrlDrive->status) {
|
||||
case 0: // Inspect status
|
||||
case 9: // Inspect status 2
|
||||
pCtrlDrive->status = (BYTE)m_cEntry.GetStatus(nUnit);
|
||||
pCtrlDrive->status = (uint8_t)m_cEntry.GetStatus(nUnit);
|
||||
return pCtrlDrive->status;
|
||||
|
||||
case 1: // Eject
|
||||
|
@ -3501,7 +3500,7 @@ int CFileSys::GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const
|
|||
return FS_FATAL_INVALIDUNIT;
|
||||
|
||||
Human68k::capacity_t cap;
|
||||
BYTE media = Human68k::MEDIA_REMOTE;
|
||||
uint8_t media = Human68k::MEDIA_REMOTE;
|
||||
if (nUnit < m_nUnits) {
|
||||
media = m_cEntry.GetMediaByte(nUnit);
|
||||
|
||||
|
@ -3549,11 +3548,11 @@ int CFileSys::GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const
|
|||
// Set DPB
|
||||
pDpb->sector_size = cap.bytes; // Bytes per sector
|
||||
pDpb->cluster_size =
|
||||
(BYTE)(cap.sectors - 1); // Sectors per cluster - 1
|
||||
pDpb->shift = (BYTE)nShift; // Number of cluster → sector shifts
|
||||
(uint8_t)(cap.sectors - 1); // Sectors per cluster - 1
|
||||
pDpb->shift = (uint8_t)nShift; // Number of cluster → sector shifts
|
||||
pDpb->fat_sector = (uint16_t)nFat; // First FAT sector number
|
||||
pDpb->fat_max = 1; // Number of FAT memory spaces
|
||||
pDpb->fat_size = (BYTE)cap.sectors; // Number of sectors controlled by FAT (excluding copies)
|
||||
pDpb->fat_size = (uint8_t)cap.sectors; // Number of sectors controlled by FAT (excluding copies)
|
||||
pDpb->file_max =
|
||||
(uint16_t)(cap.sectors * cap.bytes / 0x20); // Number of files in the root directory
|
||||
pDpb->data_sector = (uint16_t)nData; // First sector number of data memory
|
||||
|
@ -3572,7 +3571,7 @@ int CFileSys::GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const
|
|||
/// Buffer size is hard coded to $200 byte.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int CFileSys::DiskRead(uint32_t nUnit, BYTE* pBuffer, uint32_t nSector, uint32_t nSize)
|
||||
int CFileSys::DiskRead(uint32_t nUnit, uint8_t* pBuffer, uint32_t nSector, uint32_t nSize)
|
||||
{
|
||||
assert(pBuffer);
|
||||
|
||||
|
@ -3828,14 +3827,14 @@ void CFileSys::InitOption(const Human68k::argument_t* pArgument)
|
|||
// Initialize number of drives
|
||||
m_nDrives = 0;
|
||||
|
||||
const BYTE* pp = pArgument->buf;
|
||||
const uint8_t* pp = pArgument->buf;
|
||||
pp += strlen((const char*)pp) + 1;
|
||||
|
||||
uint32_t nOption = m_nOptionDefault;
|
||||
for (;;) {
|
||||
assert(pp < pArgument->buf + sizeof(*pArgument));
|
||||
const BYTE* p = pp;
|
||||
BYTE c = *p++;
|
||||
const uint8_t* p = pp;
|
||||
uint8_t c = *p++;
|
||||
if (c == '\0')
|
||||
break;
|
||||
|
||||
|
|
|
@ -106,48 +106,48 @@ namespace Human68k {
|
|||
const static int MEDIA_REMOTE = 0xF3; ///< Remote drive
|
||||
|
||||
struct namests_t {
|
||||
BYTE wildcard; ///< Wildcard character length
|
||||
BYTE drive; ///< Drive number
|
||||
BYTE path[65]; ///< Path (subdirectory +/)
|
||||
BYTE name[8]; ///< File name (PADDING 0x20)
|
||||
BYTE ext[3]; ///< Extension (PADDING 0x20)
|
||||
BYTE add[10]; ///< File name addition (PADDING 0x00)
|
||||
uint8_t wildcard; ///< Wildcard character length
|
||||
uint8_t drive; ///< Drive number
|
||||
uint8_t path[65]; ///< Path (subdirectory +/)
|
||||
uint8_t name[8]; ///< File name (PADDING 0x20)
|
||||
uint8_t ext[3]; ///< Extension (PADDING 0x20)
|
||||
uint8_t add[10]; ///< File name addition (PADDING 0x00)
|
||||
|
||||
void GetCopyPath(BYTE* szPath) const;
|
||||
void GetCopyFilename(BYTE* szFilename) const;
|
||||
void GetCopyPath(uint8_t* szPath) const;
|
||||
void GetCopyFilename(uint8_t* szFilename) const;
|
||||
};
|
||||
|
||||
struct files_t {
|
||||
BYTE fatr; ///< + 0 search attribute; read-only
|
||||
// BYTE drive; ///< + 1 drive number; read-only
|
||||
uint8_t fatr; ///< + 0 search attribute; read-only
|
||||
// uint8_t drive; ///< + 1 drive number; read-only
|
||||
uint32_t sector; ///< + 2 directory sector; DOS _FILES first address substitute
|
||||
// uint16_t cluster; ///< + 6 directory cluster; details unknown (unused)
|
||||
uint16_t offset; ///< + 8 directory entry; write-only
|
||||
// BYTE name[8]; ///< +10 working file name; write-only (unused)
|
||||
// BYTE ext[3]; ///< +18 working extension; write-only (unused)
|
||||
BYTE attr; ///< +21 file attribute; write-only
|
||||
// uint8_t name[8]; ///< +10 working file name; write-only (unused)
|
||||
// uint8_t ext[3]; ///< +18 working extension; write-only (unused)
|
||||
uint8_t attr; ///< +21 file attribute; write-only
|
||||
uint16_t time; ///< +22 last change time of day; write-only
|
||||
uint16_t date; ///< +24 last change date; write-only
|
||||
uint32_t size; ///< +26 file size; write-only
|
||||
BYTE full[23]; ///< +30 full name; write-only
|
||||
uint8_t full[23]; ///< +30 full name; write-only
|
||||
};
|
||||
|
||||
struct fcb_t {
|
||||
// BYTE pad00[6]; ///< + 0~+ 5 (unused)
|
||||
// uint8_t pad00[6]; ///< + 0~+ 5 (unused)
|
||||
uint32_t fileptr; ///< + 6~+ 9 file pointer
|
||||
// BYTE pad01[4]; ///< +10~+13 (unused)
|
||||
// uint8_t pad01[4]; ///< +10~+13 (unused)
|
||||
uint16_t mode; ///< +14~+15 open mode
|
||||
// BYTE pad02[16]; ///< +16~+31 (unused)
|
||||
// uint8_t pad02[16]; ///< +16~+31 (unused)
|
||||
// uint32_t zero; ///< +32~+35 zeros are written when opened (unused)
|
||||
// BYTE name[8]; ///< +36~+43 file name (PADDING 0x20) (unused)
|
||||
// BYTE ext[3]; ///< +44~+46 extension (PADDING 0x20) (unused)
|
||||
BYTE attr; ///< +47 file attribute
|
||||
// BYTE add[10]; ///< +48~+57 file name addition (PADDING 0x00) (unused)
|
||||
// uint8_t name[8]; ///< +36~+43 file name (PADDING 0x20) (unused)
|
||||
// uint8_t ext[3]; ///< +44~+46 extension (PADDING 0x20) (unused)
|
||||
uint8_t attr; ///< +47 file attribute
|
||||
// uint8_t add[10]; ///< +48~+57 file name addition (PADDING 0x00) (unused)
|
||||
uint16_t time; ///< +58~+59 last change time of day
|
||||
uint16_t date; ///< +60~+61 last change date
|
||||
// uint16_t cluster; ///< +62~+63 cluster number (unused)
|
||||
uint32_t size; ///< +64~+67 file size
|
||||
// BYTE pad03[28]; ///< +68~+95 FAT cache (unused)
|
||||
// uint8_t pad03[28]; ///< +68~+95 FAT cache (unused)
|
||||
};
|
||||
|
||||
struct capacity_t {
|
||||
|
@ -158,32 +158,32 @@ namespace Human68k {
|
|||
};
|
||||
|
||||
struct ctrldrive_t {
|
||||
BYTE status; ///< +13 status
|
||||
BYTE pad[3]; ///< Padding
|
||||
uint8_t status; ///< +13 status
|
||||
uint8_t pad[3]; ///< Padding
|
||||
};
|
||||
|
||||
struct dpb_t {
|
||||
uint16_t sector_size; ///< + 0 Number of bytes in one sector
|
||||
BYTE cluster_size; ///< + 2 Number sectors in one cluster -1
|
||||
BYTE shift; ///< + 3 Number of cluster→sector shifts
|
||||
uint8_t cluster_size; ///< + 2 Number sectors in one cluster -1
|
||||
uint8_t shift; ///< + 3 Number of cluster→sector shifts
|
||||
uint16_t fat_sector; ///< + 4 FAT first sector number
|
||||
BYTE fat_max; ///< + 6 FAT storage quantity
|
||||
BYTE fat_size; ///< + 7 FAT controlled sector number (excluding duplicates)
|
||||
uint8_t fat_max; ///< + 6 FAT storage quantity
|
||||
uint8_t fat_size; ///< + 7 FAT controlled sector number (excluding duplicates)
|
||||
uint16_t file_max; ///< + 8 Number of files in the root directory
|
||||
uint16_t data_sector; ///< +10 First sector number of data storage
|
||||
uint16_t cluster_max; ///< +12 Total number of clusters +1
|
||||
uint16_t root_sector; ///< +14 First sector number of root directory
|
||||
// uint32_t driverentry; ///< +16 Device driver pointer (unused)
|
||||
BYTE media; ///< +20 Media identifier
|
||||
// BYTE flag; ///< +21 Flag used by DPB (unused)
|
||||
uint8_t media; ///< +20 Media identifier
|
||||
// uint8_t flag; ///< +21 Flag used by DPB (unused)
|
||||
};
|
||||
|
||||
/// Directory entry struct
|
||||
struct dirent_t {
|
||||
BYTE name[8]; ///< + 0 File name (PADDING 0x20)
|
||||
BYTE ext[3]; ///< + 8 Extension (PADDING 0x20)
|
||||
BYTE attr; ///< +11 File attribute
|
||||
BYTE add[10]; ///< +12 File name addition (PADDING 0x00)
|
||||
uint8_t name[8]; ///< + 0 File name (PADDING 0x20)
|
||||
uint8_t ext[3]; ///< + 8 Extension (PADDING 0x20)
|
||||
uint8_t attr; ///< +11 File attribute
|
||||
uint8_t add[10]; ///< +12 File name addition (PADDING 0x00)
|
||||
uint16_t time; ///< +22 Last change time of day
|
||||
uint16_t date; ///< +24 Last change date
|
||||
uint16_t cluster; ///< +26 Cluster number
|
||||
|
@ -192,7 +192,7 @@ namespace Human68k {
|
|||
|
||||
/// IOCTRL parameter union
|
||||
union ioctrl_t {
|
||||
BYTE buffer[8]; ///< Access in byte units
|
||||
uint8_t buffer[8]; ///< Access in byte units
|
||||
uint32_t param; ///< Parameter (First 4 bytes)
|
||||
uint16_t media; ///< Media byte (First 2 bytes)
|
||||
};
|
||||
|
@ -203,7 +203,7 @@ namespace Human68k {
|
|||
so setting to a length longer than HUMAN68K_PATH_MAX
|
||||
*/
|
||||
struct argument_t {
|
||||
BYTE buf[256]; ///< Command line argument
|
||||
uint8_t buf[256]; ///< Command line argument
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -423,15 +423,15 @@ public:
|
|||
void SetHost(const TCHAR* szHost); ///< Set the name of the host
|
||||
const TCHAR* GetHost() const { return m_szHost; } ///< Get the name of the host
|
||||
void ConvertHuman(int nCount = -1); ///< Convert the Human68k name
|
||||
void CopyHuman(const BYTE* szHuman); ///< Copy the Human68k name
|
||||
void CopyHuman(const uint8_t* szHuman); ///< Copy the Human68k name
|
||||
bool isReduce() const; ///< Inspect if the Human68k name is generated
|
||||
bool isCorrect() const { return m_bCorrect; } ///< Inspect if the Human68k file name adhers to naming rules
|
||||
const BYTE* GetHuman() const { return m_szHuman; } ///< Get Human68k file name
|
||||
const BYTE* GetHumanLast() const
|
||||
const uint8_t* GetHuman() const { return m_szHuman; } ///< Get Human68k file name
|
||||
const uint8_t* GetHumanLast() const
|
||||
{ return m_pszHumanLast; } ///< Get Human68k file name
|
||||
const BYTE* GetHumanExt() const { return m_pszHumanExt; }///< Get Human68k file name
|
||||
const uint8_t* GetHumanExt() const { return m_pszHumanExt; }///< Get Human68k file name
|
||||
void SetEntryName(); ///< Set Human68k directory entry
|
||||
void SetEntryAttribute(BYTE nHumanAttribute)
|
||||
void SetEntryAttribute(uint8_t nHumanAttribute)
|
||||
{ m_dirHuman.attr = nHumanAttribute; } ///< Set Human68k directory entry
|
||||
void SetEntrySize(uint32_t nHumanSize)
|
||||
{ m_dirHuman.size = nHumanSize; } ///< Set Human68k directory entry
|
||||
|
@ -449,16 +449,16 @@ public:
|
|||
///< Determine Human68k directory entry match
|
||||
|
||||
// Path name operations
|
||||
static const BYTE* SeparateExt(const BYTE* szHuman); ///< Extract extension from Human68k file name
|
||||
static const uint8_t* SeparateExt(const uint8_t* szHuman); ///< Extract extension from Human68k file name
|
||||
|
||||
private:
|
||||
static BYTE* CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast);
|
||||
static uint8_t* CopyName(uint8_t* pWrite, const uint8_t* pFirst, const uint8_t* pLast);
|
||||
///< Copy Human68k file name elements
|
||||
|
||||
const BYTE* m_pszHumanLast = nullptr; ///< Last position of the Human68k internal name of the relevant entry
|
||||
const BYTE* m_pszHumanExt = nullptr; ///< Position of the extension of the Human68k internal name of the relevant entry
|
||||
const uint8_t* m_pszHumanLast = nullptr; ///< Last position of the Human68k internal name of the relevant entry
|
||||
const uint8_t* m_pszHumanExt = nullptr; ///< Position of the extension of the Human68k internal name of the relevant entry
|
||||
bool m_bCorrect = false; ///< TRUE if the relevant entry of the Human68k internal name is correct
|
||||
BYTE m_szHuman[24]; ///< Human68k internal name of the relevant entry
|
||||
uint8_t m_szHuman[24]; ///< Human68k internal name of the relevant entry
|
||||
Human68k::dirent_t m_dirHuman; ///< All information for the Human68k relevant entry
|
||||
TCHAR m_szHost[FILEPATH_MAX]; ///< The host name of the relevant entry (variable length)
|
||||
};
|
||||
|
@ -510,14 +510,14 @@ public:
|
|||
|
||||
void Clean(); ///< Initialialize for reuse
|
||||
|
||||
void SetHuman(const BYTE* szHuman); ///< Directly specify the name on the Human68k side
|
||||
void SetHuman(const uint8_t* szHuman); ///< Directly specify the name on the Human68k side
|
||||
void SetHost(const TCHAR* szHost); ///< Directly specify the name on the host side
|
||||
bool isSameHuman(const BYTE* szHuman) const; ///< Compare the name on the Human68k side
|
||||
bool isSameChild(const BYTE* szHuman) const; ///< Compare the name on the Human68k side
|
||||
bool isSameHuman(const uint8_t* szHuman) const; ///< Compare the name on the Human68k side
|
||||
bool isSameChild(const uint8_t* szHuman) const; ///< Compare the name on the Human68k side
|
||||
const TCHAR* GetHost() const { return m_szHost; } ///< Obtain the name on the host side
|
||||
const CHostFilename* FindFilename(const BYTE* szHuman, uint32_t nHumanAttribute = Human68k::AT_ALL) const;
|
||||
const CHostFilename* FindFilename(const uint8_t* szHuman, uint32_t nHumanAttribute = Human68k::AT_ALL) const;
|
||||
///< Find file name
|
||||
const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, uint32_t nHumanAttribute, find_t* pFind) const;
|
||||
const CHostFilename* FindFilenameWildcard(const uint8_t* szHuman, uint32_t nHumanAttribute, find_t* pFind) const;
|
||||
///< Find file name (with support for wildcards)
|
||||
bool isRefresh() const; ///< Check that the file change has been done
|
||||
void Refresh(); ///< Refresh file
|
||||
|
@ -531,14 +531,14 @@ public:
|
|||
private:
|
||||
static ring_t* Alloc(size_t nLength); ///< Allocate memory for the file name
|
||||
static void Free(ring_t* pRing); ///< Release memory for the file name
|
||||
static int Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast);
|
||||
static int Compare(const uint8_t* pFirst, const uint8_t* pLast, const uint8_t* pBufFirst, const uint8_t* pBufLast);
|
||||
///< Compare string (with support for wildcards)
|
||||
|
||||
CRing m_cRing; ///< For CHostFilename linking
|
||||
time_t m_tBackup = 0; ///< For time stamp restoration
|
||||
bool m_bRefresh = true; ///< Refresh flag
|
||||
uint32_t m_nId = 0; ///< Unique ID (When the value has changed, it means an update has been made)
|
||||
BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< The internal Human68k name for the relevant entry
|
||||
uint8_t m_szHuman[HUMAN68K_PATH_MAX]; ///< The internal Human68k name for the relevant entry
|
||||
TCHAR m_szHost[FILEPATH_MAX]; ///< The host side name for the relevant entry
|
||||
|
||||
static uint32_t g_nId; ///< Counter for the unique ID generation
|
||||
|
@ -595,9 +595,9 @@ public:
|
|||
uint16_t GetDate() const { return m_dirHuman.date; } ///< Get Human68k date
|
||||
uint16_t GetTime() const { return m_dirHuman.time; } ///< Get Human68k time
|
||||
uint32_t GetSize() const { return m_dirHuman.size; } ///< Get Human68k file size
|
||||
const BYTE* GetHumanFilename() const { return m_szHumanFilename; }///< Get Human68k file name
|
||||
const BYTE* GetHumanResult() const { return m_szHumanResult; } ///< Get Human68k file name search results
|
||||
const BYTE* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name
|
||||
const uint8_t* GetHumanFilename() const { return m_szHumanFilename; }///< Get Human68k file name
|
||||
const uint8_t* GetHumanResult() const { return m_szHumanResult; } ///< Get Human68k file name search results
|
||||
const uint8_t* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name
|
||||
|
||||
private:
|
||||
uint32_t m_nKey = 0; ///< FILES buffer address for Human68k; 0 is unused
|
||||
|
@ -605,9 +605,9 @@ private:
|
|||
uint32_t m_nHumanAttribute = 0; ///< Human68k search attribute
|
||||
CHostPath::find_t m_findNext = {}; ///< Next search location data
|
||||
Human68k::dirent_t m_dirHuman = {}; ///< Search results: Human68k file data
|
||||
BYTE m_szHumanFilename[24] = {}; ///< Human68k file name
|
||||
BYTE m_szHumanResult[24] = {}; ///< Search results: Human68k file name
|
||||
BYTE m_szHumanPath[HUMAN68K_PATH_MAX] = {}; ///< Human68k path name
|
||||
uint8_t m_szHumanFilename[24] = {}; ///< Human68k file name
|
||||
uint8_t m_szHumanResult[24] = {}; ///< Search results: Human68k file name
|
||||
uint8_t m_szHumanPath[HUMAN68K_PATH_MAX] = {}; ///< Human68k path name
|
||||
TCHAR m_szHostResult[FILEPATH_MAX] = {}; ///< Search results: host's full path name
|
||||
};
|
||||
|
||||
|
@ -657,13 +657,13 @@ public:
|
|||
bool isUpdate() const { return m_bUpdate; } ///< Get update state
|
||||
bool SetMode(uint32_t nHumanMode); ///< Set file open mode
|
||||
void SetFilename(const TCHAR* szFilename); ///< Set file name
|
||||
void SetHumanPath(const BYTE* szHumanPath); ///< Set Human68k path name
|
||||
const BYTE* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name
|
||||
void SetHumanPath(const uint8_t* szHumanPath); ///< Set Human68k path name
|
||||
const uint8_t* GetHumanPath() const { return m_szHumanPath; } ///< Get Human68k path name
|
||||
|
||||
bool Create(uint32_t nHumanAttribute, bool bForce); ///< Create file
|
||||
bool Open(); ///< Open file
|
||||
uint32_t Read(BYTE* pBuffer, uint32_t nSize); ///< Read file
|
||||
uint32_t Write(const BYTE* pBuffer, uint32_t nSize); ///< Write file
|
||||
uint32_t Read(uint8_t* pBuffer, uint32_t nSize); ///< Read file
|
||||
uint32_t Write(const uint8_t* pBuffer, uint32_t nSize); ///< Write file
|
||||
bool Truncate() const; ///< Truncate file
|
||||
uint32_t Seek(uint32_t nOffset, Human68k::seek_t nHumanSeek); ///< Seek file
|
||||
bool TimeStamp(uint32_t nHumanTime) const; ///< Set file time stamp
|
||||
|
@ -675,7 +675,7 @@ private:
|
|||
FILE* m_pFile = nullptr; ///< Host side file object
|
||||
const char* m_pszMode = nullptr; ///< Host side file open mode
|
||||
bool m_bFlag = false; ///< Host side file open flag
|
||||
BYTE m_szHumanPath[HUMAN68K_PATH_MAX] = {}; ///< Human68k path name
|
||||
uint8_t m_szHumanPath[HUMAN68K_PATH_MAX] = {}; ///< Human68k path name
|
||||
TCHAR m_szFilename[FILEPATH_MAX] = {}; ///< Host side file name
|
||||
};
|
||||
|
||||
|
@ -726,7 +726,7 @@ public:
|
|||
bool isWriteProtect() const { return m_bWriteProtect; }
|
||||
bool isEnable() const { return m_bEnable; } ///< Is it accessible?
|
||||
bool isMediaOffline() const;
|
||||
BYTE GetMediaByte() const;
|
||||
uint8_t GetMediaByte() const;
|
||||
uint32_t GetStatus() const;
|
||||
void SetEnable(bool); ///< Set media status
|
||||
bool CheckMedia(); ///< Check if media was changed
|
||||
|
@ -739,17 +739,17 @@ public:
|
|||
|
||||
// Cache operations
|
||||
void CleanCache() const; ///< Update all cache
|
||||
void CleanCache(const BYTE* szHumanPath); ///< Update cache for the specified path
|
||||
void CleanCacheChild(const BYTE* szHumanPath) const; ///< Update all cache below the specified path
|
||||
void DeleteCache(const BYTE* szHumanPath); ///< Delete the cache for the specified path
|
||||
CHostPath* FindCache(const BYTE* szHuman); ///< Inspect if the specified path is cached
|
||||
void CleanCache(const uint8_t* szHumanPath); ///< Update cache for the specified path
|
||||
void CleanCacheChild(const uint8_t* szHumanPath) const; ///< Update all cache below the specified path
|
||||
void DeleteCache(const uint8_t* szHumanPath); ///< Delete the cache for the specified path
|
||||
CHostPath* FindCache(const uint8_t* szHuman); ///< Inspect if the specified path is cached
|
||||
CHostPath* CopyCache(CHostFiles* pFiles); ///< Acquire the host side name on the basis of cache information
|
||||
CHostPath* MakeCache(CHostFiles* pFiles); ///< Get all required data to construct a host side name
|
||||
bool Find(CHostFiles* pFiles); ///< Find host side name (path + file name (can be abbreviated) + attribute)
|
||||
|
||||
private:
|
||||
// Path name operations
|
||||
static const BYTE* SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer);
|
||||
static const uint8_t* SeparateCopyFilename(const uint8_t* szHuman, uint8_t* szBuffer);
|
||||
///< Split and copy the first element of the Human68k full path name
|
||||
|
||||
/// For memory management
|
||||
|
@ -791,9 +791,9 @@ public:
|
|||
// Cache operations
|
||||
void CleanCache() const; ///< Update all cache
|
||||
void CleanCache(uint32_t nUnit) const; ///< Update cache for the specified unit
|
||||
void CleanCache(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Update cache for the specified path
|
||||
void CleanCacheChild(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Update cache below the specified path
|
||||
void DeleteCache(uint32_t nUnit, const BYTE* szHumanPath) const; ///< Delete cache for the specified path
|
||||
void CleanCache(uint32_t nUnit, const uint8_t* szHumanPath) const; ///< Update cache for the specified path
|
||||
void CleanCacheChild(uint32_t nUnit, const uint8_t* szHumanPath) const; ///< Update cache below the specified path
|
||||
void DeleteCache(uint32_t nUnit, const uint8_t* szHumanPath) const; ///< Delete cache for the specified path
|
||||
bool Find(uint32_t nUnit, CHostFiles* pFiles) const; ///< Find host side name (path + file name (can be abbreviated) + attribute)
|
||||
void ShellNotify(uint32_t nEvent, const TCHAR* szPath); ///< Notify status change in the host side file system
|
||||
|
||||
|
@ -802,7 +802,7 @@ public:
|
|||
bool isWriteProtect(uint32_t nUnit) const;
|
||||
bool isEnable(uint32_t nUnit) const; ///< Is it accessible?
|
||||
bool isMediaOffline(uint32_t nUnit) const;
|
||||
BYTE GetMediaByte(uint32_t nUnit) const;
|
||||
uint8_t GetMediaByte(uint32_t nUnit) const;
|
||||
uint32_t GetStatus(uint32_t nUnit) const; ///< Get drive status
|
||||
bool CheckMedia(uint32_t nUnit) const; ///< Media change check
|
||||
void Eject(uint32_t nUnit) const;
|
||||
|
@ -875,9 +875,9 @@ public:
|
|||
int Open(uint32_t nUnit, uint32_t nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb);
|
||||
///< $4A - Open file
|
||||
int Close(uint32_t nUnit, uint32_t nKey, const Human68k::fcb_t* pFcb); ///< $4B - Close file
|
||||
int Read(uint32_t nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, uint32_t nSize);
|
||||
int Read(uint32_t nKey, Human68k::fcb_t* pFcb, uint8_t* pAddress, uint32_t nSize);
|
||||
///< $4C - Read file
|
||||
int Write(uint32_t nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, uint32_t nSize);
|
||||
int Write(uint32_t nKey, Human68k::fcb_t* pFcb, const uint8_t* pAddress, uint32_t nSize);
|
||||
///< $4D - Write file
|
||||
int Seek(uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nSeek, int nOffset); ///< $4E - Seek file
|
||||
uint32_t TimeStamp(uint32_t nUnit, uint32_t nKey, Human68k::fcb_t* pFcb, uint32_t nHumanTime);
|
||||
|
@ -885,7 +885,7 @@ public:
|
|||
int GetCapacity(uint32_t nUnit, Human68k::capacity_t* pCapacity) const; ///< $50 - Get capacity
|
||||
int CtrlDrive(uint32_t nUnit, Human68k::ctrldrive_t* pCtrlDrive) const; ///< $51 - Inspect / control drive status
|
||||
int GetDPB(uint32_t nUnit, Human68k::dpb_t* pDpb) const; ///< $52 - Get DPB
|
||||
int DiskRead(uint32_t nUnit, BYTE* pBuffer, uint32_t nSector, uint32_t nSize); ///< $53 - Read sectors
|
||||
int DiskRead(uint32_t nUnit, uint8_t* pBuffer, uint32_t nSector, uint32_t nSize); ///< $53 - Read sectors
|
||||
int DiskWrite(uint32_t nUnit) const; ///< $54 - Write sectors
|
||||
int Ioctrl(uint32_t nUnit, uint32_t nFunction, Human68k::ioctrl_t* pIoctrl); ///< $55 - IOCTRL
|
||||
int Flush(uint32_t nUnit) const; ///< $56 - Flush
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "os.h"
|
||||
#include "ctapdriver.h"
|
||||
#include "log.h"
|
||||
#include "rasutil.h"
|
||||
|
@ -411,12 +410,12 @@ void CTapDriver::Flush()
|
|||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
while (PendingPackets()) {
|
||||
array<BYTE, ETH_FRAME_LEN> m_garbage_buffer;
|
||||
array<uint8_t, ETH_FRAME_LEN> m_garbage_buffer;
|
||||
(void)Receive(m_garbage_buffer.data());
|
||||
}
|
||||
}
|
||||
|
||||
void CTapDriver::GetMacAddr(BYTE *mac) const
|
||||
void CTapDriver::GetMacAddr(uint8_t *mac) const
|
||||
{
|
||||
assert(mac);
|
||||
|
||||
|
@ -447,19 +446,19 @@ bool CTapDriver::PendingPackets() const
|
|||
}
|
||||
|
||||
// See https://stackoverflow.com/questions/21001659/crc32-algorithm-implementation-in-c-without-a-look-up-table-and-with-a-public-li
|
||||
uint32_t CTapDriver::Crc32(const BYTE *buf, int length) {
|
||||
uint32_t CTapDriver::Crc32(const uint8_t *buf, int length) {
|
||||
uint32_t crc = 0xffffffff;
|
||||
for (int i = 0; i < length; i++) {
|
||||
crc ^= buf[i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
const uint32_t mask = -((int)crc & 1);
|
||||
const uint32_t mask = -(static_cast<int>(crc) & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
int CTapDriver::Receive(BYTE *buf)
|
||||
int CTapDriver::Receive(uint8_t *buf)
|
||||
{
|
||||
assert(m_hTAP != -1);
|
||||
|
||||
|
@ -469,8 +468,8 @@ int CTapDriver::Receive(BYTE *buf)
|
|||
}
|
||||
|
||||
// Receive
|
||||
auto dwReceived = (uint32_t)read(m_hTAP, buf, ETH_FRAME_LEN);
|
||||
if (dwReceived == (uint32_t)-1) {
|
||||
auto dwReceived = static_cast<uint32_t>(read(m_hTAP, buf, ETH_FRAME_LEN));
|
||||
if (dwReceived == static_cast<uint32_t>(-1)) {
|
||||
LOGWARN("%s Error occured while receiving a packet", __PRETTY_FUNCTION__)
|
||||
return 0;
|
||||
}
|
||||
|
@ -482,10 +481,10 @@ int CTapDriver::Receive(BYTE *buf)
|
|||
// need it.
|
||||
const int crc = Crc32(buf, dwReceived);
|
||||
|
||||
buf[dwReceived + 0] = (BYTE)((crc >> 0) & 0xFF);
|
||||
buf[dwReceived + 1] = (BYTE)((crc >> 8) & 0xFF);
|
||||
buf[dwReceived + 2] = (BYTE)((crc >> 16) & 0xFF);
|
||||
buf[dwReceived + 3] = (BYTE)((crc >> 24) & 0xFF);
|
||||
buf[dwReceived + 0] = (uint8_t)((crc >> 0) & 0xFF);
|
||||
buf[dwReceived + 1] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
buf[dwReceived + 2] = (uint8_t)((crc >> 16) & 0xFF);
|
||||
buf[dwReceived + 3] = (uint8_t)((crc >> 24) & 0xFF);
|
||||
|
||||
LOGDEBUG("%s CRC is %08X - %02X %02X %02X %02X\n", __PRETTY_FUNCTION__, crc, buf[dwReceived+0], buf[dwReceived+1], buf[dwReceived+2], buf[dwReceived+3])
|
||||
|
||||
|
@ -508,7 +507,7 @@ int CTapDriver::Receive(BYTE *buf)
|
|||
return dwReceived;
|
||||
}
|
||||
|
||||
int CTapDriver::Send(const BYTE *buf, int len)
|
||||
int CTapDriver::Send(const uint8_t *buf, int len)
|
||||
{
|
||||
assert(m_hTAP != -1);
|
||||
|
||||
|
@ -524,5 +523,5 @@ int CTapDriver::Send(const BYTE *buf, int len)
|
|||
}
|
||||
|
||||
// Start sending
|
||||
return (int)write(m_hTAP, buf, len);
|
||||
return static_cast<int>(write(m_hTAP, buf, len));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <pcap/pcap.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <array>
|
||||
|
||||
|
@ -33,15 +33,15 @@ public:
|
|||
|
||||
bool Init(const unordered_map<string, string>&);
|
||||
void OpenDump(const string& path); // Capture packets
|
||||
void GetMacAddr(BYTE *mac) const;
|
||||
int Receive(BYTE *buf);
|
||||
int Send(const BYTE *buf, int len);
|
||||
void GetMacAddr(uint8_t *mac) const;
|
||||
int Receive(uint8_t *buf);
|
||||
int Send(const uint8_t *buf, int len);
|
||||
bool PendingPackets() const; // Check if there are IP packets available
|
||||
bool Enable() const; // Enable the ras0 interface
|
||||
bool Disable() const; // Disable the ras0 interface
|
||||
void Flush(); // Purge all of the packets that are waiting to be processed
|
||||
|
||||
static uint32_t Crc32(const BYTE *, int);
|
||||
static uint32_t Crc32(const uint8_t *, int);
|
||||
|
||||
private:
|
||||
array<byte, 6> m_MacAddr; // MAC Address
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
pcap_dumper_t *m_pcap_dumper = nullptr;
|
||||
|
||||
// Prioritized comma-separated list of interfaces to create the bridge for
|
||||
list<string> interfaces;
|
||||
vector<string> interfaces;
|
||||
|
||||
string inet;
|
||||
};
|
||||
|
|
|
@ -169,9 +169,9 @@ const unordered_map<string, string>& DeviceFactory::GetDefaultParams(PbDeviceTyp
|
|||
return it != default_params.end() ? it->second : empty_map;
|
||||
}
|
||||
|
||||
list<string> DeviceFactory::GetNetworkInterfaces() const
|
||||
vector<string> DeviceFactory::GetNetworkInterfaces() const
|
||||
{
|
||||
list<string> network_interfaces;
|
||||
vector<string> network_interfaces;
|
||||
|
||||
#ifdef __linux__
|
||||
ifaddrs *addrs;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include "rascsi_interface.pb.h"
|
||||
|
@ -36,7 +36,7 @@ public:
|
|||
PbDeviceType GetTypeForFile(const string&) const;
|
||||
const unordered_set<uint32_t>& GetSectorSizes(PbDeviceType type) const;
|
||||
const unordered_map<string, string>& GetDefaultParams(PbDeviceType type) const;
|
||||
list<string> GetNetworkInterfaces() const;
|
||||
vector<string> GetNetworkInterfaces() const;
|
||||
const unordered_map<string, PbDeviceType>& GetExtensionMapping() const { return extension_mapping; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -78,13 +78,13 @@ bool Disk::Dispatch(scsi_command cmd)
|
|||
|
||||
void Disk::SetUpCache(off_t image_offset, bool raw)
|
||||
{
|
||||
cache = make_unique<DiskCache>(GetFilename(), size_shift_count, (uint32_t)GetBlockCount(), image_offset);
|
||||
cache = make_unique<DiskCache>(GetFilename(), size_shift_count, static_cast<uint32_t>(GetBlockCount()), image_offset);
|
||||
cache->SetRawMode(raw);
|
||||
}
|
||||
|
||||
void Disk::ResizeCache(const string& path, bool raw)
|
||||
{
|
||||
cache.reset(new DiskCache(path, size_shift_count, (uint32_t)GetBlockCount()));
|
||||
cache.reset(new DiskCache(path, size_shift_count, static_cast<uint32_t>(GetBlockCount())));
|
||||
cache->SetRawMode(raw);
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ void Disk::FormatUnit()
|
|||
CheckReady();
|
||||
|
||||
// FMTDATA=1 is not supported (but OK if there is no DEFECT LIST)
|
||||
if ((ctrl->cmd[1] & 0x10) != 0 && ctrl->cmd[4] != 0) {
|
||||
if ((controller->GetCmd(1) & 0x10) != 0 && controller->GetCmd(4) != 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
@ -109,12 +109,15 @@ void Disk::FormatUnit()
|
|||
|
||||
void Disk::Read(access_mode mode)
|
||||
{
|
||||
if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, mode)) {
|
||||
ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), start);
|
||||
uint64_t start;
|
||||
uint32_t blocks;
|
||||
if (CheckAndGetStartAndCount(start, blocks, mode)) {
|
||||
controller->SetBlocks(blocks);
|
||||
controller->SetLength(Read(controller->GetCmd(), controller->GetBuffer(), start));
|
||||
LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, controller->GetLength())
|
||||
|
||||
// Set next block
|
||||
ctrl->next = start + 1;
|
||||
controller->SetNext(start + 1);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -126,7 +129,7 @@ void Disk::Read(access_mode mode)
|
|||
void Disk::ReadWriteLong10()
|
||||
{
|
||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||
if (GetInt16(ctrl->cmd, 7) != 0) {
|
||||
if (GetInt16(controller->GetCmd(), 7) != 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
@ -138,7 +141,7 @@ void Disk::ReadWriteLong10()
|
|||
void Disk::ReadWriteLong16()
|
||||
{
|
||||
// Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard
|
||||
if (GetInt16(ctrl->cmd, 12) != 0) {
|
||||
if (GetInt16(controller->GetCmd(), 12) != 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
@ -149,11 +152,14 @@ void Disk::ReadWriteLong16()
|
|||
|
||||
void Disk::Write(access_mode mode)
|
||||
{
|
||||
if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, mode)) {
|
||||
ctrl->length = WriteCheck(start);
|
||||
uint64_t start;
|
||||
uint32_t blocks;
|
||||
if (CheckAndGetStartAndCount(start, blocks, mode)) {
|
||||
controller->SetBlocks(blocks);
|
||||
controller->SetLength(WriteCheck(start));
|
||||
|
||||
// Set next block
|
||||
ctrl->next = start + 1;
|
||||
controller->SetNext(start + 1);
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
@ -164,18 +170,21 @@ void Disk::Write(access_mode mode)
|
|||
|
||||
void Disk::Verify(access_mode mode)
|
||||
{
|
||||
if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, mode)) {
|
||||
uint64_t start;
|
||||
uint32_t blocks;
|
||||
if (CheckAndGetStartAndCount(start, blocks, mode)) {
|
||||
// if BytChk=0
|
||||
if ((ctrl->cmd[1] & 0x02) == 0) {
|
||||
if ((controller->GetCmd(1) & 0x02) == 0) {
|
||||
Seek();
|
||||
return;
|
||||
}
|
||||
|
||||
// Test reading
|
||||
ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), start);
|
||||
controller->SetBlocks(blocks);
|
||||
controller->SetLength(Read(controller->GetCmd(), controller->GetBuffer(), start));
|
||||
|
||||
// Set next block
|
||||
ctrl->next = start + 1;
|
||||
controller->SetNext(start + 1);
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
@ -186,8 +195,8 @@ void Disk::Verify(access_mode mode)
|
|||
|
||||
void Disk::StartStopUnit()
|
||||
{
|
||||
const bool start = ctrl->cmd[4] & 0x01;
|
||||
const bool load = ctrl->cmd[4] & 0x02;
|
||||
const bool start = controller->GetCmd(4) & 0x01;
|
||||
const bool load = controller->GetCmd(4) & 0x02;
|
||||
|
||||
if (load) {
|
||||
LOGTRACE(start ? "Loading medium" : "Ejecting medium")
|
||||
|
@ -223,7 +232,7 @@ void Disk::PreventAllowMediumRemoval()
|
|||
{
|
||||
CheckReady();
|
||||
|
||||
const bool lock = ctrl->cmd[4] & 0x01;
|
||||
const bool lock = controller->GetCmd(4) & 0x01;
|
||||
|
||||
LOGTRACE(lock ? "Locking medium" : "Unlocking medium")
|
||||
|
||||
|
@ -241,11 +250,11 @@ void Disk::SynchronizeCache()
|
|||
|
||||
void Disk::ReadDefectData10()
|
||||
{
|
||||
const size_t allocation_length = min((size_t)GetInt16(ctrl->cmd, 7), (size_t)4);
|
||||
const size_t allocation_length = min(static_cast<size_t>(GetInt16(controller->GetCmd(), 7)), static_cast<size_t>(4));
|
||||
|
||||
// The defect list is empty
|
||||
fill_n(controller->GetBuffer().begin(), allocation_length, 0);
|
||||
ctrl->length = (int)allocation_length;
|
||||
controller->SetLength(static_cast<uint32_t>(allocation_length));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -264,10 +273,10 @@ bool Disk::Eject(bool force)
|
|||
return status;
|
||||
}
|
||||
|
||||
int Disk::ModeSense6(const vector<int>& cdb, vector<BYTE>& buf) const
|
||||
int Disk::ModeSense6(const vector<int>& cdb, vector<uint8_t>& buf) const
|
||||
{
|
||||
// Get length, clear buffer
|
||||
const auto length = (int)min(buf.size(), (size_t)cdb[4]);
|
||||
const auto length = static_cast<int>(min(buf.size(), static_cast<size_t>(cdb[4])));
|
||||
fill_n(buf.begin(), length, 0);
|
||||
|
||||
// DEVICE SPECIFIC PARAMETER
|
||||
|
@ -286,7 +295,7 @@ int Disk::ModeSense6(const vector<int>& cdb, vector<BYTE>& buf) const
|
|||
// Only if ready
|
||||
if (IsReady()) {
|
||||
// Short LBA mode parameter block descriptor (number of blocks and block length)
|
||||
SetInt32(buf, 4, (uint32_t)GetBlockCount());
|
||||
SetInt32(buf, 4, static_cast<uint32_t>(GetBlockCount()));
|
||||
SetInt32(buf, 8, GetSectorSizeInBytes());
|
||||
}
|
||||
|
||||
|
@ -295,15 +304,15 @@ int Disk::ModeSense6(const vector<int>& cdb, vector<BYTE>& buf) const
|
|||
|
||||
size = AddModePages(cdb, buf, size, length, 255);
|
||||
|
||||
buf[0] = (BYTE)size;
|
||||
buf[0] = (uint8_t)size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int Disk::ModeSense10(const vector<int>& cdb, vector<BYTE>& buf) const
|
||||
int Disk::ModeSense10(const vector<int>& cdb, vector<uint8_t>& buf) const
|
||||
{
|
||||
// Get length, clear buffer
|
||||
const auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7));
|
||||
const auto length = static_cast<int>(min(buf.size(), static_cast<size_t>(GetInt16(cdb, 7))));
|
||||
fill_n(buf.begin(), length, 0);
|
||||
|
||||
// DEVICE SPECIFIC PARAMETER
|
||||
|
@ -325,7 +334,7 @@ int Disk::ModeSense10(const vector<int>& cdb, vector<BYTE>& buf) const
|
|||
buf[7] = 0x08;
|
||||
|
||||
// Short LBA mode parameter block descriptor (number of blocks and block length)
|
||||
SetInt32(buf, 8, (uint32_t)disk_blocks);
|
||||
SetInt32(buf, 8, static_cast<uint32_t>(disk_blocks));
|
||||
SetInt32(buf, 12, disk_size);
|
||||
|
||||
size = 16;
|
||||
|
@ -443,7 +452,7 @@ void Disk::AddDrivePage(map<int, vector<byte>>& pages, bool changeable) const
|
|||
uint64_t cylinders = GetBlockCount();
|
||||
cylinders >>= 3;
|
||||
cylinders /= 25;
|
||||
SetInt32(buf, 0x01, (uint32_t)cylinders);
|
||||
SetInt32(buf, 0x01, static_cast<uint32_t>(cylinders));
|
||||
|
||||
// Fix the head at 8
|
||||
buf[0x05] = (byte)0x8;
|
||||
|
@ -480,7 +489,7 @@ void Disk::AddCachePage(map<int, vector<byte>>& pages, bool changeable) const
|
|||
pages[8] = buf;
|
||||
}
|
||||
|
||||
int Disk::Read(const vector<int>&, vector<BYTE>& buf, uint64_t block)
|
||||
int Disk::Read(const vector<int>&, vector<uint8_t>& buf, uint64_t block)
|
||||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
|
||||
|
@ -492,7 +501,7 @@ int Disk::Read(const vector<int>&, vector<BYTE>& buf, uint64_t block)
|
|||
}
|
||||
|
||||
// leave it to the cache
|
||||
if (!cache->ReadSector(buf, (uint32_t)block)) {
|
||||
if (!cache->ReadSector(buf, static_cast<uint32_t>(block))) {
|
||||
throw scsi_exception(sense_key::MEDIUM_ERROR, asc::READ_FAULT);
|
||||
}
|
||||
|
||||
|
@ -516,7 +525,7 @@ int Disk::WriteCheck(uint64_t block)
|
|||
return GetSectorSizeInBytes();
|
||||
}
|
||||
|
||||
void Disk::Write(const vector<int>&, const vector<BYTE>& buf, uint64_t block)
|
||||
void Disk::Write(const vector<int>&, const vector<uint8_t>& buf, uint64_t block)
|
||||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
|
||||
|
@ -533,7 +542,7 @@ void Disk::Write(const vector<int>&, const vector<BYTE>& buf, uint64_t block)
|
|||
}
|
||||
|
||||
// Leave it to the cache
|
||||
if (!cache->WriteSector(buf, (uint32_t)block)) {
|
||||
if (!cache->WriteSector(buf, static_cast<uint32_t>(block))) {
|
||||
throw scsi_exception(sense_key::MEDIUM_ERROR, asc::WRITE_FAULT);
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +556,8 @@ void Disk::Seek()
|
|||
|
||||
void Disk::Seek6()
|
||||
{
|
||||
if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, SEEK6)) {
|
||||
uint64_t start;
|
||||
if (uint32_t blocks; CheckAndGetStartAndCount(start, blocks, SEEK6)) {
|
||||
CheckReady();
|
||||
}
|
||||
|
||||
|
@ -556,7 +566,8 @@ void Disk::Seek6()
|
|||
|
||||
void Disk::Seek10()
|
||||
{
|
||||
if (uint64_t start; CheckAndGetStartAndCount(start, ctrl->blocks, SEEK10)) {
|
||||
uint64_t start;
|
||||
if (uint32_t blocks; CheckAndGetStartAndCount(start, blocks, SEEK10)) {
|
||||
CheckReady();
|
||||
}
|
||||
|
||||
|
@ -571,7 +582,7 @@ void Disk::ReadCapacity10()
|
|||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT);
|
||||
}
|
||||
|
||||
vector<BYTE>& buf = controller->GetBuffer();
|
||||
vector<uint8_t>& buf = controller->GetBuffer();
|
||||
|
||||
// Create end of logical block address (blocks-1)
|
||||
uint64_t capacity = GetBlockCount() - 1;
|
||||
|
@ -580,13 +591,13 @@ void Disk::ReadCapacity10()
|
|||
if (capacity > 4294967295) {
|
||||
capacity = -1;
|
||||
}
|
||||
SetInt32(buf, 0, (uint32_t)capacity);
|
||||
SetInt32(buf, 0, static_cast<uint32_t>(capacity));
|
||||
|
||||
// Create block length (1 << size)
|
||||
SetInt32(buf, 4, 1 << size_shift_count);
|
||||
|
||||
// the size
|
||||
ctrl->length = 8;
|
||||
controller->SetLength(8);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -599,7 +610,7 @@ void Disk::ReadCapacity16()
|
|||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::MEDIUM_NOT_PRESENT);
|
||||
}
|
||||
|
||||
vector<BYTE>& buf = controller->GetBuffer();
|
||||
vector<uint8_t>& buf = controller->GetBuffer();
|
||||
|
||||
// Create end of logical block address (blocks-1)
|
||||
SetInt64(buf, 0, GetBlockCount() - 1);
|
||||
|
@ -613,7 +624,7 @@ void Disk::ReadCapacity16()
|
|||
buf[13] = 0;
|
||||
|
||||
// the size
|
||||
ctrl->length = 14;
|
||||
controller->SetLength(14);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -621,7 +632,7 @@ void Disk::ReadCapacity16()
|
|||
void Disk::ReadCapacity16_ReadLong16()
|
||||
{
|
||||
// The service action determines the actual command
|
||||
switch (ctrl->cmd[1] & 0x1f) {
|
||||
switch (controller->GetCmd(1) & 0x1f) {
|
||||
case 0x10:
|
||||
ReadCapacity16();
|
||||
break;
|
||||
|
@ -644,7 +655,7 @@ void Disk::ReadCapacity16_ReadLong16()
|
|||
|
||||
void Disk::ValidateBlockAddress(access_mode mode) const
|
||||
{
|
||||
const uint64_t block = mode == RW16 ? GetInt64(ctrl->cmd, 2) : GetInt32(ctrl->cmd, 2);
|
||||
const uint64_t block = mode == RW16 ? GetInt64(controller->GetCmd(), 2) : GetInt32(controller->GetCmd(), 2);
|
||||
|
||||
if (block > GetBlockCount()) {
|
||||
LOGTRACE("%s", ("Capacity of " + to_string(GetBlockCount()) + " block(s) exceeded: Trying to access block "
|
||||
|
@ -656,28 +667,29 @@ void Disk::ValidateBlockAddress(access_mode mode) const
|
|||
bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mode mode) const
|
||||
{
|
||||
if (mode == RW6 || mode == SEEK6) {
|
||||
start = GetInt24(ctrl->cmd, 1);
|
||||
start = GetInt24(controller->GetCmd(), 1);
|
||||
|
||||
count = ctrl->cmd[4];
|
||||
count = controller->GetCmd(4);
|
||||
if (!count) {
|
||||
count= 0x100;
|
||||
}
|
||||
}
|
||||
else {
|
||||
start = mode == RW16 ? GetInt64(ctrl->cmd, 2) : GetInt32(ctrl->cmd, 2);
|
||||
start = mode == RW16 ? GetInt64(controller->GetCmd(), 2) : GetInt32(controller->GetCmd(), 2);
|
||||
|
||||
if (mode == RW16) {
|
||||
count = GetInt32(ctrl->cmd, 10);
|
||||
count = GetInt32(controller->GetCmd(), 10);
|
||||
}
|
||||
else if (mode != SEEK6 && mode != SEEK10) {
|
||||
count = GetInt16(ctrl->cmd, 7);
|
||||
count = GetInt16(controller->GetCmd(), 7);
|
||||
}
|
||||
else {
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LOGTRACE("%s READ/WRITE/VERIFY/SEEK command record=$%08X blocks=%d", __PRETTY_FUNCTION__, (uint32_t)start, count)
|
||||
LOGTRACE("%s READ/WRITE/VERIFY/SEEK command record=$%08X blocks=%d", __PRETTY_FUNCTION__,
|
||||
static_cast<uint32_t>(start), count)
|
||||
|
||||
// Check capacity
|
||||
if (uint64_t capacity = GetBlockCount(); !capacity || start > capacity || start + count > capacity) {
|
||||
|
|
|
@ -53,9 +53,9 @@ public:
|
|||
|
||||
// Command helpers
|
||||
virtual int WriteCheck(uint64_t);
|
||||
virtual void Write(const vector<int>&, const vector<BYTE>&, uint64_t);
|
||||
virtual void Write(const vector<int>&, const vector<uint8_t>&, uint64_t);
|
||||
|
||||
virtual int Read(const vector<int>&, vector<BYTE>& , uint64_t);
|
||||
virtual int Read(const vector<int>&, vector<uint8_t>& , uint64_t);
|
||||
|
||||
uint32_t GetSectorSizeInBytes() const;
|
||||
bool IsSectorSizeConfigurable() const { return !sector_sizes.empty(); }
|
||||
|
@ -95,8 +95,8 @@ private:
|
|||
void ValidateBlockAddress(access_mode) const;
|
||||
bool CheckAndGetStartAndCount(uint64_t&, uint32_t&, access_mode) const;
|
||||
|
||||
int ModeSense6(const vector<int>&, vector<BYTE>&) const override;
|
||||
int ModeSense10(const vector<int>&, vector<BYTE>&) const override;
|
||||
int ModeSense6(const vector<int>&, vector<uint8_t>&) const override;
|
||||
int ModeSense10(const vector<int>&, vector<uint8_t>&) const override;
|
||||
|
||||
static const unordered_map<uint32_t, uint32_t> shift_counts;
|
||||
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include "disk_track.h"
|
||||
#include "disk_cache.h"
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
DiskCache::DiskCache(const string& path, int size, uint32_t blocks, off_t imgoff)
|
||||
: sec_path(path), sec_size(size), sec_blocks(blocks), imgoffset(imgoff)
|
||||
|
@ -29,15 +29,9 @@ DiskCache::DiskCache(const string& path, int size, uint32_t blocks, off_t imgoff
|
|||
|
||||
bool DiskCache::Save() const
|
||||
{
|
||||
// Save track
|
||||
for (const cache_t& c : cache) {
|
||||
// Save if this is a valid track
|
||||
if (c.disktrk && !c.disktrk->Save(sec_path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// Save valid tracks
|
||||
return none_of(cache.begin(), cache.end(), [this](const cache_t& c)
|
||||
{ return c.disktrk != nullptr && !c.disktrk->Save(sec_path); });
|
||||
}
|
||||
|
||||
shared_ptr<DiskTrack> DiskCache::GetTrack(uint32_t block)
|
||||
|
@ -52,7 +46,7 @@ shared_ptr<DiskTrack> DiskCache::GetTrack(uint32_t block)
|
|||
return Assign(track);
|
||||
}
|
||||
|
||||
bool DiskCache::ReadSector(vector<BYTE>& buf, uint32_t block)
|
||||
bool DiskCache::ReadSector(vector<uint8_t>& buf, uint32_t block)
|
||||
{
|
||||
shared_ptr<DiskTrack> disktrk = GetTrack(block);
|
||||
if (disktrk == nullptr) {
|
||||
|
@ -63,7 +57,7 @@ bool DiskCache::ReadSector(vector<BYTE>& buf, uint32_t block)
|
|||
return disktrk->ReadSector(buf, block & 0xff);
|
||||
}
|
||||
|
||||
bool DiskCache::WriteSector(const vector<BYTE>& buf, uint32_t block)
|
||||
bool DiskCache::WriteSector(const vector<uint8_t>& buf, uint32_t block)
|
||||
{
|
||||
shared_ptr<DiskTrack> disktrk = GetTrack(block);
|
||||
if (disktrk == nullptr) {
|
||||
|
@ -97,7 +91,7 @@ shared_ptr<DiskTrack> DiskCache::Assign(int track)
|
|||
for (size_t i = 0; i < cache.size(); i++) {
|
||||
if (cache[i].disktrk == nullptr) {
|
||||
// Try loading
|
||||
if (Load((int)i, track, nullptr)) {
|
||||
if (Load(static_cast<int>(i), track, nullptr)) {
|
||||
// Success loading
|
||||
cache[i].serial = serial;
|
||||
return cache[i].disktrk;
|
||||
|
@ -134,7 +128,7 @@ shared_ptr<DiskTrack> DiskCache::Assign(int track)
|
|||
shared_ptr<DiskTrack> disktrk = cache[c].disktrk;
|
||||
cache[c].disktrk.reset();
|
||||
|
||||
if (Load((int)c, track, disktrk)) {
|
||||
if (Load(static_cast<int>(c), track, disktrk)) {
|
||||
// Successful loading
|
||||
cache[c].serial = serial;
|
||||
return cache[c].disktrk;
|
||||
|
@ -151,7 +145,7 @@ shared_ptr<DiskTrack> DiskCache::Assign(int track)
|
|||
//---------------------------------------------------------------------------
|
||||
bool DiskCache::Load(int index, int track, shared_ptr<DiskTrack> disktrk)
|
||||
{
|
||||
assert(index >= 0 && index < (int)cache.size());
|
||||
assert(index >= 0 && index < static_cast<int>(cache.size()));
|
||||
assert(track >= 0);
|
||||
assert(cache[index].disktrk == nullptr);
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
|
||||
// Access
|
||||
bool Save() const; // Save and release all
|
||||
bool ReadSector(vector<BYTE>&, uint32_t); // Sector Read
|
||||
bool WriteSector(const vector<BYTE>&, uint32_t); // Sector Write
|
||||
bool ReadSector(vector<uint8_t>&, uint32_t); // Sector Read
|
||||
bool WriteSector(const vector<uint8_t>&, uint32_t); // Sector Write
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ bool DiskTrack::Load(const string& path)
|
|||
}
|
||||
|
||||
// Reallocate if the buffer length is different
|
||||
if (dt.length != (uint32_t)length) {
|
||||
if (dt.length != static_cast<uint32_t>(length)) {
|
||||
free(dt.buffer);
|
||||
if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) {
|
||||
LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__)
|
||||
|
@ -215,7 +215,7 @@ bool DiskTrack::Save(const string& path)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DiskTrack::ReadSector(vector<BYTE>& buf, int sec) const
|
||||
bool DiskTrack::ReadSector(vector<uint8_t>& buf, int sec) const
|
||||
{
|
||||
assert(sec >= 0 && sec < 0x100);
|
||||
|
||||
|
@ -240,7 +240,7 @@ bool DiskTrack::ReadSector(vector<BYTE>& buf, int sec) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DiskTrack::WriteSector(const vector<BYTE>& buf, int sec)
|
||||
bool DiskTrack::WriteSector(const vector<uint8_t>& buf, int sec)
|
||||
{
|
||||
assert((sec >= 0) && (sec < 0x100));
|
||||
assert(!dt.raw);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "os.h"
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -29,7 +28,7 @@ class DiskTrack
|
|||
int size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096)
|
||||
int sectors; // Number of sectors(<0x100)
|
||||
uint32_t length; // Data buffer length
|
||||
BYTE *buffer; // Data buffer
|
||||
uint8_t *buffer; // Data buffer
|
||||
bool init; // Is it initilized?
|
||||
bool changed; // Changed flag
|
||||
vector<bool> changemap; // Changed map
|
||||
|
@ -53,8 +52,8 @@ private:
|
|||
bool Save(const string& path);
|
||||
|
||||
// Read / Write
|
||||
bool ReadSector(vector<BYTE>&, int) const; // Sector Read
|
||||
bool WriteSector(const vector<BYTE>& buf, int); // Sector Write
|
||||
bool ReadSector(vector<uint8_t>&, int) const; // Sector Read
|
||||
bool WriteSector(const vector<uint8_t>& buf, int); // Sector Write
|
||||
|
||||
int GetTrack() const { return dt.track; } // Get track
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
commands[opcode] = make_unique<command_t>(name, execute);
|
||||
}
|
||||
|
||||
bool Dispatch(T *instance, scsi_command cmd)
|
||||
bool Dispatch(T *instance, scsi_command cmd) const
|
||||
{
|
||||
if (const auto& it = commands.find(cmd); it != commands.end()) {
|
||||
LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, it->second->name, (int)cmd)
|
||||
|
|
|
@ -59,8 +59,8 @@ vector<byte> HostServices::InquiryInternal() const
|
|||
|
||||
void HostServices::StartStopUnit()
|
||||
{
|
||||
const bool start = ctrl->cmd[4] & 0x01;
|
||||
const bool load = ctrl->cmd[4] & 0x02;
|
||||
const bool start = controller->GetCmd(4) & 0x01;
|
||||
const bool load = controller->GetCmd(4) & 0x02;
|
||||
|
||||
if (!start) {
|
||||
// Flush any caches
|
||||
|
@ -85,32 +85,32 @@ void HostServices::StartStopUnit()
|
|||
EnterStatusPhase();
|
||||
}
|
||||
|
||||
int HostServices::ModeSense6(const vector<int>& cdb, vector<BYTE>& buf) const
|
||||
int HostServices::ModeSense6(const vector<int>& cdb, vector<uint8_t>& buf) const
|
||||
{
|
||||
// Block descriptors cannot be returned
|
||||
if (!(cdb[1] & 0x08)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
const auto length = (int)min(buf.size(), (size_t)cdb[4]);
|
||||
const auto length = static_cast<int>(min(buf.size(), static_cast<size_t>(cdb[4])));
|
||||
fill_n(buf.begin(), length, 0);
|
||||
|
||||
// 4 bytes basic information
|
||||
int size = AddModePages(cdb, buf, 4, length, 255);
|
||||
|
||||
buf[0] = (BYTE)size;
|
||||
buf[0] = (uint8_t)size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int HostServices::ModeSense10(const vector<int>& cdb, vector<BYTE>& buf) const
|
||||
int HostServices::ModeSense10(const vector<int>& cdb, vector<uint8_t>& buf) const
|
||||
{
|
||||
// Block descriptors cannot be returned
|
||||
if (!(cdb[1] & 0x08)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
const auto length = (int)min(buf.size(), (size_t)GetInt16(cdb, 7));
|
||||
const auto length = static_cast<int>(min(buf.size(), static_cast<size_t>(GetInt16(cdb, 7))));
|
||||
fill_n(buf.begin(), length, 0);
|
||||
|
||||
// 8 bytes basic information
|
||||
|
|
|
@ -56,8 +56,8 @@ private:
|
|||
const ControllerManager& controller_manager;
|
||||
|
||||
void StartStopUnit();
|
||||
int ModeSense6(const vector<int>&, vector<BYTE>&) const override;
|
||||
int ModeSense10(const vector<int>&, vector<BYTE>&) const override;
|
||||
int ModeSense6(const vector<int>&, vector<uint8_t>&) const override;
|
||||
int ModeSense10(const vector<int>&, vector<uint8_t>&) const override;
|
||||
|
||||
void AddRealtimeClockPage(map<int, vector<byte>>&, bool) const;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Copyright (C) 2022 Uwe Seimet
|
||||
//
|
||||
// Abstraction for the DaynaPort and the host bridge, which both have methods for writing byte sequences
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ByteWriter
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
ByteWriter() = default;
|
||||
virtual ~ByteWriter() = default;
|
||||
|
||||
virtual bool WriteBytes(const vector<int>&, vector<uint8_t>&, uint32_t) = 0;
|
||||
};
|
|
@ -34,7 +34,7 @@ bool ModePageDevice::Dispatch(scsi_command cmd)
|
|||
return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd);
|
||||
}
|
||||
|
||||
int ModePageDevice::AddModePages(const vector<int>& cdb, vector<BYTE>& buf, int offset, int length, int max_size) const
|
||||
int ModePageDevice::AddModePages(const vector<int>& cdb, vector<uint8_t>& buf, int offset, int length, int max_size) const
|
||||
{
|
||||
int max_length = length - offset;
|
||||
if (max_length < 0) {
|
||||
|
@ -88,11 +88,11 @@ int ModePageDevice::AddModePages(const vector<int>& cdb, vector<BYTE>& buf, int
|
|||
result[off + 1] = (byte)(page0.size() - 2);
|
||||
}
|
||||
|
||||
if ((int)result.size() > max_size) {
|
||||
if (static_cast<int>(result.size()) > max_size) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
auto size = (int)min((size_t)max_length, result.size());
|
||||
auto size = static_cast<int>(min(static_cast<size_t>(max_length), result.size()));
|
||||
memcpy(&buf.data()[offset], result.data(), size);
|
||||
|
||||
// Do not return more than the requested number of bytes
|
||||
|
@ -101,42 +101,42 @@ int ModePageDevice::AddModePages(const vector<int>& cdb, vector<BYTE>& buf, int
|
|||
|
||||
void ModePageDevice::ModeSense6()
|
||||
{
|
||||
ctrl->length = ModeSense6(ctrl->cmd, controller->GetBuffer());
|
||||
controller->SetLength(ModeSense6(controller->GetCmd(), controller->GetBuffer()));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
||||
void ModePageDevice::ModeSense10()
|
||||
{
|
||||
ctrl->length = ModeSense10(ctrl->cmd, controller->GetBuffer());
|
||||
controller->SetLength(ModeSense10(controller->GetCmd(), controller->GetBuffer()));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
||||
void ModePageDevice::ModeSelect(scsi_command, const vector<int>&, const vector<BYTE>&, int) const
|
||||
void ModePageDevice::ModeSelect(scsi_command, const vector<int>&, const vector<uint8_t>&, int) const
|
||||
{
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
}
|
||||
|
||||
void ModePageDevice::ModeSelect6()
|
||||
{
|
||||
ctrl->length = SaveParametersCheck(ctrl->cmd[4]);
|
||||
controller->SetLength(SaveParametersCheck(controller->GetCmd(4)));
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
||||
void ModePageDevice::ModeSelect10()
|
||||
{
|
||||
const size_t length = min(controller->GetBuffer().size(), (size_t)GetInt16(ctrl->cmd, 7));
|
||||
const size_t length = min(controller->GetBuffer().size(), static_cast<size_t>(GetInt16(controller->GetCmd(), 7)));
|
||||
|
||||
ctrl->length = SaveParametersCheck((int)length);
|
||||
controller->SetLength(SaveParametersCheck(static_cast<uint32_t>(length)));
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
||||
int ModePageDevice::SaveParametersCheck(int length) const
|
||||
{
|
||||
if (!SupportsSaveParameters() && (ctrl->cmd[1] & 0x01)) {
|
||||
if (!SupportsSaveParameters() && (controller->GetCmd(1) & 0x01)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ public:
|
|||
|
||||
bool Dispatch(scsi_command) override;
|
||||
|
||||
virtual void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<BYTE>&, int) const;
|
||||
virtual void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<uint8_t>&, int) const;
|
||||
|
||||
protected:
|
||||
|
||||
bool SupportsSaveParameters() const { return supports_save_parameters; }
|
||||
void SupportsSaveParameters(bool b) { supports_save_parameters = b; }
|
||||
int AddModePages(const vector<int>&, vector<BYTE>&, int, int, int) const;
|
||||
int AddModePages(const vector<int>&, vector<uint8_t>&, int, int, int) const;
|
||||
virtual void SetUpModePages(map<int, vector<byte>>&, int, bool) const = 0;
|
||||
virtual void AddVendorPage(map<int, vector<byte>>&, int, bool) const {
|
||||
// Nothing to add by default
|
||||
|
@ -43,8 +43,8 @@ private:
|
|||
|
||||
bool supports_save_parameters = false;
|
||||
|
||||
virtual int ModeSense6(const vector<int>&, vector<BYTE>&) const = 0;
|
||||
virtual int ModeSense10(const vector<int>&, vector<BYTE>&) const = 0;
|
||||
virtual int ModeSense6(const vector<int>&, vector<uint8_t>&) const = 0;
|
||||
virtual int ModeSense10(const vector<int>&, vector<uint8_t>&) const = 0;
|
||||
|
||||
void ModeSense6();
|
||||
void ModeSense10();
|
||||
|
|
|
@ -55,7 +55,6 @@ int PrimaryDevice::GetId() const
|
|||
void PrimaryDevice::SetController(AbstractController *c)
|
||||
{
|
||||
controller = c;
|
||||
ctrl = controller->GetCtrl();
|
||||
}
|
||||
|
||||
void PrimaryDevice::TestUnitReady()
|
||||
|
@ -68,16 +67,16 @@ void PrimaryDevice::TestUnitReady()
|
|||
void PrimaryDevice::Inquiry()
|
||||
{
|
||||
// EVPD and page code check
|
||||
if ((ctrl->cmd[1] & 0x01) || ctrl->cmd[2]) {
|
||||
if ((controller->GetCmd(1) & 0x01) || controller->GetCmd(2)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
vector<byte> buf = InquiryInternal();
|
||||
|
||||
const size_t allocation_length = min(buf.size(), (size_t)GetInt16(ctrl->cmd, 3));
|
||||
const size_t allocation_length = min(buf.size(), static_cast<size_t>(GetInt16(controller->GetCmd(), 3)));
|
||||
|
||||
memcpy(controller->GetBuffer().data(), buf.data(), allocation_length);
|
||||
ctrl->length = (uint32_t)allocation_length;
|
||||
controller->SetLength(static_cast<uint32_t>(allocation_length));
|
||||
|
||||
// Report if the device does not support the requested LUN
|
||||
if (int lun = controller->GetEffectiveLun(); !controller->HasDeviceForLun(lun)) {
|
||||
|
@ -93,20 +92,20 @@ void PrimaryDevice::Inquiry()
|
|||
void PrimaryDevice::ReportLuns()
|
||||
{
|
||||
// Only SELECT REPORT mode 0 is supported
|
||||
if (ctrl->cmd[2]) {
|
||||
if (controller->GetCmd(2)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
const uint32_t allocation_length = GetInt32(ctrl->cmd, 6);
|
||||
const uint32_t allocation_length = GetInt32(controller->GetCmd(), 6);
|
||||
|
||||
vector<BYTE>& buf = controller->GetBuffer();
|
||||
fill_n(buf.begin(), min(buf.size(), (size_t)allocation_length), 0);
|
||||
vector<uint8_t>& buf = controller->GetBuffer();
|
||||
fill_n(buf.begin(), min(buf.size(), static_cast<size_t>(allocation_length)), 0);
|
||||
|
||||
uint32_t size = 0;
|
||||
for (int lun = 0; lun < controller->GetMaxLuns(); lun++) {
|
||||
if (controller->HasDeviceForLun(lun)) {
|
||||
size += 8;
|
||||
buf[size + 7] = (BYTE)lun;
|
||||
buf[size + 7] = (uint8_t)lun;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +113,7 @@ void PrimaryDevice::ReportLuns()
|
|||
|
||||
size += 8;
|
||||
|
||||
ctrl->length = min(allocation_length, size);
|
||||
controller->SetLength(min(allocation_length, size));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -139,10 +138,10 @@ void PrimaryDevice::RequestSense()
|
|||
|
||||
vector<byte> buf = controller->GetDeviceForLun(lun)->HandleRequestSense();
|
||||
|
||||
const size_t allocation_length = min(buf.size(), (size_t)ctrl->cmd[4]);
|
||||
const size_t allocation_length = min(buf.size(), static_cast<size_t>(controller->GetCmd(4)));
|
||||
|
||||
memcpy(controller->GetBuffer().data(), buf.data(), allocation_length);
|
||||
ctrl->length = (uint32_t)allocation_length;
|
||||
controller->SetLength(static_cast<uint32_t>(allocation_length));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -150,12 +149,12 @@ void PrimaryDevice::RequestSense()
|
|||
void PrimaryDevice::SendDiagnostic()
|
||||
{
|
||||
// Do not support PF bit
|
||||
if (ctrl->cmd[1] & 0x10) {
|
||||
if (controller->GetCmd(1) & 0x10) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
// Do not support parameter list
|
||||
if ((ctrl->cmd[3] != 0) || (ctrl->cmd[4] != 0)) {
|
||||
if ((controller->GetCmd(3) != 0) || (controller->GetCmd(4) != 0)) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
@ -229,13 +228,13 @@ vector<byte> PrimaryDevice::HandleRequestSense() const
|
|||
buf[12] = (byte)(GetStatusCode() >> 8);
|
||||
buf[13] = (byte)GetStatusCode();
|
||||
|
||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, (int)controller->GetStatus(),
|
||||
(int)buf[2], (int)buf[12])
|
||||
LOGTRACE("%s Status $%02X, Sense Key $%02X, ASC $%02X",__PRETTY_FUNCTION__, static_cast<int>(controller->GetStatus()),
|
||||
static_cast<int>(buf[2]), static_cast<int>(buf[12]))
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool PrimaryDevice::WriteByteSequence(vector<BYTE>&, uint32_t)
|
||||
bool PrimaryDevice::WriteByteSequence(vector<uint8_t>&, uint32_t)
|
||||
{
|
||||
LOGERROR("%s Writing bytes is not supported by this device", __PRETTY_FUNCTION__)
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
int GetId() const override;
|
||||
|
||||
void SetController(AbstractController *);
|
||||
virtual bool WriteByteSequence(vector<BYTE>&, uint32_t);
|
||||
virtual bool WriteByteSequence(vector<uint8_t>&, uint32_t);
|
||||
|
||||
int GetSendDelay() const { return send_delay; }
|
||||
|
||||
|
@ -60,8 +60,8 @@ protected:
|
|||
void EnterDataInPhase() { controller->DataIn(); }
|
||||
void EnterDataOutPhase() { controller->DataOut(); }
|
||||
|
||||
// TODO Try to replace this raw pointer, maybe by a weak_ptr
|
||||
AbstractController *controller = nullptr;
|
||||
AbstractController::ctrl_t *ctrl = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
using namespace scsi_defs;
|
||||
|
||||
void scsi_command_util::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<BYTE>& buf, int length,
|
||||
void scsi_command_util::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<uint8_t>& buf, int length,
|
||||
int sector_size)
|
||||
{
|
||||
assert(cmd == scsi_command::eCmdModeSelect6 || cmd == scsi_command::eCmdModeSelect10);
|
||||
|
@ -99,91 +99,91 @@ void scsi_command_util::AddAppleVendorModePage(map<int, vector<byte>>& pages, bo
|
|||
pages[48] = buf;
|
||||
}
|
||||
|
||||
int scsi_command_util::GetInt16(const vector<BYTE>& buf, int offset)
|
||||
int scsi_command_util::GetInt16(const vector<uint8_t>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 1);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 1);
|
||||
|
||||
return ((int)buf[offset] << 8) | buf[offset + 1];
|
||||
return (static_cast<int>(buf[offset]) << 8) | buf[offset + 1];
|
||||
}
|
||||
|
||||
int scsi_command_util::GetInt16(const vector<int>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 1);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 1);
|
||||
|
||||
return (buf[offset] << 8) | buf[offset + 1];
|
||||
}
|
||||
|
||||
int scsi_command_util::GetInt24(const vector<int>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 2);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 2);
|
||||
|
||||
return (buf[offset] << 16) | (buf[offset + 1] << 8) | buf[offset + 2];
|
||||
}
|
||||
|
||||
uint32_t scsi_command_util::GetInt32(const vector<int>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 3);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 3);
|
||||
|
||||
return ((uint32_t)buf[offset] << 24) | ((uint32_t)buf[offset + 1] << 16) |
|
||||
((uint32_t)buf[offset + 2] << 8) | (uint32_t)buf[offset + 3];
|
||||
return (static_cast<uint32_t>(buf[offset]) << 24) | (static_cast<uint32_t>(buf[offset + 1]) << 16) |
|
||||
(static_cast<uint32_t>(buf[offset + 2]) << 8) | static_cast<uint32_t>(buf[offset + 3]);
|
||||
}
|
||||
|
||||
uint64_t scsi_command_util::GetInt64(const vector<int>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 7);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 7);
|
||||
|
||||
return ((uint64_t)buf[offset] << 56) | ((uint64_t)buf[offset + 1] << 48) |
|
||||
((uint64_t)buf[offset + 2] << 40) | ((uint64_t)buf[offset + 3] << 32) |
|
||||
((uint64_t)buf[offset + 4] << 24) | ((uint64_t)buf[offset + 5] << 16) |
|
||||
((uint64_t)buf[offset + 6] << 8) | (uint64_t)buf[offset + 7];
|
||||
return (static_cast<uint64_t>(buf[offset]) << 56) | (static_cast<uint64_t>(buf[offset + 1]) << 48) |
|
||||
(static_cast<uint64_t>(buf[offset + 2]) << 40) | (static_cast<uint64_t>(buf[offset + 3]) << 32) |
|
||||
(static_cast<uint64_t>(buf[offset + 4]) << 24) | (static_cast<uint64_t>(buf[offset + 5]) << 16) |
|
||||
(static_cast<uint64_t>(buf[offset + 6]) << 8) | static_cast<uint64_t>(buf[offset + 7]);
|
||||
}
|
||||
|
||||
void scsi_command_util::SetInt16(vector<byte>& buf, int offset, int value)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 1);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 1);
|
||||
|
||||
buf[offset] = (byte)(value >> 8);
|
||||
buf[offset + 1] = (byte)value;
|
||||
buf[offset] = static_cast<byte>(value >> 8);
|
||||
buf[offset + 1] = static_cast<byte>(value);
|
||||
}
|
||||
|
||||
void scsi_command_util::SetInt32(vector<byte>& buf, int offset, uint32_t value)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 3);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 3);
|
||||
|
||||
buf[offset] = (byte)(value >> 24);
|
||||
buf[offset + 1] = (byte)(value >> 16);
|
||||
buf[offset + 2] = (byte)(value >> 8);
|
||||
buf[offset + 3] = (byte)value;
|
||||
buf[offset] = static_cast<byte>(value >> 24);
|
||||
buf[offset + 1] = static_cast<byte>(value >> 16);
|
||||
buf[offset + 2] = static_cast<byte>(value >> 8);
|
||||
buf[offset + 3] = static_cast<byte>(value);
|
||||
}
|
||||
|
||||
void scsi_command_util::SetInt16(vector<BYTE>& buf, int offset, int value)
|
||||
void scsi_command_util::SetInt16(vector<uint8_t>& buf, int offset, int value)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 1);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 1);
|
||||
|
||||
buf[offset] = (BYTE)(value >> 8);
|
||||
buf[offset + 1] = (BYTE)value;
|
||||
buf[offset] = static_cast<uint8_t>(value >> 8);
|
||||
buf[offset + 1] = static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
void scsi_command_util::SetInt32(vector<BYTE>& buf, int offset, uint32_t value)
|
||||
void scsi_command_util::SetInt32(vector<uint8_t>& buf, int offset, uint32_t value)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 3);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 3);
|
||||
|
||||
buf[offset] = (BYTE)(value >> 24);
|
||||
buf[offset + 1] = (BYTE)(value >> 16);
|
||||
buf[offset + 2] = (BYTE)(value >> 8);
|
||||
buf[offset + 3] = (BYTE)value;
|
||||
buf[offset] = static_cast<uint8_t>(value >> 24);
|
||||
buf[offset + 1] = static_cast<uint8_t>(value >> 16);
|
||||
buf[offset + 2] = static_cast<uint8_t>(value >> 8);
|
||||
buf[offset + 3] = static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
void scsi_command_util::SetInt64(vector<BYTE>& buf, int offset, uint64_t value)
|
||||
void scsi_command_util::SetInt64(vector<uint8_t>& buf, int offset, uint64_t value)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 7);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 7);
|
||||
|
||||
buf[offset] = (BYTE)(value >> 56);
|
||||
buf[offset + 1] = (BYTE)(value >> 48);
|
||||
buf[offset + 2] = (BYTE)(value >> 40);
|
||||
buf[offset + 3] = (BYTE)(value >> 32);
|
||||
buf[offset + 4] = (BYTE)(value >> 24);
|
||||
buf[offset + 5] = (BYTE)(value >> 16);
|
||||
buf[offset + 6] = (BYTE)(value >> 8);
|
||||
buf[offset + 7] = (BYTE)value;
|
||||
buf[offset] = static_cast<uint8_t>(value >> 56);
|
||||
buf[offset + 1] = static_cast<uint8_t>(value >> 48);
|
||||
buf[offset + 2] = static_cast<uint8_t>(value >> 40);
|
||||
buf[offset + 3] = static_cast<uint8_t>(value >> 32);
|
||||
buf[offset + 4] = static_cast<uint8_t>(value >> 24);
|
||||
buf[offset + 5] = static_cast<uint8_t>(value >> 16);
|
||||
buf[offset + 6] = static_cast<uint8_t>(value >> 8);
|
||||
buf[offset + 7] = static_cast<uint8_t>(value);
|
||||
}
|
||||
|
|
|
@ -19,18 +19,18 @@ using namespace std;
|
|||
|
||||
namespace scsi_command_util
|
||||
{
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<BYTE>&, int, int);
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<uint8_t>&, int, int);
|
||||
void EnrichFormatPage(map<int, vector<byte>>&, bool, int);
|
||||
void AddAppleVendorModePage(map<int, vector<byte>>&, bool);
|
||||
|
||||
int GetInt16(const vector<BYTE>&, int);
|
||||
int GetInt16(const vector<uint8_t>&, int);
|
||||
int GetInt16(const vector<int>&, int);
|
||||
int GetInt24(const vector<int>&, int);
|
||||
uint32_t GetInt32(const vector<int>&, int);
|
||||
uint64_t GetInt64(const vector<int>&, int);
|
||||
void SetInt16(vector<byte>&, int, int);
|
||||
void SetInt32(vector<byte>&, int, uint32_t);
|
||||
void SetInt16(vector<BYTE>&, int, int);
|
||||
void SetInt32(vector<BYTE>&, int, uint32_t);
|
||||
void SetInt64(vector<BYTE>&, int, uint64_t);
|
||||
void SetInt16(vector<uint8_t>&, int, int);
|
||||
void SetInt32(vector<uint8_t>&, int, uint32_t);
|
||||
void SetInt64(vector<uint8_t>&, int, uint64_t);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
using namespace scsi_defs;
|
||||
using namespace scsi_command_util;
|
||||
|
||||
// TODO Disk must not be the superclass
|
||||
SCSIDaynaPort::SCSIDaynaPort(int lun) : Disk(SCDP, lun)
|
||||
SCSIDaynaPort::SCSIDaynaPort(int lun) : PrimaryDevice(SCDP, lun)
|
||||
{
|
||||
dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady);
|
||||
dispatcher.Add(scsi_command::eCmdRead6, "Read6", &SCSIDaynaPort::Read6);
|
||||
|
@ -48,20 +47,10 @@ SCSIDaynaPort::SCSIDaynaPort(int lun) : Disk(SCDP, lun)
|
|||
SetSendDelay(DAYNAPORT_READ_HEADER_SZ);
|
||||
|
||||
SupportsParams(true);
|
||||
// TODO Remove as soon as SCDP is not a subclass of Disk anymore
|
||||
SetStoppable(false);
|
||||
// TODO Remove as soon as SCDP is not a subclass of Disk anymore
|
||||
SupportsFile(false);
|
||||
}
|
||||
|
||||
bool SCSIDaynaPort::Dispatch(scsi_command cmd)
|
||||
{
|
||||
// TODO As long as DaynaPort suffers from being a subclass of Disk at least reject MODE SENSE and MODE SELECT
|
||||
if (cmd == scsi_command::eCmdModeSense6 || cmd == scsi_command::eCmdModeSelect6 ||
|
||||
cmd == scsi_command::eCmdModeSense10 || cmd == scsi_command::eCmdModeSelect10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The superclass class handles the less specific commands
|
||||
return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd);
|
||||
}
|
||||
|
@ -89,18 +78,13 @@ bool SCSIDaynaPort::Init(const unordered_map<string, string>& params)
|
|||
return true;
|
||||
}
|
||||
|
||||
void SCSIDaynaPort::Open()
|
||||
{
|
||||
m_tap.OpenDump(GetFilename().c_str());
|
||||
}
|
||||
|
||||
vector<byte> SCSIDaynaPort::InquiryInternal() const
|
||||
{
|
||||
vector<byte> buf = HandleInquiry(device_type::PROCESSOR, scsi_level::SCSI_2, false);
|
||||
|
||||
// The Daynaport driver for the Mac expects 37 bytes: Increase additional length and
|
||||
// add a vendor-specific byte in order to satisfy this driver.
|
||||
buf[4] = (byte)((int)buf[4] + 1);
|
||||
buf[4] = (byte)(to_integer<int>(buf[4]) + 1);
|
||||
buf.push_back((byte)0);
|
||||
|
||||
return buf;
|
||||
|
@ -137,7 +121,7 @@ vector<byte> SCSIDaynaPort::InquiryInternal() const
|
|||
// - The SCSI/Link apparently has about 6KB buffer space for packets.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIDaynaPort::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t)
|
||||
int SCSIDaynaPort::Read(const vector<int>& cdb, vector<uint8_t>& buf, uint64_t)
|
||||
{
|
||||
int rx_packet_size = 0;
|
||||
const auto response = (scsi_resp_read_t*)buf.data();
|
||||
|
@ -145,8 +129,8 @@ int SCSIDaynaPort::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t)
|
|||
const int requested_length = cdb[4];
|
||||
LOGTRACE("%s Read maximum length %d, (%04X)", __PRETTY_FUNCTION__, requested_length, requested_length)
|
||||
|
||||
// At host startup, it will send a READ(6) command with a length of 1. We should
|
||||
// respond by going into the status mode with a code of 0x02
|
||||
// At startup the host may send a READ(6) command with a sector count of 1 to read the root sector.
|
||||
// We should respond by going into the status mode with a code of 0x02.
|
||||
if (requested_length == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -204,12 +188,12 @@ int SCSIDaynaPort::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t)
|
|||
if (!send_message_to_host) {
|
||||
LOGDEBUG("%s Received a packet that's not for me: %02X %02X %02X %02X %02X %02X", \
|
||||
__PRETTY_FUNCTION__,
|
||||
(int)response->data[0],
|
||||
(int)response->data[1],
|
||||
(int)response->data[2],
|
||||
(int)response->data[3],
|
||||
(int)response->data[4],
|
||||
(int)response->data[5])
|
||||
static_cast<int>(response->data[0]),
|
||||
static_cast<int>(response->data[1]),
|
||||
static_cast<int>(response->data[2]),
|
||||
static_cast<int>(response->data[3]),
|
||||
static_cast<int>(response->data[4]),
|
||||
static_cast<int>(response->data[5]))
|
||||
|
||||
// If there are pending packets to be processed, we'll tell the host that the read
|
||||
// length was 0.
|
||||
|
@ -253,17 +237,6 @@ int SCSIDaynaPort::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t)
|
|||
return DAYNAPORT_READ_HEADER_SZ;
|
||||
}
|
||||
|
||||
int SCSIDaynaPort::WriteCheck(uint64_t)
|
||||
{
|
||||
CheckReady();
|
||||
|
||||
if (!m_bTapEnable) {
|
||||
throw scsi_exception(sense_key::UNIT_ATTENTION, asc::MEDIUM_NOT_PRESENT);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Write
|
||||
|
@ -282,7 +255,7 @@ int SCSIDaynaPort::WriteCheck(uint64_t)
|
|||
// XX XX ... is the actual packet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool SCSIDaynaPort::WriteBytes(const vector<int>& cdb, const vector<BYTE>& buf, uint64_t)
|
||||
bool SCSIDaynaPort::WriteBytes(const vector<int>& cdb, vector<uint8_t>& buf, uint32_t)
|
||||
{
|
||||
const int data_format = cdb[5];
|
||||
int data_length = GetInt16(cdb, 3);
|
||||
|
@ -293,7 +266,7 @@ bool SCSIDaynaPort::WriteBytes(const vector<int>& cdb, const vector<BYTE>& buf,
|
|||
}
|
||||
else if (data_format == 0x80) {
|
||||
// The data length is specified in the first 2 bytes of the payload
|
||||
data_length = buf[1] + (((int)buf[0] & 0xff) << 8);
|
||||
data_length = buf[1] + ((static_cast<int>(buf[0]) & 0xff) << 8);
|
||||
m_tap.Send(&(buf.data()[4]), data_length);
|
||||
LOGTRACE("%s Transmitted %u bytes (80 format)", __PRETTY_FUNCTION__, data_length)
|
||||
}
|
||||
|
@ -301,6 +274,8 @@ bool SCSIDaynaPort::WriteBytes(const vector<int>& cdb, const vector<BYTE>& buf,
|
|||
LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, data_format)
|
||||
}
|
||||
|
||||
controller->SetBlocks(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -320,11 +295,11 @@ bool SCSIDaynaPort::WriteBytes(const vector<int>& cdb, const vector<BYTE>& buf,
|
|||
// - long #3: frames lost
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIDaynaPort::RetrieveStats(const vector<int>& cdb, vector<BYTE>& buf) const
|
||||
int SCSIDaynaPort::RetrieveStats(const vector<int>& cdb, vector<uint8_t>& buf) const
|
||||
{
|
||||
memcpy(buf.data(), &m_scsi_link_stats, sizeof(m_scsi_link_stats));
|
||||
|
||||
return (int)min(sizeof(m_scsi_link_stats), (size_t)GetInt16(cdb, 3));
|
||||
return static_cast<int>(min(sizeof(m_scsi_link_stats), static_cast<size_t>(GetInt16(cdb, 3))));
|
||||
}
|
||||
|
||||
void SCSIDaynaPort::TestUnitReady()
|
||||
|
@ -336,23 +311,24 @@ void SCSIDaynaPort::TestUnitReady()
|
|||
void SCSIDaynaPort::Read6()
|
||||
{
|
||||
// Get record number and block number
|
||||
const uint32_t record = GetInt24(ctrl->cmd, 1) & 0x1fffff;
|
||||
ctrl->blocks=1;
|
||||
const uint32_t record = GetInt24(controller->GetCmd(), 1) & 0x1fffff;
|
||||
controller->SetBlocks(1);
|
||||
|
||||
// If any commands have a bogus control value, they were probably not
|
||||
// generated by the DaynaPort driver so ignore them
|
||||
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])
|
||||
if (controller->GetCmd(5) != 0xc0 && controller->GetCmd(5) != 0x80) {
|
||||
LOGTRACE("%s Control value %d, (%04X), returning invalid CDB", __PRETTY_FUNCTION__,
|
||||
controller->GetCmd(5), controller->GetCmd(5))
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, record, ctrl->blocks)
|
||||
LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, record, controller->GetBlocks())
|
||||
|
||||
ctrl->length = Read(ctrl->cmd, controller->GetBuffer(), record);
|
||||
LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, ctrl->length)
|
||||
controller->SetLength(Read(controller->GetCmd(), controller->GetBuffer(), record));
|
||||
LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, controller->GetLength())
|
||||
|
||||
// Set next block
|
||||
ctrl->next = record + 1;
|
||||
controller->SetNext(record + 1);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -362,37 +338,38 @@ void SCSIDaynaPort::Write6()
|
|||
// Ensure a sufficient buffer size (because it is not transfer for each block)
|
||||
controller->AllocateBuffer(DAYNAPORT_BUFFER_SIZE);
|
||||
|
||||
const int data_format = ctrl->cmd[5];
|
||||
const int data_format = controller->GetCmd(5);
|
||||
|
||||
if (data_format == 0x00) {
|
||||
ctrl->length = GetInt16(ctrl->cmd, 3);
|
||||
controller->SetLength(GetInt16(controller->GetCmd(), 3));
|
||||
}
|
||||
else if (data_format == 0x80) {
|
||||
ctrl->length = GetInt16(ctrl->cmd, 3) + 8;
|
||||
controller->SetLength(GetInt16(controller->GetCmd(), 3) + 8);
|
||||
}
|
||||
else {
|
||||
LOGWARN("%s Unknown data format $%02X", __PRETTY_FUNCTION__, data_format)
|
||||
}
|
||||
LOGTRACE("%s length: $%04X (%d) format: $%02X", __PRETTY_FUNCTION__, ctrl->length, ctrl->length, data_format)
|
||||
LOGTRACE("%s length: $%04X (%d) format: $%02X", __PRETTY_FUNCTION__, controller->GetLength(),
|
||||
controller->GetLength(), data_format)
|
||||
|
||||
if (ctrl->length <= 0) {
|
||||
if (controller->GetLength() <= 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
// Set next block
|
||||
ctrl->blocks = 1;
|
||||
ctrl->next = 1;
|
||||
controller->SetBlocks(1);
|
||||
controller->SetNext(1);
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
||||
void SCSIDaynaPort::RetrieveStatistics()
|
||||
{
|
||||
ctrl->length = RetrieveStats(ctrl->cmd, controller->GetBuffer());
|
||||
controller->SetLength(RetrieveStats(controller->GetCmd(), controller->GetBuffer()));
|
||||
|
||||
// Set next block
|
||||
ctrl->blocks = 1;
|
||||
ctrl->next = 1;
|
||||
controller->SetBlocks(1);
|
||||
controller->SetNext(1);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -427,27 +404,27 @@ void SCSIDaynaPort::SetInterfaceMode()
|
|||
{
|
||||
// Check whether this command is telling us to "Set Interface Mode" or "Set MAC Address"
|
||||
|
||||
ctrl->length = RetrieveStats(ctrl->cmd, controller->GetBuffer());
|
||||
switch(ctrl->cmd[5]){
|
||||
controller->SetLength(RetrieveStats(controller->GetCmd(), controller->GetBuffer()));
|
||||
switch(controller->GetCmd(5)){
|
||||
case CMD_SCSILINK_SETMODE:
|
||||
// TODO Not implemented, do nothing
|
||||
EnterStatusPhase();
|
||||
break;
|
||||
|
||||
case CMD_SCSILINK_SETMAC:
|
||||
ctrl->length = 6;
|
||||
controller->SetLength(6);
|
||||
EnterDataOutPhase();
|
||||
break;
|
||||
|
||||
case CMD_SCSILINK_STATS:
|
||||
case CMD_SCSILINK_ENABLE:
|
||||
case CMD_SCSILINK_SET:
|
||||
LOGWARN("%s Unsupported SetInterface command received: %02X", __PRETTY_FUNCTION__, ctrl->cmd[5])
|
||||
LOGWARN("%s Unsupported SetInterface command received: %02X", __PRETTY_FUNCTION__, controller->GetCmd(5))
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGWARN("%s Unknown SetInterface command received: %02X", __PRETTY_FUNCTION__, ctrl->cmd[5])
|
||||
LOGWARN("%s Unknown SetInterface command received: %02X", __PRETTY_FUNCTION__, controller->GetCmd(5))
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE);
|
||||
break;
|
||||
}
|
||||
|
@ -455,9 +432,9 @@ void SCSIDaynaPort::SetInterfaceMode()
|
|||
|
||||
void SCSIDaynaPort::SetMcastAddr()
|
||||
{
|
||||
ctrl->length = ctrl->cmd[4];
|
||||
if (ctrl->length == 0) {
|
||||
LOGWARN("%s Not supported SetMcastAddr Command %02X", __PRETTY_FUNCTION__, ctrl->cmd[2])
|
||||
controller->SetLength(controller->GetCmd(4));
|
||||
if (controller->GetLength() == 0) {
|
||||
LOGWARN("%s Not supported SetMcastAddr Command %02X", __PRETTY_FUNCTION__, controller->GetCmd(2))
|
||||
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
@ -479,7 +456,7 @@ void SCSIDaynaPort::SetMcastAddr()
|
|||
//---------------------------------------------------------------------------
|
||||
void SCSIDaynaPort::EnableInterface()
|
||||
{
|
||||
if (ctrl->cmd[5] & 0x80) {
|
||||
if (controller->GetCmd(5) & 0x80) {
|
||||
if (!m_tap.Enable()) {
|
||||
LOGWARN("Unable to enable the DaynaPort Interface")
|
||||
|
||||
|
@ -502,3 +479,4 @@ void SCSIDaynaPort::EnableInterface()
|
|||
|
||||
EnterStatusPhase();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "os.h"
|
||||
#include "disk.h"
|
||||
#include "interfaces/byte_writer.h"
|
||||
#include "primary_device.h"
|
||||
#include "ctapdriver.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -41,7 +41,7 @@
|
|||
// DaynaPort SCSI Link
|
||||
//
|
||||
//===========================================================================
|
||||
class SCSIDaynaPort : public Disk
|
||||
class SCSIDaynaPort : public PrimaryDevice, public ByteWriter
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -49,19 +49,17 @@ public:
|
|||
~SCSIDaynaPort() override = default;
|
||||
|
||||
bool Init(const unordered_map<string, string>&) override;
|
||||
void Open() override;
|
||||
|
||||
// Commands
|
||||
vector<byte> InquiryInternal() const override;
|
||||
int Read(const vector<int>&, vector<BYTE>&, uint64_t) override;
|
||||
bool WriteBytes(const vector<int>&, const vector<BYTE>&, uint64_t);
|
||||
int WriteCheck(uint64_t block) override;
|
||||
int Read(const vector<int>&, vector<uint8_t>&, uint64_t);
|
||||
bool WriteBytes(const vector<int>&, vector<uint8_t>&, uint32_t) override;
|
||||
|
||||
int RetrieveStats(const vector<int>&, vector<BYTE>&) const;
|
||||
int RetrieveStats(const vector<int>&, vector<uint8_t>&) const;
|
||||
|
||||
void TestUnitReady() override;
|
||||
void Read6() override;
|
||||
void Write6() override;
|
||||
void Read6();
|
||||
void Write6();
|
||||
void RetrieveStatistics();
|
||||
void SetInterfaceMode();
|
||||
void SetMcastAddr();
|
||||
|
@ -90,7 +88,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
using super = Disk;
|
||||
using super = PrimaryDevice;
|
||||
|
||||
Dispatcher<SCSIDaynaPort> dispatcher;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ using namespace std;
|
|||
using namespace scsi_defs;
|
||||
using namespace scsi_command_util;
|
||||
|
||||
SCSIBR::SCSIBR(int lun) : Disk(SCBR, lun)
|
||||
SCSIBR::SCSIBR(int lun) : PrimaryDevice(SCBR, lun)
|
||||
{
|
||||
// Create host file system
|
||||
fs.Reset();
|
||||
|
@ -37,10 +37,6 @@ SCSIBR::SCSIBR(int lun) : Disk(SCBR, lun)
|
|||
dispatcher.Add(scsi_command::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10);
|
||||
|
||||
SupportsParams(true);
|
||||
// TODO Remove as soon as SCBR is not a subclass of Disk anymore
|
||||
SetStoppable(false);
|
||||
// TODO Remove as soon as SCBR is not a subclass of Disk anymore
|
||||
SupportsFile(false);
|
||||
}
|
||||
|
||||
bool SCSIBR::Init(const unordered_map<string, string>& params)
|
||||
|
@ -110,7 +106,7 @@ void SCSIBR::TestUnitReady()
|
|||
EnterStatusPhase();
|
||||
}
|
||||
|
||||
int SCSIBR::GetMessage10(const vector<int>& cdb, vector<BYTE>& buf)
|
||||
int SCSIBR::GetMessage10(const vector<int>& cdb, vector<uint8_t>& buf)
|
||||
{
|
||||
// Type
|
||||
const int type = cdb[2];
|
||||
|
@ -198,7 +194,7 @@ int SCSIBR::GetMessage10(const vector<int>& cdb, vector<BYTE>& buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool SCSIBR::WriteBytes(const vector<int>& cdb, vector<BYTE>& buf, uint64_t)
|
||||
bool SCSIBR::WriteBytes(const vector<int>& cdb, vector<uint8_t>& buf, uint32_t)
|
||||
{
|
||||
// Type
|
||||
const int type = cdb[2];
|
||||
|
@ -261,14 +257,14 @@ void SCSIBR::GetMessage10()
|
|||
// Ensure a sufficient buffer size (because it is not a transfer for each block)
|
||||
controller->AllocateBuffer(0x1000000);
|
||||
|
||||
ctrl->length = GetMessage10(ctrl->cmd, controller->GetBuffer());
|
||||
if (ctrl->length <= 0) {
|
||||
controller->SetLength(GetMessage10(controller->GetCmd(), controller->GetBuffer()));
|
||||
if (controller->GetLength() <= 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
// Set next block
|
||||
ctrl->blocks = 1;
|
||||
ctrl->next = 1;
|
||||
controller->SetBlocks(1);
|
||||
controller->SetNext(1);
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -282,8 +278,8 @@ void SCSIBR::GetMessage10()
|
|||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::SendMessage10()
|
||||
{
|
||||
ctrl->length = GetInt24(ctrl->cmd, 6);
|
||||
if (ctrl->length <= 0) {
|
||||
controller->SetLength(GetInt24(controller->GetCmd(), 6));
|
||||
if (controller->GetLength() <= 0) {
|
||||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
|
@ -291,19 +287,19 @@ void SCSIBR::SendMessage10()
|
|||
controller->AllocateBuffer(0x1000000);
|
||||
|
||||
// Set next block
|
||||
ctrl->blocks = 1;
|
||||
ctrl->next = 1;
|
||||
controller->SetBlocks(1);
|
||||
controller->SetNext(1);
|
||||
|
||||
EnterDataOutPhase();
|
||||
}
|
||||
|
||||
int SCSIBR::GetMacAddr(vector<BYTE>& mac) const
|
||||
int SCSIBR::GetMacAddr(vector<uint8_t>& mac) const
|
||||
{
|
||||
memcpy(mac.data(), mac_addr.data(), mac_addr.size());
|
||||
return (int)mac_addr.size();
|
||||
return static_cast<int>(mac_addr.size());
|
||||
}
|
||||
|
||||
void SCSIBR::SetMacAddr(const vector<BYTE>& mac)
|
||||
void SCSIBR::SetMacAddr(const vector<uint8_t>& mac)
|
||||
{
|
||||
memcpy(mac_addr.data(), mac.data(), mac_addr.size());
|
||||
}
|
||||
|
@ -335,7 +331,7 @@ void SCSIBR::ReceivePacket()
|
|||
}
|
||||
}
|
||||
|
||||
void SCSIBR::GetPacketBuf(vector<BYTE>& buf, int index)
|
||||
void SCSIBR::GetPacketBuf(vector<uint8_t>& buf, int index)
|
||||
{
|
||||
// Size limit
|
||||
int len = packet_len;
|
||||
|
@ -350,7 +346,7 @@ void SCSIBR::GetPacketBuf(vector<BYTE>& buf, int index)
|
|||
packet_enable = false;
|
||||
}
|
||||
|
||||
void SCSIBR::SendPacket(const vector<BYTE>& buf, int len)
|
||||
void SCSIBR::SendPacket(const vector<uint8_t>& buf, int len)
|
||||
{
|
||||
tap.Send(buf.data(), len);
|
||||
}
|
||||
|
@ -360,7 +356,7 @@ void SCSIBR::SendPacket(const vector<BYTE>& buf, int len)
|
|||
// $40 - Device Boot
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_InitDevice(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_InitDevice(vector<uint8_t>& buf)
|
||||
{
|
||||
fs.Reset();
|
||||
fsresult = fs.InitDevice((Human68k::argument_t*)buf.data());
|
||||
|
@ -371,7 +367,7 @@ void SCSIBR::FS_InitDevice(vector<BYTE>& buf)
|
|||
// $41 - Directory Check
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CheckDir(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_CheckDir(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -387,7 +383,7 @@ void SCSIBR::FS_CheckDir(vector<BYTE>& buf)
|
|||
// $42 - Create Directory
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_MakeDir(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_MakeDir(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -403,7 +399,7 @@ void SCSIBR::FS_MakeDir(vector<BYTE>& buf)
|
|||
// $43 - Remove Directory
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_RemoveDir(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_RemoveDir(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -419,7 +415,7 @@ void SCSIBR::FS_RemoveDir(vector<BYTE>& buf)
|
|||
// $44 - Rename
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Rename(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Rename(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -438,7 +434,7 @@ void SCSIBR::FS_Rename(vector<BYTE>& buf)
|
|||
// $45 - Delete File
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Delete(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Delete(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -454,7 +450,7 @@ void SCSIBR::FS_Delete(vector<BYTE>& buf)
|
|||
// $46 - Get / Set file attributes
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Attribute(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Attribute(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -474,7 +470,7 @@ void SCSIBR::FS_Attribute(vector<BYTE>& buf)
|
|||
// $47 - File Search
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Files(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Files(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -515,7 +511,7 @@ void SCSIBR::FS_Files(vector<BYTE>& buf)
|
|||
// $48 - File next search
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_NFiles(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_NFiles(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -553,7 +549,7 @@ void SCSIBR::FS_NFiles(vector<BYTE>& buf)
|
|||
// $49 - File Creation
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Create(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Create(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -602,7 +598,7 @@ void SCSIBR::FS_Create(vector<BYTE>& buf)
|
|||
// $4A - Open File
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Open(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Open(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -643,7 +639,7 @@ void SCSIBR::FS_Open(vector<BYTE>& buf)
|
|||
// $4B - Close File
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Close(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Close(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -681,7 +677,7 @@ void SCSIBR::FS_Close(vector<BYTE>& buf)
|
|||
// $4C - Read File
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Read(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Read(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nKey = ntohl(*dp);
|
||||
|
@ -721,7 +717,7 @@ void SCSIBR::FS_Read(vector<BYTE>& buf)
|
|||
// $4D - Write file
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Write(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Write(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nKey = ntohl(*dp);
|
||||
|
@ -759,7 +755,7 @@ void SCSIBR::FS_Write(vector<BYTE>& buf)
|
|||
// $4E - Seek file
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Seek(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Seek(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nKey = ntohl(*dp);
|
||||
|
@ -801,7 +797,7 @@ void SCSIBR::FS_Seek(vector<BYTE>& buf)
|
|||
// $4F - File Timestamp Get / Set
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_TimeStamp(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_TimeStamp(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -843,7 +839,7 @@ void SCSIBR::FS_TimeStamp(vector<BYTE>& buf)
|
|||
// $50 - Get Capacity
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_GetCapacity(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_GetCapacity(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -865,7 +861,7 @@ void SCSIBR::FS_GetCapacity(vector<BYTE>& buf)
|
|||
// $51 - Drive status inspection/control
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CtrlDrive(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_CtrlDrive(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -884,7 +880,7 @@ void SCSIBR::FS_CtrlDrive(vector<BYTE>& buf)
|
|||
// $52 - Get DPB
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_GetDPB(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_GetDPB(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -908,7 +904,7 @@ void SCSIBR::FS_GetDPB(vector<BYTE>& buf)
|
|||
// $53 - Read Sector
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_DiskRead(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_DiskRead(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -930,7 +926,7 @@ void SCSIBR::FS_DiskRead(vector<BYTE>& buf)
|
|||
// $54 - Write Sector
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_DiskWrite(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_DiskWrite(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -943,7 +939,7 @@ void SCSIBR::FS_DiskWrite(vector<BYTE>& buf)
|
|||
// $55 - IOCTRL
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Ioctrl(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Ioctrl(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -989,7 +985,7 @@ void SCSIBR::FS_Ioctrl(vector<BYTE>& buf)
|
|||
// $56 - Flush
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Flush(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Flush(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -1002,7 +998,7 @@ void SCSIBR::FS_Flush(vector<BYTE>& buf)
|
|||
// $57 - Check Media
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_CheckMedia(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_CheckMedia(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -1015,7 +1011,7 @@ void SCSIBR::FS_CheckMedia(vector<BYTE>& buf)
|
|||
// $58 - Lock
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::FS_Lock(vector<BYTE>& buf)
|
||||
void SCSIBR::FS_Lock(vector<uint8_t>& buf)
|
||||
{
|
||||
auto dp = (uint32_t*)buf.data();
|
||||
const uint32_t nUnit = ntohl(*dp);
|
||||
|
@ -1028,7 +1024,7 @@ void SCSIBR::FS_Lock(vector<BYTE>& buf)
|
|||
// Read Filesystem (result code)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsResult(vector<BYTE>& buf) const
|
||||
int SCSIBR::ReadFsResult(vector<uint8_t>& buf) const
|
||||
{
|
||||
auto dp = (uint32_t *)buf.data();
|
||||
*dp = htonl(fsresult);
|
||||
|
@ -1040,7 +1036,7 @@ int SCSIBR::ReadFsResult(vector<BYTE>& buf) const
|
|||
// Read Filesystem (return data)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsOut(vector<BYTE>& buf) const
|
||||
int SCSIBR::ReadFsOut(vector<uint8_t>& buf) const
|
||||
{
|
||||
copy_n(fsout.begin(), fsoutlen, buf.begin());
|
||||
return fsoutlen;
|
||||
|
@ -1051,7 +1047,7 @@ int SCSIBR::ReadFsOut(vector<BYTE>& buf) const
|
|||
// Read file system (return option data)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int SCSIBR::ReadFsOpt(vector<BYTE>& buf) const
|
||||
int SCSIBR::ReadFsOpt(vector<uint8_t>& buf) const
|
||||
{
|
||||
copy_n(fsopt.begin(), fsoptlen, buf.begin());
|
||||
return fsoptlen;
|
||||
|
@ -1062,7 +1058,7 @@ int SCSIBR::ReadFsOpt(vector<BYTE>& buf) const
|
|||
// Write Filesystem
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::WriteFs(int func, vector<BYTE>& buf)
|
||||
void SCSIBR::WriteFs(int func, vector<uint8_t>& buf)
|
||||
{
|
||||
fsresult = FS_FATAL_INVALIDCOMMAND;
|
||||
fsoutlen = 0;
|
||||
|
@ -1155,7 +1151,7 @@ void SCSIBR::WriteFs(int func, vector<BYTE>& buf)
|
|||
// File system write (input option data)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSIBR::WriteFsOpt(const vector<BYTE>& buf, int num)
|
||||
void SCSIBR::WriteFsOpt(const vector<uint8_t>& buf, int num)
|
||||
{
|
||||
copy_n(buf.begin(), num, fsopt.begin());
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
//---------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#include "os.h"
|
||||
#include "disk.h"
|
||||
#include "interfaces/byte_writer.h"
|
||||
#include "primary_device.h"
|
||||
#include "ctapdriver.h"
|
||||
#include "cfilesystem.h"
|
||||
#include <string>
|
||||
|
@ -26,9 +26,9 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
class SCSIBR : public Disk
|
||||
class SCSIBR : public PrimaryDevice, public ByteWriter
|
||||
{
|
||||
static constexpr const array<BYTE, 6> bcast_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
static constexpr const array<uint8_t, 6> bcast_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
public:
|
||||
|
||||
|
@ -38,73 +38,70 @@ public:
|
|||
bool Init(const unordered_map<string, string>&) override;
|
||||
bool Dispatch(scsi_command) override;
|
||||
|
||||
// TODO Remove as soon as SCSIBR is not a subclass of Disk anymore
|
||||
void Open() override { super::ValidateFile(); }
|
||||
|
||||
// Commands
|
||||
vector<byte> InquiryInternal() const override;
|
||||
int GetMessage10(const vector<int>&, vector<BYTE>&);
|
||||
bool WriteBytes(const vector<int>&, vector<BYTE>&, uint64_t);
|
||||
int GetMessage10(const vector<int>&, vector<uint8_t>&);
|
||||
bool WriteBytes(const vector<int>&, vector<uint8_t>&, uint32_t) override;
|
||||
void TestUnitReady() override;
|
||||
void GetMessage10();
|
||||
void SendMessage10();
|
||||
|
||||
private:
|
||||
|
||||
using super = Disk;
|
||||
using super = PrimaryDevice;
|
||||
|
||||
Dispatcher<SCSIBR> dispatcher;
|
||||
|
||||
int GetMacAddr(vector<BYTE>&) const; // Get MAC address
|
||||
void SetMacAddr(const vector<BYTE>&); // Set MAC address
|
||||
int GetMacAddr(vector<uint8_t>&) const; // Get MAC address
|
||||
void SetMacAddr(const vector<uint8_t>&); // Set MAC address
|
||||
void ReceivePacket(); // Receive a packet
|
||||
void GetPacketBuf(vector<BYTE>&, int); // Get a packet
|
||||
void SendPacket(const vector<BYTE>&, int); // Send a packet
|
||||
void GetPacketBuf(vector<uint8_t>&, int); // Get a packet
|
||||
void SendPacket(const vector<uint8_t>&, int); // Send a packet
|
||||
|
||||
CTapDriver tap; // TAP driver
|
||||
bool m_bTapEnable = false; // TAP valid flag
|
||||
array<BYTE, 6> mac_addr = {}; // MAC Address
|
||||
array<uint8_t, 6> mac_addr = {}; // MAC Address
|
||||
int packet_len = 0; // Receive packet size
|
||||
array<BYTE, 0x1000> packet_buf; // Receive packet buffer
|
||||
array<uint8_t, 0x1000> packet_buf; // Receive packet buffer
|
||||
bool packet_enable = false; // Received packet valid
|
||||
|
||||
int ReadFsResult(vector<BYTE>&) const; // Read filesystem (result code)
|
||||
int ReadFsOut(vector<BYTE>&) const; // Read filesystem (return data)
|
||||
int ReadFsOpt(vector<BYTE>&) const; // Read file system (optional data)
|
||||
void WriteFs(int, vector<BYTE>&); // File system write (execute)
|
||||
void WriteFsOpt(const vector<BYTE>&, int); // File system write (optional data)
|
||||
int ReadFsResult(vector<uint8_t>&) const; // Read filesystem (result code)
|
||||
int ReadFsOut(vector<uint8_t>&) const; // Read filesystem (return data)
|
||||
int ReadFsOpt(vector<uint8_t>&) const; // Read file system (optional data)
|
||||
void WriteFs(int, vector<uint8_t>&); // File system write (execute)
|
||||
void WriteFsOpt(const vector<uint8_t>&, int); // File system write (optional data)
|
||||
|
||||
// Command handlers
|
||||
void FS_InitDevice(vector<BYTE>&); // $40 - boot
|
||||
void FS_CheckDir(vector<BYTE>&); // $41 - directory check
|
||||
void FS_MakeDir(vector<BYTE>&); // $42 - create directory
|
||||
void FS_RemoveDir(vector<BYTE>&); // $43 - delete directory
|
||||
void FS_Rename(vector<BYTE>&); // $44 - change filename
|
||||
void FS_Delete(vector<BYTE>&); // $45 - delete file
|
||||
void FS_Attribute(vector<BYTE>&); // $46 - get/set file attributes
|
||||
void FS_Files(vector<BYTE>&); // $47 - file search
|
||||
void FS_NFiles(vector<BYTE>&); // $48 - find next file
|
||||
void FS_Create(vector<BYTE>&); // $49 - create file
|
||||
void FS_Open(vector<BYTE>&); // $4A - open file
|
||||
void FS_Close(vector<BYTE>&); // $4B - close file
|
||||
void FS_Read(vector<BYTE>&); // $4C - read file
|
||||
void FS_Write(vector<BYTE>&); // $4D - write file
|
||||
void FS_Seek(vector<BYTE>&); // $4E - seek file
|
||||
void FS_TimeStamp(vector<BYTE>&); // $4F - get/set file time
|
||||
void FS_GetCapacity(vector<BYTE>&); // $50 - get capacity
|
||||
void FS_CtrlDrive(vector<BYTE>&); // $51 - drive status check/control
|
||||
void FS_GetDPB(vector<BYTE>&); // $52 - get DPB
|
||||
void FS_DiskRead(vector<BYTE>&); // $53 - read sector
|
||||
void FS_DiskWrite(vector<BYTE>&); // $54 - write sector
|
||||
void FS_Ioctrl(vector<BYTE>&); // $55 - IOCTRL
|
||||
void FS_Flush(vector<BYTE>&); // $56 - flush cache
|
||||
void FS_CheckMedia(vector<BYTE>&); // $57 - check media
|
||||
void FS_Lock(vector<BYTE>&); // $58 - get exclusive control
|
||||
void FS_InitDevice(vector<uint8_t>&); // $40 - boot
|
||||
void FS_CheckDir(vector<uint8_t>&); // $41 - directory check
|
||||
void FS_MakeDir(vector<uint8_t>&); // $42 - create directory
|
||||
void FS_RemoveDir(vector<uint8_t>&); // $43 - delete directory
|
||||
void FS_Rename(vector<uint8_t>&); // $44 - change filename
|
||||
void FS_Delete(vector<uint8_t>&); // $45 - delete file
|
||||
void FS_Attribute(vector<uint8_t>&); // $46 - get/set file attributes
|
||||
void FS_Files(vector<uint8_t>&); // $47 - file search
|
||||
void FS_NFiles(vector<uint8_t>&); // $48 - find next file
|
||||
void FS_Create(vector<uint8_t>&); // $49 - create file
|
||||
void FS_Open(vector<uint8_t>&); // $4A - open file
|
||||
void FS_Close(vector<uint8_t>&); // $4B - close file
|
||||
void FS_Read(vector<uint8_t>&); // $4C - read file
|
||||
void FS_Write(vector<uint8_t>&); // $4D - write file
|
||||
void FS_Seek(vector<uint8_t>&); // $4E - seek file
|
||||
void FS_TimeStamp(vector<uint8_t>&); // $4F - get/set file time
|
||||
void FS_GetCapacity(vector<uint8_t>&); // $50 - get capacity
|
||||
void FS_CtrlDrive(vector<uint8_t>&); // $51 - drive status check/control
|
||||
void FS_GetDPB(vector<uint8_t>&); // $52 - get DPB
|
||||
void FS_DiskRead(vector<uint8_t>&); // $53 - read sector
|
||||
void FS_DiskWrite(vector<uint8_t>&); // $54 - write sector
|
||||
void FS_Ioctrl(vector<uint8_t>&); // $55 - IOCTRL
|
||||
void FS_Flush(vector<uint8_t>&); // $56 - flush cache
|
||||
void FS_CheckMedia(vector<uint8_t>&); // $57 - check media
|
||||
void FS_Lock(vector<uint8_t>&); // $58 - get exclusive control
|
||||
|
||||
CFileSys fs; // File system accessor
|
||||
uint32_t fsresult = 0; // File system access result code
|
||||
array<BYTE, 0x800> fsout; // File system access result buffer
|
||||
array<uint8_t, 0x800> fsout; // File system access result buffer
|
||||
uint32_t fsoutlen = 0; // File system access result buffer size
|
||||
array<BYTE, 0x1000000> fsopt; // File system access buffer
|
||||
array<uint8_t, 0x1000000> fsopt; // File system access buffer
|
||||
uint32_t fsoptlen = 0; // File system access buffer size
|
||||
};
|
||||
|
|
|
@ -98,7 +98,7 @@ vector<byte> SCSIPrinter::InquiryInternal() const
|
|||
|
||||
void SCSIPrinter::Print()
|
||||
{
|
||||
const uint32_t length = GetInt24(ctrl->cmd, 2);
|
||||
const uint32_t length = GetInt24(controller->GetCmd(), 2);
|
||||
|
||||
LOGTRACE("Receiving %d byte(s) to be printed", length)
|
||||
|
||||
|
@ -109,7 +109,7 @@ void SCSIPrinter::Print()
|
|||
throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
|
||||
ctrl->length = length;
|
||||
controller->SetLength(length);
|
||||
controller->SetByteTransfer(true);
|
||||
|
||||
EnterDataOutPhase();
|
||||
|
@ -147,7 +147,7 @@ void SCSIPrinter::SynchronizeBuffer()
|
|||
EnterStatusPhase();
|
||||
}
|
||||
|
||||
bool SCSIPrinter::WriteByteSequence(vector<BYTE>& buf, uint32_t length)
|
||||
bool SCSIPrinter::WriteByteSequence(vector<uint8_t>& buf, uint32_t length)
|
||||
{
|
||||
if (!out.is_open()) {
|
||||
vector<char> f(file_template.begin(), file_template.end());
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
void Print() override;
|
||||
void SynchronizeBuffer();
|
||||
|
||||
bool WriteByteSequence(vector<BYTE>&, uint32_t) override;
|
||||
bool WriteByteSequence(vector<uint8_t>&, uint32_t) override;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -123,9 +123,9 @@ void SCSICD::OpenIso()
|
|||
+ to_string(size) + " bytes");
|
||||
}
|
||||
|
||||
SetBlockCount((uint32_t)(size / 2352));
|
||||
SetBlockCount(static_cast<uint32_t>(size / 2352));
|
||||
} else {
|
||||
SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount()));
|
||||
SetBlockCount(static_cast<uint32_t>(size >> GetSectorSizeShiftCount()));
|
||||
}
|
||||
|
||||
CreateDataTrack();
|
||||
|
@ -144,7 +144,7 @@ void SCSICD::OpenPhysical()
|
|||
size = (size / 512) * 512;
|
||||
|
||||
// Set the number of blocks
|
||||
SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount()));
|
||||
SetBlockCount(static_cast<uint32_t>(size >> GetSectorSizeShiftCount()));
|
||||
|
||||
CreateDataTrack();
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ void SCSICD::CreateDataTrack()
|
|||
// Create only one data track
|
||||
assert(!tracks.size());
|
||||
auto track = make_unique<CDTrack>();
|
||||
track->Init(1, 0, (int)GetBlockCount() - 1);
|
||||
track->Init(1, 0, static_cast<int>(GetBlockCount()) - 1);
|
||||
track->SetPath(false, GetFilename());
|
||||
tracks.push_back(move(track));
|
||||
dataindex = 0;
|
||||
|
@ -162,7 +162,7 @@ void SCSICD::CreateDataTrack()
|
|||
|
||||
void SCSICD::ReadToc()
|
||||
{
|
||||
ctrl->length = ReadTocInternal(ctrl->cmd, controller->GetBuffer());
|
||||
controller->SetLength(ReadTocInternal(controller->GetCmd(), controller->GetBuffer()));
|
||||
|
||||
EnterDataInPhase();
|
||||
}
|
||||
|
@ -222,12 +222,12 @@ void SCSICD::AddVendorPage(map<int, vector<byte>>& pages, int page, bool changea
|
|||
}
|
||||
}
|
||||
|
||||
int SCSICD::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t block)
|
||||
int SCSICD::Read(const vector<int>& cdb, vector<uint8_t>& buf, uint64_t block)
|
||||
{
|
||||
CheckReady();
|
||||
|
||||
// Search for the track
|
||||
const int index = SearchTrack((int)block);
|
||||
const int index = SearchTrack(static_cast<int>(block));
|
||||
|
||||
// If invalid, out of range
|
||||
if (index < 0) {
|
||||
|
@ -254,7 +254,7 @@ int SCSICD::Read(const vector<int>& cdb, vector<BYTE>& buf, uint64_t block)
|
|||
return super::Read(cdb, buf, block);
|
||||
}
|
||||
|
||||
int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<BYTE>& buf)
|
||||
int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<uint8_t>& buf)
|
||||
{
|
||||
CheckReady();
|
||||
|
||||
|
@ -296,8 +296,8 @@ int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<BYTE>& buf)
|
|||
// Returns the final LBA+1 because it is AA
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x0a;
|
||||
buf[2] = (BYTE)tracks[0]->GetTrackNo();
|
||||
buf[3] = (BYTE)last;
|
||||
buf[2] = (uint8_t)tracks[0]->GetTrackNo();
|
||||
buf[3] = (uint8_t)last;
|
||||
buf[6] = 0xaa;
|
||||
const uint32_t lba = tracks[tracks.size() - 1]->GetLast() + 1;
|
||||
if (msf) {
|
||||
|
@ -316,8 +316,8 @@ int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<BYTE>& buf)
|
|||
|
||||
// Create header
|
||||
SetInt16(buf, 0, (loop << 3) + 2);
|
||||
buf[2] = (BYTE)tracks[0]->GetTrackNo();
|
||||
buf[3] = (BYTE)last;
|
||||
buf[2] = (uint8_t)tracks[0]->GetTrackNo();
|
||||
buf[3] = (uint8_t)last;
|
||||
|
||||
int offset = 4;
|
||||
|
||||
|
@ -333,7 +333,7 @@ int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<BYTE>& buf)
|
|||
}
|
||||
|
||||
// track number
|
||||
buf[offset + 2] = (BYTE)tracks[index]->GetTrackNo();
|
||||
buf[offset + 2] = (uint8_t)tracks[index]->GetTrackNo();
|
||||
|
||||
// track address
|
||||
if (msf) {
|
||||
|
@ -356,7 +356,7 @@ int SCSICD::ReadTocInternal(const vector<int>& cdb, vector<BYTE>& buf)
|
|||
// LBA→MSF Conversion
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SCSICD::LBAtoMSF(uint32_t lba, BYTE *msf) const
|
||||
void SCSICD::LBAtoMSF(uint32_t lba, uint8_t *msf) const
|
||||
{
|
||||
// 75 and 75*60 get the remainder
|
||||
uint32_t m = lba / (75 * 60);
|
||||
|
@ -376,9 +376,9 @@ void SCSICD::LBAtoMSF(uint32_t lba, BYTE *msf) const
|
|||
assert(s < 60);
|
||||
assert(f < 75);
|
||||
msf[0] = 0x00;
|
||||
msf[1] = (BYTE)m;
|
||||
msf[2] = (BYTE)s;
|
||||
msf[3] = (BYTE)f;
|
||||
msf[1] = (uint8_t)m;
|
||||
msf[2] = (uint8_t)s;
|
||||
msf[3] = (uint8_t)f;
|
||||
}
|
||||
|
||||
void SCSICD::ClearTrack()
|
||||
|
@ -403,7 +403,7 @@ int SCSICD::SearchTrack(uint32_t lba) const
|
|||
// Listen to the track
|
||||
assert(tracks[i]);
|
||||
if (tracks[i]->IsValid(lba)) {
|
||||
return (int)i;
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
// Commands
|
||||
vector<byte> InquiryInternal() const override;
|
||||
int Read(const vector<int>&, vector<BYTE>&, uint64_t) override;
|
||||
int Read(const vector<int>&, vector<uint8_t>&, uint64_t) override;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -44,7 +44,7 @@ private:
|
|||
|
||||
Dispatcher<SCSICD> dispatcher;
|
||||
|
||||
int ReadTocInternal(const vector<int>&, vector<BYTE>&);
|
||||
int ReadTocInternal(const vector<int>&, vector<uint8_t>&);
|
||||
|
||||
void AddCDROMPage(map<int, vector<byte>>&, bool) const;
|
||||
void AddCDDAPage(map<int, vector<byte>>&, bool) const;
|
||||
|
@ -56,7 +56,7 @@ private:
|
|||
|
||||
void ReadToc() override;
|
||||
|
||||
void LBAtoMSF(uint32_t, BYTE *) const; // LBA→MSF conversion
|
||||
void LBAtoMSF(uint32_t, uint8_t *) const; // LBA→MSF conversion
|
||||
|
||||
bool rawfile = false; // RAW flag
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ void SCSIHD::Open()
|
|||
|
||||
// Sector size (default 512 bytes) and number of blocks
|
||||
SetSectorSizeInBytes(GetConfiguredSectorSize() ? GetConfiguredSectorSize() : 512);
|
||||
SetBlockCount((uint32_t)(size >> GetSectorSizeShiftCount()));
|
||||
SetBlockCount(static_cast<uint32_t>(size >> GetSectorSizeShiftCount()));
|
||||
|
||||
FinalizeSetup(0);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ vector<byte> SCSIHD::InquiryInternal() const
|
|||
return HandleInquiry(device_type::DIRECT_ACCESS, scsi_level, IsRemovable());
|
||||
}
|
||||
|
||||
void SCSIHD::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<BYTE>& buf, int length) const
|
||||
void SCSIHD::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<uint8_t>& buf, int length) const
|
||||
{
|
||||
scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount());
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
// Commands
|
||||
vector<byte> InquiryInternal() const override;
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<BYTE>&, int) const override;
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<uint8_t>&, int) const override;
|
||||
|
||||
void AddFormatPage(map<int, vector<byte>>&, bool) const override;
|
||||
void AddVendorPage(map<int, vector<byte>>&, int, bool) const override;
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
using namespace ras_util;
|
||||
using namespace scsi_command_util;
|
||||
|
||||
const unordered_set<uint32_t> SCSIHD_NEC::sector_sizes = { 512 };
|
||||
|
||||
void SCSIHD_NEC::Open()
|
||||
{
|
||||
assert(!IsReady());
|
||||
|
@ -34,7 +32,7 @@ void SCSIHD_NEC::Open()
|
|||
array<char, 512> root_sector;
|
||||
ifstream in(GetFilename(), ios::binary);
|
||||
in.read(root_sector.data(), root_sector.size());
|
||||
if (!in.good() || size < (off_t)root_sector.size()) {
|
||||
if (!in.good() || size < static_cast<off_t>(root_sector.size())) {
|
||||
throw io_exception("Can't read NEC hard disk file root sector");
|
||||
}
|
||||
|
||||
|
@ -42,9 +40,9 @@ void SCSIHD_NEC::Open()
|
|||
size = (size / 512) * 512;
|
||||
|
||||
// Determine parameters by extension
|
||||
const auto [image_size, sector_size] = SetParameters(root_sector, (int)size);
|
||||
const auto [image_size, sector_size] = SetParameters(root_sector, static_cast<int>(size));
|
||||
|
||||
SetSectorSizeShiftCount((uint32_t)size);
|
||||
SetSectorSizeShiftCount(static_cast<uint32_t>(size));
|
||||
|
||||
SetBlockCount(image_size >> GetSectorSizeShiftCount());
|
||||
|
||||
|
@ -53,7 +51,7 @@ void SCSIHD_NEC::Open()
|
|||
|
||||
pair<int, int> SCSIHD_NEC::SetParameters(const array<char, 512>& data, int size)
|
||||
{
|
||||
array<BYTE, 512> root_sector = {};
|
||||
array<uint8_t, 512> root_sector = {};
|
||||
memcpy(root_sector.data(), data.data(), root_sector.size());
|
||||
|
||||
int image_size;
|
||||
|
@ -88,7 +86,7 @@ pair<int, int> SCSIHD_NEC::SetParameters(const array<char, 512>& data, int size)
|
|||
heads = GetInt16LittleEndian(&root_sector[0x118]);
|
||||
sectors = GetInt16LittleEndian(&root_sector[0x11a]);
|
||||
sector_size = GetInt16LittleEndian(&root_sector[0x11c]);
|
||||
image_size = (int)((off_t)cylinders * heads * sectors * sector_size);
|
||||
image_size = static_cast<int>(static_cast<off_t>(cylinders * heads * sectors * sector_size));
|
||||
}
|
||||
else {
|
||||
throw io_exception("Invalid NEC image file format");
|
||||
|
@ -170,12 +168,12 @@ void SCSIHD_NEC::AddDrivePage(map<int, vector<byte>>& pages, bool changeable) co
|
|||
pages[4] = buf;
|
||||
}
|
||||
|
||||
int SCSIHD_NEC::GetInt16LittleEndian(const BYTE *buf)
|
||||
int SCSIHD_NEC::GetInt16LittleEndian(const uint8_t *buf)
|
||||
{
|
||||
return ((int)buf[1] << 8) | buf[0];
|
||||
return (static_cast<int>(buf[1]) << 8) | buf[0];
|
||||
}
|
||||
|
||||
int SCSIHD_NEC::GetInt32LittleEndian(const BYTE *buf)
|
||||
int SCSIHD_NEC::GetInt32LittleEndian(const uint8_t *buf)
|
||||
{
|
||||
return ((int)buf[3] << 24) | ((int)buf[2] << 16) | ((int)buf[1] << 8) | buf[0];
|
||||
return (static_cast<int>(buf[3]) << 24) | (static_cast<int>(buf[2]) << 16) | (static_cast<int>(buf[1]) << 8) | buf[0];
|
||||
}
|
||||
|
|
|
@ -49,10 +49,10 @@ private:
|
|||
|
||||
pair<int, int> SetParameters(const array<char, 512>&, int);
|
||||
|
||||
static int GetInt16LittleEndian(const BYTE *);
|
||||
static int GetInt32LittleEndian(const BYTE *);
|
||||
static int GetInt16LittleEndian(const uint8_t *);
|
||||
static int GetInt32LittleEndian(const uint8_t *);
|
||||
|
||||
static const unordered_set<uint32_t> sector_sizes;
|
||||
static inline const unordered_set<uint32_t> sector_sizes = { 512 };
|
||||
|
||||
// Image file offset
|
||||
off_t image_offset = 0;
|
||||
|
|
|
@ -89,7 +89,7 @@ void SCSIMO::AddOptionPage(map<int, vector<byte>>& pages, bool) const
|
|||
// Do not report update blocks
|
||||
}
|
||||
|
||||
void SCSIMO::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<BYTE>& buf, int length) const
|
||||
void SCSIMO::ModeSelect(scsi_command cmd, const vector<int>& cdb, const vector<uint8_t>& buf, int length) const
|
||||
{
|
||||
scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount());
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ void SCSIMO::AddVendorPage(map<int, vector<byte>>& pages, int page, bool changea
|
|||
|
||||
buf[2] = (byte)0; // format mode
|
||||
buf[3] = (byte)0; // type of format
|
||||
SetInt32(buf, 4, (uint32_t)blocks);
|
||||
SetInt32(buf, 4, static_cast<uint32_t>(blocks));
|
||||
SetInt16(buf, 8, spare);
|
||||
SetInt16(buf, 10, bands);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
void Open() override;
|
||||
|
||||
vector<byte> InquiryInternal() const override;
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<BYTE>&, int) const override;
|
||||
void ModeSelect(scsi_defs::scsi_command, const vector<int>&, const vector<uint8_t>&, int) const override;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
using namespace std;
|
||||
using namespace filesystem;
|
||||
|
||||
unordered_map<string, id_set> StorageDevice::reserved_files;
|
||||
|
||||
StorageDevice::StorageDevice(PbDeviceType type, int lun) : ModePageDevice(type, lun)
|
||||
{
|
||||
SupportsFile(true);
|
||||
|
|
|
@ -67,5 +67,5 @@ private:
|
|||
bool medium_changed = false;
|
||||
|
||||
// The list of image files in use and the IDs and LUNs using these files
|
||||
static unordered_map<string, id_set> reserved_files;
|
||||
static inline unordered_map<string, id_set> reserved_files;
|
||||
};
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "hal/sbc_version.h"
|
||||
#include "hal/systimer.h"
|
||||
#include "log.h"
|
||||
#include "os.h"
|
||||
#include <array>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -523,7 +522,7 @@ uint32_t GPIOBUS::GetPinRaw(uint32_t raw_data, board_type::pi_physical_pin_e pin
|
|||
// Receive command handshake
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::CommandHandShake(BYTE *buf)
|
||||
int GPIOBUS::CommandHandShake(uint8_t *buf)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
// Only works in TARGET mode
|
||||
|
@ -646,7 +645,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf)
|
|||
// Data reception handshake
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::ReceiveHandShake(BYTE *buf, int count)
|
||||
int GPIOBUS::ReceiveHandShake(uint8_t *buf, int count)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
|
||||
|
@ -752,7 +751,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count)
|
|||
// Data transmission handshake
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::SendHandShake(BYTE *buf, int count, int delay_after_bytes)
|
||||
int GPIOBUS::SendHandShake(uint8_t *buf, int count, int delay_after_bytes)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
|
||||
|
@ -1097,7 +1096,7 @@ BUS::phase_t GPIOBUS::GetPhaseRaw(uint32_t raw_data)
|
|||
// Get the number of bytes for a command
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int GPIOBUS::GetCommandByteCount(BYTE opcode)
|
||||
int GPIOBUS::GetCommandByteCount(uint8_t opcode)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
|
||||
|
@ -1105,7 +1104,7 @@ int GPIOBUS::GetCommandByteCount(BYTE opcode)
|
|||
return 16;
|
||||
} else if (opcode == 0xA0) {
|
||||
return 12;
|
||||
} else if (opcode == 0x05 || (opcode >= 0x20 && opcode <= 0x7D)) {
|
||||
} else if (opcode >= 0x20 && opcode <= 0x7D) {
|
||||
return 10;
|
||||
} else {
|
||||
return 6;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "config.h"
|
||||
#include "hal/board_type.h"
|
||||
#include "scsi.h"
|
||||
#include "bus.h"
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
@ -50,7 +51,7 @@
|
|||
#define GPIO_FUNCTION_TRACE
|
||||
#endif
|
||||
|
||||
using namespace std; // NOSONAR Not relevant for rascsi
|
||||
using namespace std;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -340,17 +341,17 @@ class GPIOBUS : public BUS
|
|||
return board;
|
||||
}
|
||||
|
||||
int CommandHandShake(BYTE *buf) override;
|
||||
int CommandHandShake(uint8_t *buf) override;
|
||||
// Command receive handshake
|
||||
int ReceiveHandShake(BYTE *buf, int count) override;
|
||||
int ReceiveHandShake(uint8_t *buf, int count) override;
|
||||
// Data receive handshake
|
||||
int SendHandShake(BYTE *buf, int count, int delay_after_bytes) override;
|
||||
int SendHandShake(uint8_t *buf, int count, int delay_after_bytes) override;
|
||||
// Data transmission handshake
|
||||
|
||||
// Get the phase based on raw data
|
||||
static BUS::phase_t GetPhaseRaw(uint32_t raw_data);
|
||||
|
||||
static int GetCommandByteCount(BYTE opcode);
|
||||
static int GetCommandByteCount(uint8_t opcode);
|
||||
|
||||
const string GetConnectDesc();
|
||||
|
||||
|
|
|
@ -321,22 +321,23 @@ void GPIOBUS_Allwinner::Cleanup()
|
|||
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
|
||||
}
|
||||
|
||||
BYTE GPIOBUS_Allwinner::GetDAT()
|
||||
|
||||
uint8_t GPIOBUS_Allwinner::GetDAT()
|
||||
{
|
||||
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
|
||||
// LOGDEBUG("0:%02X 1:%02X 2:%02X 3:%02X 4:%02X 5:%02X 6:%02X 7:%02X P:%02X", GetSignal(PIN_DT0),
|
||||
// GetSignal(PIN_DT1),GetSignal(PIN_DT2),GetSignal(PIN_DT3),GetSignal(PIN_DT4),GetSignal(PIN_DT5),GetSignal(PIN_DT6),GetSignal(PIN_DT7),GetSignal(PIN_DP));
|
||||
// TODO: This is crazy inefficient...
|
||||
DWORD data = ((GetSignal(board->pin_dt0) ? 0x01 : 0x00) << 0) | ((GetSignal(board->pin_dt1) ? 0x01 : 0x00) << 1) |
|
||||
uint8_t data = ((GetSignal(board->pin_dt0) ? 0x01 : 0x00) << 0) | ((GetSignal(board->pin_dt1) ? 0x01 : 0x00) << 1) |
|
||||
((GetSignal(board->pin_dt2) ? 0x01 : 0x00) << 2) | ((GetSignal(board->pin_dt3) ? 0x01 : 0x00) << 3) |
|
||||
((GetSignal(board->pin_dt4) ? 0x01 : 0x00) << 0) | ((GetSignal(board->pin_dt5) ? 0x01 : 0x00) << 5) |
|
||||
((GetSignal(board->pin_dt6) ? 0x01 : 0x00) << 6) | ((GetSignal(board->pin_dt7) ? 0x01 : 0x00) << 7);
|
||||
|
||||
return (BYTE)data;
|
||||
return (uint8_t)data;
|
||||
// return 0;
|
||||
}
|
||||
|
||||
void GPIOBUS_Allwinner::SetDAT(BYTE dat)
|
||||
void GPIOBUS_Allwinner::SetDAT(uint8_t dat)
|
||||
{
|
||||
// TODO: This is crazy inefficient...
|
||||
PinSetSignal(board->pin_dt0, (dat & (1 << 0)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
|
||||
|
@ -522,7 +523,7 @@ void GPIOBUS_Allwinner::PinSetSignal(board_type::pi_physical_pin_e pin, board_ty
|
|||
// LOGERROR("%s not implemented!!", __PRETTY_FUNCTION__)
|
||||
}
|
||||
|
||||
void GPIOBUS_Allwinner::DrvConfig(DWORD drive)
|
||||
void GPIOBUS_Allwinner::DrvConfig(uint32_t drive)
|
||||
{
|
||||
(void)drive;
|
||||
LOGERROR("%s not implemented!!", __PRETTY_FUNCTION__)
|
||||
|
|
|
@ -43,9 +43,9 @@ class GPIOBUS_Allwinner : public GPIOBUS
|
|||
//---------------------------------------------------------------------------
|
||||
uint32_t Acquire() override;
|
||||
|
||||
BYTE GetDAT() override;
|
||||
uint8_t GetDAT() override;
|
||||
// Get DAT signal
|
||||
void SetDAT(BYTE dat) override;
|
||||
void SetDAT(uint8_t dat) override;
|
||||
// Set DAT signal
|
||||
// TODO: Restore these back to protected
|
||||
// protected:
|
||||
|
@ -76,7 +76,7 @@ class GPIOBUS_Allwinner : public GPIOBUS
|
|||
// GPIO pin pull up/down resistor setting
|
||||
void PinSetSignal(board_type::pi_physical_pin_e pin, board_type::gpio_high_low_e ast) override;
|
||||
// Set GPIO output signal
|
||||
void DrvConfig(DWORD drive) override;
|
||||
void DrvConfig(uint32_t drive) override;
|
||||
// Set GPIO drive strength
|
||||
|
||||
// Map the physical pin number to the logical GPIO number
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "hal/gpiobus.h"
|
||||
#include "hal/systimer.h"
|
||||
#include "log.h"
|
||||
#include "os.h"
|
||||
#include <map>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
|
@ -53,7 +52,7 @@ static uint32_t get_dt_ranges(const char *filename, uint32_t offset)
|
|||
uint32_t address = ~0;
|
||||
if (FILE *fp = fopen(filename, "rb"); fp) {
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
if (array<BYTE, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
|
||||
if (array<uint8_t, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
|
||||
address = (int)buf[0] << 24 | (int)buf[1] << 16 | (int)buf[2] << 8 | (int)buf[3] << 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
@ -395,7 +394,7 @@ void GPIOBUS_Raspberry::Cleanup()
|
|||
// Get data signals
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BYTE GPIOBUS_Raspberry::GetDAT()
|
||||
uint8_t GPIOBUS_Raspberry::GetDAT()
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
uint32_t data = Acquire();
|
||||
|
@ -407,7 +406,7 @@ BYTE GPIOBUS_Raspberry::GetDAT()
|
|||
((data >> (phys_to_gpio_map.at(board->pin_dt5) - 5)) & (1 << 5)) |
|
||||
((data >> (phys_to_gpio_map.at(board->pin_dt6) - 6)) & (1 << 6)) |
|
||||
((data >> (phys_to_gpio_map.at(board->pin_dt7) - 7)) & (1 << 7));
|
||||
return (BYTE)data;
|
||||
return (uint8_t)data;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -415,7 +414,7 @@ BYTE GPIOBUS_Raspberry::GetDAT()
|
|||
// Set data signals
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void GPIOBUS_Raspberry::SetDAT(BYTE dat)
|
||||
void GPIOBUS_Raspberry::SetDAT(uint8_t dat)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
// Write to port
|
||||
|
|
|
@ -46,9 +46,9 @@ class GPIOBUS_Raspberry final : public GPIOBUS
|
|||
//---------------------------------------------------------------------------
|
||||
uint32_t Acquire() override;
|
||||
|
||||
BYTE GetDAT() override;
|
||||
uint8_t GetDAT() override;
|
||||
// Get DAT signal
|
||||
void SetDAT(BYTE dat) override;
|
||||
void SetDAT(uint8_t dat) override;
|
||||
// Set DAT signal
|
||||
// TODO: Restore this back to private
|
||||
// private:
|
||||
|
|
|
@ -161,13 +161,13 @@ bool SBC_Version::IsBananaPi()
|
|||
|
||||
// The following functions are only used on the Raspberry Pi
|
||||
// (imported from bcm_host.c)
|
||||
DWORD SBC_Version::GetDeviceTreeRanges(const char *filename, DWORD offset)
|
||||
uint32_t SBC_Version::GetDeviceTreeRanges(const char *filename, uint32_t offset)
|
||||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
DWORD address = ~0;
|
||||
uint32_t address = ~0;
|
||||
if (FILE *fp = fopen(filename, "rb"); fp) {
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
if (std::array<BYTE, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
|
||||
if (std::array<uint8_t, 4> buf; fread(buf.data(), 1, buf.size(), fp) == buf.size()) {
|
||||
address = (int)buf[0] << 24 | (int)buf[1] << 16 | (int)buf[2] << 8 | (int)buf[3] << 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
@ -176,25 +176,25 @@ DWORD SBC_Version::GetDeviceTreeRanges(const char *filename, DWORD offset)
|
|||
}
|
||||
|
||||
#if defined __linux__
|
||||
DWORD SBC_Version::GetPeripheralAddress(void)
|
||||
uint32_t SBC_Version::GetPeripheralAddress(void)
|
||||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
DWORD address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 4);
|
||||
uint32_t address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 4);
|
||||
if (address == 0) {
|
||||
address = GetDeviceTreeRanges("/proc/device-tree/soc/ranges", 8);
|
||||
}
|
||||
address = (address == (DWORD)~0) ? 0x20000000 : address;
|
||||
address = (address == (uint32_t)~0) ? 0x20000000 : address;
|
||||
|
||||
LOGDEBUG("Peripheral address : 0x%8x\n", address)
|
||||
|
||||
return address;
|
||||
}
|
||||
#elif defined __NetBSD__
|
||||
DWORD SBC_Version::GetPeripheralAddress(void)
|
||||
uint32_t SBC_Version::GetPeripheralAddress(void)
|
||||
{
|
||||
char buf[1024];
|
||||
size_t len = sizeof(buf);
|
||||
DWORD address;
|
||||
uint32_t address;
|
||||
|
||||
if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) {
|
||||
// Failed to get CPU model || Not BCM2835
|
||||
|
@ -208,7 +208,7 @@ DWORD SBC_Version::GetPeripheralAddress(void)
|
|||
return address;
|
||||
}
|
||||
#else
|
||||
DWORD SBC_Version::GetPeripheralAddress(void)
|
||||
uint32_t SBC_Version::GetPeripheralAddress(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
#include "os.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
@ -47,7 +47,7 @@ class SBC_Version
|
|||
|
||||
static const std::string *GetString();
|
||||
|
||||
static DWORD GetPeripheralAddress();
|
||||
static uint32_t GetPeripheralAddress();
|
||||
|
||||
private:
|
||||
static sbc_version_type m_sbc_version;
|
||||
|
@ -66,5 +66,5 @@ class SBC_Version
|
|||
|
||||
static const std::string m_device_tree_model_path;
|
||||
|
||||
static DWORD GetDeviceTreeRanges(const char *filename, DWORD offset);
|
||||
};
|
||||
static uint32_t GetDeviceTreeRanges(const char *filename, uint32_t offset);
|
||||
};
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "hal/gpiobus.h"
|
||||
#include "hal/sbc_version.h"
|
||||
#include "os.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <sys/mman.h>
|
||||
|
||||
#include "hal/gpiobus.h"
|
||||
#include "os.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
@ -99,14 +98,14 @@ void SysTimer_AllWinner::disable_hs_timer()
|
|||
sysbus_regs->bus_soft_rst_reg0)
|
||||
}
|
||||
|
||||
DWORD SysTimer_AllWinner::GetTimerLow()
|
||||
uint32_t SysTimer_AllWinner::GetTimerLow()
|
||||
{
|
||||
// RaSCSI expects the timer to count UP, but the Allwinner HS timer counts
|
||||
// down. So, we subtract the current timer value from UINT32_MAX
|
||||
return UINT32_MAX - (hsitimer_regs->hs_tmr_curnt_lo_reg / 200);
|
||||
}
|
||||
|
||||
DWORD SysTimer_AllWinner::GetTimerHigh()
|
||||
uint32_t SysTimer_AllWinner::GetTimerHigh()
|
||||
{
|
||||
return (uint32_t)0;
|
||||
}
|
||||
|
@ -116,7 +115,7 @@ DWORD SysTimer_AllWinner::GetTimerHigh()
|
|||
// Sleep in nanoseconds
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SysTimer_AllWinner::SleepNsec(DWORD nsec)
|
||||
void SysTimer_AllWinner::SleepNsec(uint32_t nsec)
|
||||
{
|
||||
// If time is less than one HS timer clock tick, don't do anything
|
||||
if (nsec < 20) {
|
||||
|
@ -127,7 +126,7 @@ void SysTimer_AllWinner::SleepNsec(DWORD nsec)
|
|||
// one clock tick every 5 ns.
|
||||
auto clockticks = (uint32_t)std::ceil(nsec / 5);
|
||||
|
||||
DWORD enter_time = hsitimer_regs->hs_tmr_curnt_lo_reg;
|
||||
uint32_t enter_time = hsitimer_regs->hs_tmr_curnt_lo_reg;
|
||||
|
||||
LOGTRACE("%s entertime: %08X ns: %d clockticks: %d", __PRETTY_FUNCTION__, enter_time, nsec, clockticks)
|
||||
while ((enter_time - hsitimer_regs->hs_tmr_curnt_lo_reg) < clockticks)
|
||||
|
@ -141,7 +140,7 @@ void SysTimer_AllWinner::SleepNsec(DWORD nsec)
|
|||
// Sleep in microseconds
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SysTimer_AllWinner::SleepUsec(DWORD usec)
|
||||
void SysTimer_AllWinner::SleepUsec(uint32_t usec)
|
||||
{
|
||||
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||
|
||||
|
@ -150,7 +149,7 @@ void SysTimer_AllWinner::SleepUsec(DWORD usec)
|
|||
return;
|
||||
}
|
||||
|
||||
DWORD enter_time = GetTimerLow();
|
||||
uint32_t enter_time = GetTimerLow();
|
||||
while ((GetTimerLow() - enter_time) < usec)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "hal/gpiobus.h"
|
||||
#include "hal/sbc_version.h"
|
||||
#include "os.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
@ -69,8 +68,8 @@ void SysTimer_Raspberry::Init()
|
|||
std::array<uint32_t, 32> maxclock = {32, 0, 0x00030004, 8, 0, 4, 0, 0};
|
||||
|
||||
// Save the base address
|
||||
systaddr = (DWORD *)map + SYST_OFFSET / sizeof(DWORD);
|
||||
armtaddr = (DWORD *)map + ARMT_OFFSET / sizeof(DWORD);
|
||||
systaddr = (uint32_t *)map + SYST_OFFSET / sizeof(uint32_t);
|
||||
armtaddr = (uint32_t *)map + ARMT_OFFSET / sizeof(uint32_t);
|
||||
|
||||
// Change the ARM timer to free run mode
|
||||
armtaddr[ARMT_CTRL] = 0x00000282;
|
||||
|
@ -88,7 +87,7 @@ void SysTimer_Raspberry::Init()
|
|||
// Get system timer low byte
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
DWORD SysTimer_Raspberry::GetTimerLow()
|
||||
uint32_t SysTimer_Raspberry::GetTimerLow()
|
||||
{
|
||||
return systaddr[SYST_CLO];
|
||||
}
|
||||
|
@ -98,7 +97,7 @@ DWORD SysTimer_Raspberry::GetTimerLow()
|
|||
// Get system timer high byte
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
DWORD SysTimer_Raspberry::GetTimerHigh()
|
||||
uint32_t SysTimer_Raspberry::GetTimerHigh()
|
||||
{
|
||||
return systaddr[SYST_CHI];
|
||||
}
|
||||
|
@ -108,7 +107,7 @@ DWORD SysTimer_Raspberry::GetTimerHigh()
|
|||
// Sleep in nanoseconds
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SysTimer_Raspberry::SleepNsec(DWORD nsec)
|
||||
void SysTimer_Raspberry::SleepNsec(uint32_t nsec)
|
||||
{
|
||||
// If time is 0, don't do anything
|
||||
if (nsec == 0) {
|
||||
|
@ -116,7 +115,7 @@ void SysTimer_Raspberry::SleepNsec(DWORD nsec)
|
|||
}
|
||||
|
||||
// Calculate the timer difference
|
||||
DWORD diff = corefreq * nsec / 1000;
|
||||
uint32_t diff = corefreq * nsec / 1000;
|
||||
|
||||
// Return if the difference in time is too small
|
||||
if (diff == 0) {
|
||||
|
@ -124,7 +123,7 @@ void SysTimer_Raspberry::SleepNsec(DWORD nsec)
|
|||
}
|
||||
|
||||
// Start
|
||||
DWORD start = armtaddr[ARMT_FREERUN];
|
||||
uint32_t start = armtaddr[ARMT_FREERUN];
|
||||
|
||||
// Loop until timer has elapsed
|
||||
while ((armtaddr[ARMT_FREERUN] - start) < diff)
|
||||
|
@ -136,14 +135,14 @@ void SysTimer_Raspberry::SleepNsec(DWORD nsec)
|
|||
// Sleep in microseconds
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void SysTimer_Raspberry::SleepUsec(DWORD usec)
|
||||
void SysTimer_Raspberry::SleepUsec(uint32_t usec)
|
||||
{
|
||||
// If time is 0, don't do anything
|
||||
if (usec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD now = GetTimerLow();
|
||||
uint32_t now = GetTimerLow();
|
||||
while ((GetTimerLow() - now) < usec)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// [ SCSI Bus Monitor ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "os.h"
|
||||
|
||||
#include "scsi.h"
|
||||
#include "data_sample.h"
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ inline bool GetCd(const data_capture *sample) { return bus->GetPinRaw(sample->d
|
|||
inline bool GetIo(const data_capture *sample) { return bus->GetPinRaw(sample->data, bus->GetBoard()->pin_io); }
|
||||
inline bool GetReq(const data_capture *sample) { return bus->GetPinRaw(sample->data, bus->GetBoard()->pin_req); }
|
||||
inline bool GetDp(const data_capture *sample) { return bus->GetPinRaw(sample->data, bus->GetBoard()->pin_dp); }
|
||||
inline BYTE GetData(const data_capture *sample)
|
||||
inline uint8_t GetData(const data_capture *sample)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
result |= (bus->GetPinRaw(sample->data, bus->GetBoard()->pin_dt0) != 0) ? (1 << 0) : 0;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "os.h"
|
||||
#include "log.h"
|
||||
#include "sm_reports.h"
|
||||
#include "rascsi_version.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include "log.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
@ -52,17 +51,17 @@ const int PIN_PHASE = 0;
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
// TODO: prev_value can be smaller. Just making up a big number for now
|
||||
static BYTE prev_value[128] = {0xFF};
|
||||
static uint8_t prev_value[128] = {0xFF};
|
||||
|
||||
extern double ns_per_loop;
|
||||
|
||||
static BYTE get_pin_value(uint32_t data, board_type::pi_physical_pin_e pin)
|
||||
static uint8_t get_pin_value(uint32_t data, board_type::pi_physical_pin_e pin)
|
||||
{
|
||||
return bus->GetPinRaw(data, pin);
|
||||
// return (data >> pin) & 1;
|
||||
}
|
||||
|
||||
static BYTE get_data_field(uint32_t data)
|
||||
static uint8_t get_data_field(uint32_t data)
|
||||
{
|
||||
// TODO: This is a quick hack to re-use the GetData() function from data_sample.h
|
||||
const struct data_capture dummy_data_capture =
|
||||
|
@ -71,21 +70,20 @@ static BYTE get_data_field(uint32_t data)
|
|||
.timestamp = 0,
|
||||
};
|
||||
return GetData(&dummy_data_capture);
|
||||
|
||||
}
|
||||
|
||||
static void vcd_output_if_changed_phase(ofstream& fp, uint32_t data, int pin, char symbol)
|
||||
{
|
||||
const BUS::phase_t new_value = GPIOBUS::GetPhaseRaw(data);
|
||||
if (prev_value[pin] != (int)new_value) {
|
||||
prev_value[pin] = (int)new_value;
|
||||
if (prev_value[pin] != static_cast<int>(new_value)) {
|
||||
prev_value[pin] = static_cast<int>(new_value);
|
||||
fp << "s" << GPIOBUS::GetPhaseStrRaw(new_value) << " " << symbol << endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void vcd_output_if_changed_bool(ofstream& fp, uint32_t data, board_type::pi_physical_pin_e pin, char symbol)
|
||||
{
|
||||
const BYTE new_value = get_pin_value(data, pin);
|
||||
const uint8_t new_value = get_pin_value(data, pin);
|
||||
if (prev_value[(int)pin] != new_value) {
|
||||
prev_value[(int)pin] = new_value;
|
||||
fp << new_value << symbol << endl;
|
||||
|
@ -94,7 +92,7 @@ static void vcd_output_if_changed_bool(ofstream& fp, uint32_t data, board_type::
|
|||
|
||||
static void vcd_output_if_changed_byte(ofstream& fp, uint32_t data, int pin, char symbol)
|
||||
{
|
||||
const BYTE new_value = get_data_field(data);
|
||||
const uint8_t new_value = get_data_field(data);
|
||||
if (prev_value[pin] != new_value) {
|
||||
prev_value[pin] = new_value;
|
||||
fp << "b"
|
||||
|
|
17
cpp/os.h
17
cpp/os.h
|
@ -1,17 +0,0 @@
|
|||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI Reloaded
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
// Copyright (C) 2020 akuker
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using BYTE = unsigned char;
|
||||
using DWORD = uint32_t;
|
|
@ -28,7 +28,7 @@ void ProtobufSerializer::SerializeMessage(int fd, const google::protobuf::Messag
|
|||
message.SerializeToString(&data);
|
||||
|
||||
// Write the size of the protobuf data as a header
|
||||
auto size = (int32_t)data.length();
|
||||
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");
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ void ProtobufSerializer::DeserializeMessage(int fd, google::protobuf::Message& m
|
|||
throw io_exception("Invalid protobuf message header");
|
||||
}
|
||||
|
||||
const int size = ((int)header_buf[3] << 24) + ((int)header_buf[2] << 16)
|
||||
+ ((int)header_buf[1] << 8) + (int)header_buf[0];
|
||||
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");
|
||||
}
|
||||
|
|
188
cpp/rascsi.cpp
188
cpp/rascsi.cpp
|
@ -40,7 +40,7 @@
|
|||
#include <fstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
|
||||
using namespace std;
|
||||
using namespace spdlog;
|
||||
|
@ -73,6 +73,9 @@ shared_ptr<RascsiResponse> rascsi_response;
|
|||
shared_ptr<RascsiExecutor> executor;
|
||||
const ProtobufSerializer serializer;
|
||||
|
||||
using optarg_value_type = std::pair<int,string>;
|
||||
using optarg_queue_type = std::deque<optarg_value_type>;
|
||||
|
||||
void Banner(int argc, char* argv[])
|
||||
{
|
||||
cout << Banner("Reloaded");
|
||||
|
@ -206,40 +209,32 @@ bool ProcessId(const string& id_spec, int& id, int& unit)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ParseArgument(int argc, char* argv[], int& port)
|
||||
bool ParseArgument(int argc, char* argv[], int& port, optarg_queue_type& post_process)
|
||||
{
|
||||
PbCommand command;
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
PbDeviceType type = UNDEFINED;
|
||||
int block_size = 0;
|
||||
string name;
|
||||
string log_level;
|
||||
|
||||
const char *locale = setlocale(LC_MESSAGES, "");
|
||||
if (locale == nullptr || !strcmp(locale, "C")) {
|
||||
locale = "en";
|
||||
}
|
||||
|
||||
opterr = 1;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "-Iib:d:n:p:r:t:z:D:F:L:P:R:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "-Iib:d:n:p:r:t:z:D:F:L:P:R:C:v")) != -1) {
|
||||
switch (opt) {
|
||||
// The two options below are kind of a compound option with two letters
|
||||
// The following options can not be processed until AFTER
|
||||
// the 'bus' object is created and configured
|
||||
case 'i':
|
||||
case 'I':
|
||||
id = -1;
|
||||
unit = -1;
|
||||
continue;
|
||||
|
||||
case 'd':
|
||||
case 'D': {
|
||||
if (!ProcessId(optarg, id, unit)) {
|
||||
return false;
|
||||
}
|
||||
case 'D':
|
||||
case 'R':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'F':
|
||||
case 'z':
|
||||
{
|
||||
string optarg_str = (optarg == nullptr) ? "" : string(optarg);
|
||||
post_process.push_back(optarg_value_type(opt,optarg_str));
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'b': {
|
||||
if (!GetAsInt(optarg, block_size)) {
|
||||
cerr << "Invalid block size " << optarg << endl;
|
||||
|
@ -248,33 +243,8 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
continue;
|
||||
}
|
||||
|
||||
case 'z':
|
||||
locale = optarg;
|
||||
continue;
|
||||
|
||||
case 'F': {
|
||||
if (const string result = rascsi_image.SetDefaultFolder(optarg); !result.empty()) {
|
||||
cerr << result << endl;
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
log_level = optarg;
|
||||
continue;
|
||||
|
||||
case 'R':
|
||||
int depth;
|
||||
if (!GetAsInt(optarg, depth) || depth < 0) {
|
||||
cerr << "Invalid image file scan depth " << optarg << endl;
|
||||
return false;
|
||||
}
|
||||
rascsi_image.SetDepth(depth);
|
||||
continue;
|
||||
|
||||
case 'n':
|
||||
name = optarg;
|
||||
current_log_level = optarg;
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
|
@ -289,9 +259,91 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
return false;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'v':
|
||||
cout << rascsi_get_version_string() << endl;
|
||||
exit(0);
|
||||
|
||||
case 1:
|
||||
{
|
||||
// Encountered filename
|
||||
string optarg_str = (optarg == nullptr) ? "" : string(optarg);
|
||||
post_process.push_back(optarg_value_type(opt,optarg_str));
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (optopt) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool CreateInitialDevices(optarg_queue_type& optarg_queue){
|
||||
PbCommand command;
|
||||
int id = -1;
|
||||
int unit = -1;
|
||||
PbDeviceType type = UNDEFINED;
|
||||
int block_size = 0;
|
||||
string name;
|
||||
string log_level;
|
||||
|
||||
const char *locale = setlocale(LC_MESSAGES, "");
|
||||
if (locale == nullptr || !strcmp(locale, "C")) {
|
||||
locale = "en";
|
||||
}
|
||||
|
||||
|
||||
opterr = 1;
|
||||
for(auto current_arg : optarg_queue){
|
||||
switch (current_arg.first) {
|
||||
// The two options below are kind of a compound option with two letters
|
||||
case 'i':
|
||||
case 'I':
|
||||
id = -1;
|
||||
unit = -1;
|
||||
continue;
|
||||
|
||||
case 'd':
|
||||
case 'D': {
|
||||
if (!ProcessId(current_arg.second, id, unit)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'z':
|
||||
locale = current_arg.second.c_str();
|
||||
continue;
|
||||
|
||||
case 'F': {
|
||||
if (const string result = rascsi_image.SetDefaultFolder(current_arg.second); !result.empty()) {
|
||||
cerr << result << endl;
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'R':
|
||||
int depth;
|
||||
if (!GetAsInt(current_arg.second, depth) || depth < 0) {
|
||||
cerr << "Invalid image file scan depth " << current_arg.second << endl;
|
||||
return false;
|
||||
}
|
||||
rascsi_image.SetDepth(depth);
|
||||
continue;
|
||||
|
||||
case 'n':
|
||||
name = current_arg.second;
|
||||
continue;
|
||||
|
||||
case 'r': {
|
||||
string error = executor->SetReservedIds(optarg);
|
||||
string error = executor->SetReservedIds(current_arg.second);
|
||||
if (!error.empty()) {
|
||||
cerr << error << endl;
|
||||
return false;
|
||||
|
@ -300,10 +352,10 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
continue;
|
||||
|
||||
case 't': {
|
||||
string t = optarg;
|
||||
string t = current_arg.second;
|
||||
transform(t.begin(), t.end(), t.begin(), ::toupper);
|
||||
if (!PbDeviceType_Parse(t, &type)) {
|
||||
cerr << "Illegal device type '" << optarg << "'" << endl;
|
||||
cerr << "Illegal device type '" << current_arg.second << "'" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -312,13 +364,6 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
case 1:
|
||||
// Encountered filename
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (optopt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up the device data
|
||||
|
@ -328,7 +373,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
device->set_type(type);
|
||||
device->set_block_size(block_size);
|
||||
|
||||
ParseParameters(*device, optarg);
|
||||
ParseParameters(*device, current_arg.second);
|
||||
|
||||
if (size_t separator_pos = name.find(COMPONENT_SEPARATOR); separator_pos != string::npos) {
|
||||
device->set_vendor(name.substr(0, separator_pos));
|
||||
|
@ -352,10 +397,6 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
|||
name = "";
|
||||
}
|
||||
|
||||
if (!log_level.empty() && executor->SetLogLevel(log_level)) {
|
||||
current_log_level = log_level;
|
||||
}
|
||||
|
||||
// Attach all specified devices
|
||||
command.set_operation(ATTACH);
|
||||
|
||||
|
@ -524,6 +565,7 @@ static bool ExecuteCommand(const CommandContext& context, PbCommand& command)
|
|||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
optarg_queue_type optarg_queue;
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
|
||||
|
@ -532,15 +574,12 @@ int main(int argc, char* argv[])
|
|||
// Output the Banner
|
||||
Banner(argc, argv);
|
||||
|
||||
// ParseArgument() requires the bus to have been initialized first, which requires the root user.
|
||||
// The -v option should be available for any user, which requires special handling.
|
||||
for (int i = 1 ; i < argc; i++) {
|
||||
if (!strcasecmp(argv[i], "-v")) {
|
||||
cout << rascsi_get_version_string() << endl;
|
||||
return 0;
|
||||
}
|
||||
int port = DEFAULT_PORT;
|
||||
if (!ParseArgument(argc, argv, port, optarg_queue)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note that current_log_level may have been modified by ParseArgument()
|
||||
executor->SetLogLevel(current_log_level);
|
||||
|
||||
// Create a thread-safe stdout logger to process the log messages
|
||||
|
@ -550,12 +589,13 @@ int main(int argc, char* argv[])
|
|||
return EPERM;
|
||||
}
|
||||
|
||||
int port = DEFAULT_PORT;
|
||||
if (!service.Init(&ExecuteCommand, port)) {
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
if (!ParseArgument(argc, argv, port)) {
|
||||
// We need to wait to create the devices until after the bus/controller/etc
|
||||
// objects have been created.
|
||||
if (!CreateInitialDevices(optarg_queue)) {
|
||||
Cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
@ -629,7 +669,7 @@ int main(int argc, char* argv[])
|
|||
int initiator_id = -1;
|
||||
|
||||
// The initiator and target ID
|
||||
const BYTE id_data = bus->GetDAT();
|
||||
const uint8_t id_data = bus->GetDAT();
|
||||
|
||||
BUS::phase_t phase = BUS::phase_t::busfree;
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ string Localizer::Localize(LocalizationKey key, const string& locale, const stri
|
|||
|
||||
const auto& m = messages.find(key);
|
||||
if (m == messages.end()) {
|
||||
return "Missing localization for enum value " + to_string((int)key);
|
||||
return "Missing localization for enum value " + to_string(static_cast<int>(key));
|
||||
}
|
||||
|
||||
string message = m->second;
|
||||
|
|
|
@ -49,16 +49,16 @@ bool RascsiExecutor::ProcessDeviceCmd(const CommandContext& context, const PbDev
|
|||
|
||||
auto device = controller_manager.GetDeviceByIdAndLun(id, lun);
|
||||
|
||||
if (!ValidateOperationAgainstDevice(context, device, operation)) {
|
||||
if (!ValidateOperationAgainstDevice(context, *device, operation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case START:
|
||||
return Start(device, dryRun);
|
||||
return Start(*device, dryRun);
|
||||
|
||||
case STOP:
|
||||
return Stop(device, dryRun);
|
||||
return Stop(*device, dryRun);
|
||||
|
||||
case ATTACH:
|
||||
return Attach(context, pb_device, dryRun);
|
||||
|
@ -70,13 +70,13 @@ bool RascsiExecutor::ProcessDeviceCmd(const CommandContext& context, const PbDev
|
|||
return Insert(context, pb_device, device, dryRun);
|
||||
|
||||
case EJECT:
|
||||
return Eject(device, dryRun);
|
||||
return Eject(*device, dryRun);
|
||||
|
||||
case PROTECT:
|
||||
return Protect(device, dryRun);
|
||||
return Protect(*device, dryRun);
|
||||
|
||||
case UNPROTECT:
|
||||
return Unprotect(device, dryRun);
|
||||
return Unprotect(*device, dryRun);
|
||||
break;
|
||||
|
||||
case CHECK_AUTHENTICATION:
|
||||
|
@ -196,62 +196,62 @@ bool RascsiExecutor::SetLogLevel(const string& log_level) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Start(shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Start(PrimaryDevice& device, bool dryRun) const
|
||||
{
|
||||
if (!dryRun) {
|
||||
LOGINFO("Start requested for %s ID %d, unit %d", device->GetTypeString(), device->GetId(), device->GetLun())
|
||||
LOGINFO("Start requested for %s ID %d, unit %d", device.GetTypeString(), device.GetId(), device.GetLun())
|
||||
|
||||
if (!device->Start()) {
|
||||
LOGWARN("Starting %s ID %d, unit %d failed", device->GetTypeString(), device->GetId(), device->GetLun())
|
||||
if (!device.Start()) {
|
||||
LOGWARN("Starting %s ID %d, unit %d failed", device.GetTypeString(), device.GetId(), device.GetLun())
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Stop(shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Stop(PrimaryDevice& device, bool dryRun) const
|
||||
{
|
||||
if (!dryRun) {
|
||||
LOGINFO("Stop requested for %s ID %d, unit %d", device->GetTypeString(), device->GetId(), device->GetLun())
|
||||
LOGINFO("Stop requested for %s ID %d, unit %d", device.GetTypeString(), device.GetId(), device.GetLun())
|
||||
|
||||
device->Stop();
|
||||
device.Stop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Eject(shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Eject(PrimaryDevice& device, bool dryRun) const
|
||||
{
|
||||
if (!dryRun) {
|
||||
LOGINFO("Eject requested for %s ID %d, unit %d", device->GetTypeString(), device->GetId(), device->GetLun())
|
||||
LOGINFO("Eject requested for %s ID %d, unit %d", device.GetTypeString(), device.GetId(), device.GetLun())
|
||||
|
||||
if (!device->Eject(true)) {
|
||||
LOGWARN("Ejecting %s ID %d, unit %d failed", device->GetTypeString(), device->GetId(), device->GetLun())
|
||||
if (!device.Eject(true)) {
|
||||
LOGWARN("Ejecting %s ID %d, unit %d failed", device.GetTypeString(), device.GetId(), device.GetLun())
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Protect(shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Protect(PrimaryDevice& device, bool dryRun) const
|
||||
{
|
||||
if (!dryRun) {
|
||||
LOGINFO("Write protection requested for %s ID %d, unit %d", device->GetTypeString(), device->GetId(),
|
||||
device->GetLun())
|
||||
LOGINFO("Write protection requested for %s ID %d, unit %d", device.GetTypeString(), device.GetId(),
|
||||
device.GetLun())
|
||||
|
||||
device->SetProtected(true);
|
||||
device.SetProtected(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Unprotect(shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Unprotect(PrimaryDevice& device, bool dryRun) const
|
||||
{
|
||||
if (!dryRun) {
|
||||
LOGINFO("Write unprotection requested for %s ID %d, unit %d", device->GetTypeString(), device->GetId(),
|
||||
device->GetLun())
|
||||
LOGINFO("Write unprotection requested for %s ID %d, unit %d", device.GetTypeString(), device.GetId(),
|
||||
device.GetLun())
|
||||
|
||||
device->SetProtected(false);
|
||||
device.SetProtected(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -286,7 +286,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit
|
|||
auto storage_device = dynamic_pointer_cast<StorageDevice>(device);
|
||||
device->SetRemoved(storage_device != nullptr ? filename.empty() : false);
|
||||
|
||||
if (!SetProductData(context, pb_device, device)) {
|
||||
if (!SetProductData(context, pb_device, *device)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit
|
|||
return context.ReturnLocalizedError(LocalizationKey::ERROR_MISSING_FILENAME, PbDeviceType_Name(type));
|
||||
}
|
||||
|
||||
if (!ValidateImageFile(context, storage_device, filename, full_path)) {
|
||||
if (!ValidateImageFile(context, *storage_device, filename, full_path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -319,12 +319,11 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit
|
|||
}
|
||||
|
||||
if (device->SupportsParams() && !device->Init(params)) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_INITIALIZATION, PbDeviceType_Name(type),
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_INITIALIZATION, PbDeviceType_Name(device->GetType()),
|
||||
to_string(id), to_string(lun));
|
||||
}
|
||||
|
||||
// Remove SupportsFile as soon as Daynaport and bridge do not inherit from Disk anymore
|
||||
if (storage_device != nullptr && storage_device->SupportsFile()) {
|
||||
if (storage_device != nullptr) {
|
||||
storage_device->ReserveFile(full_path, id, lun);
|
||||
}
|
||||
|
||||
|
@ -351,7 +350,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit
|
|||
}
|
||||
|
||||
bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
||||
shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
const shared_ptr<PrimaryDevice>& device, bool dryRun) const
|
||||
{
|
||||
auto storage_device = dynamic_pointer_cast<StorageDevice>(device);
|
||||
if (storage_device == nullptr) {
|
||||
|
@ -384,7 +383,7 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit
|
|||
}
|
||||
|
||||
string full_path;
|
||||
if (!ValidateImageFile(context, storage_device, filename, full_path)) {
|
||||
if (!ValidateImageFile(context, *storage_device, filename, full_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -395,9 +394,8 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::Detach(const CommandContext& context, shared_ptr<PrimaryDevice> device, bool dryRun) const
|
||||
bool RascsiExecutor::Detach(const CommandContext& context, const shared_ptr<PrimaryDevice>& device, bool dryRun) const
|
||||
{
|
||||
cerr << "AAA " << device->GetId() << endl;
|
||||
auto controller = controller_manager.FindController(device->GetId());
|
||||
if (controller == nullptr) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_DETACH);
|
||||
|
@ -541,7 +539,7 @@ string RascsiExecutor::SetReservedIds(string_view ids)
|
|||
return "";
|
||||
}
|
||||
|
||||
bool RascsiExecutor::ValidateImageFile(const CommandContext& context, shared_ptr<StorageDevice> storage_device,
|
||||
bool RascsiExecutor::ValidateImageFile(const CommandContext& context, StorageDevice& storage_device,
|
||||
const string& filename, string& full_path) const
|
||||
{
|
||||
if (filename.empty()) {
|
||||
|
@ -569,19 +567,19 @@ bool RascsiExecutor::ValidateImageFile(const CommandContext& context, shared_ptr
|
|||
}
|
||||
}
|
||||
|
||||
storage_device->SetFilename(effective_filename);
|
||||
storage_device.SetFilename(effective_filename);
|
||||
|
||||
if (storage_device->IsReadOnlyFile()) {
|
||||
if (storage_device.IsReadOnlyFile()) {
|
||||
// Permanently write-protected
|
||||
storage_device->SetReadOnly(true);
|
||||
storage_device->SetProtectable(false);
|
||||
storage_device.SetReadOnly(true);
|
||||
storage_device.SetProtectable(false);
|
||||
}
|
||||
else {
|
||||
storage_device->SetReadOnly(false);
|
||||
storage_device->SetProtectable(true);
|
||||
storage_device.SetReadOnly(false);
|
||||
storage_device.SetProtectable(true);
|
||||
}
|
||||
|
||||
storage_device->Open();
|
||||
storage_device.Open();
|
||||
|
||||
full_path = effective_filename;
|
||||
|
||||
|
@ -701,23 +699,23 @@ bool RascsiExecutor::SetSectorSize(const CommandContext& context, shared_ptr<Pri
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RascsiExecutor::ValidateOperationAgainstDevice(const CommandContext& context,
|
||||
const shared_ptr<PrimaryDevice> device, const PbOperation& operation)
|
||||
bool RascsiExecutor::ValidateOperationAgainstDevice(const CommandContext& context, const PrimaryDevice& device,
|
||||
const PbOperation& operation)
|
||||
{
|
||||
if ((operation == START || operation == STOP) && !device->IsStoppable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, device->GetTypeString());
|
||||
if ((operation == START || operation == STOP) && !device.IsStoppable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_STOPPABLE, device.GetTypeString());
|
||||
}
|
||||
|
||||
if ((operation == INSERT || operation == EJECT) && !device->IsRemovable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, device->GetTypeString());
|
||||
if ((operation == INSERT || operation == EJECT) && !device.IsRemovable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_REMOVABLE, device.GetTypeString());
|
||||
}
|
||||
|
||||
if ((operation == PROTECT || operation == UNPROTECT) && !device->IsProtectable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, device->GetTypeString());
|
||||
if ((operation == PROTECT || operation == UNPROTECT) && !device.IsProtectable()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_PROTECTABLE, device.GetTypeString());
|
||||
}
|
||||
|
||||
if ((operation == PROTECT || operation == UNPROTECT) && !device->IsReady()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_READY, device->GetTypeString());
|
||||
if ((operation == PROTECT || operation == UNPROTECT) && !device.IsReady()) {
|
||||
return context.ReturnLocalizedError(LocalizationKey::ERROR_OPERATION_DENIED_READY, device.GetTypeString());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -740,17 +738,17 @@ bool RascsiExecutor::ValidateIdAndLun(const CommandContext& context, int id, int
|
|||
}
|
||||
|
||||
bool RascsiExecutor::SetProductData(const CommandContext& context, const PbDeviceDefinition& pb_device,
|
||||
shared_ptr<PrimaryDevice> device)
|
||||
PrimaryDevice& device)
|
||||
{
|
||||
try {
|
||||
if (!pb_device.vendor().empty()) {
|
||||
device->SetVendor(pb_device.vendor());
|
||||
device.SetVendor(pb_device.vendor());
|
||||
}
|
||||
if (!pb_device.product().empty()) {
|
||||
device->SetProduct(pb_device.product());
|
||||
device.SetProduct(pb_device.product());
|
||||
}
|
||||
if (!pb_device.revision().empty()) {
|
||||
device->SetRevision(pb_device.revision());
|
||||
device.SetRevision(pb_device.revision());
|
||||
}
|
||||
}
|
||||
catch(const invalid_argument& e) {
|
||||
|
|
|
@ -45,27 +45,26 @@ public:
|
|||
bool ProcessDeviceCmd(const CommandContext&, const PbDeviceDefinition&, const PbCommand&, bool);
|
||||
bool ProcessCmd(const CommandContext&, const PbCommand&);
|
||||
bool SetLogLevel(const string&) const;
|
||||
bool Start(shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Stop(shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Eject(shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Protect(shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Unprotect(shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Start(PrimaryDevice&, bool) const;
|
||||
bool Stop(PrimaryDevice&, bool) const;
|
||||
bool Eject(PrimaryDevice&, bool) const;
|
||||
bool Protect(PrimaryDevice&, bool) const;
|
||||
bool Unprotect(PrimaryDevice&, bool) const;
|
||||
bool Attach(const CommandContext&, const PbDeviceDefinition&, bool);
|
||||
bool Insert(const CommandContext&, const PbDeviceDefinition&, shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Detach(const CommandContext&, shared_ptr<PrimaryDevice>, bool) const;
|
||||
bool Insert(const CommandContext&, const PbDeviceDefinition&, const shared_ptr<PrimaryDevice>&, bool) const;
|
||||
bool Detach(const CommandContext&, const shared_ptr<PrimaryDevice>&, bool) const;
|
||||
void DetachAll();
|
||||
bool ShutDown(const CommandContext&, const string&);
|
||||
string SetReservedIds(string_view);
|
||||
bool ValidateImageFile(const CommandContext&, shared_ptr<StorageDevice>, const string&, string&) const;
|
||||
bool ValidateImageFile(const CommandContext&, StorageDevice&, const string&, string&) const;
|
||||
void PrintCommand(const PbCommand&, const PbDeviceDefinition&, bool) const;
|
||||
string ValidateLunSetup(const PbCommand&) const;
|
||||
bool VerifyExistingIdAndLun(const CommandContext&, int, int) const;
|
||||
shared_ptr<PrimaryDevice> CreateDevice(const CommandContext&, const PbDeviceType, int, const string&) const;
|
||||
bool SetSectorSize(const CommandContext&, shared_ptr<PrimaryDevice>, int) const;
|
||||
|
||||
static bool ValidateOperationAgainstDevice(const CommandContext&, const shared_ptr<PrimaryDevice>,
|
||||
const PbOperation&);
|
||||
static bool ValidateOperationAgainstDevice(const CommandContext&, const PrimaryDevice&, const PbOperation&);
|
||||
static bool ValidateIdAndLun(const CommandContext&, int, int);
|
||||
static bool SetProductData(const CommandContext&, const PbDeviceDefinition&, shared_ptr<PrimaryDevice>);
|
||||
static bool SetProductData(const CommandContext&, const PbDeviceDefinition&, PrimaryDevice&);
|
||||
|
||||
};
|
||||
|
|
|
@ -169,19 +169,20 @@ bool RascsiImage::DeleteImage(const CommandContext& context, const PbCommand& co
|
|||
return context.ReturnStatus(false, ("Invalid folder hierarchy depth '" + filename + "'").c_str());
|
||||
}
|
||||
|
||||
const string full_filename = GetFullName(filename);
|
||||
const auto full_filename = path(GetFullName(filename));
|
||||
|
||||
if (!exists(full_filename)) {
|
||||
return context.ReturnStatus(false, "Image file '" + string(full_filename) + "' does not exist");
|
||||
}
|
||||
|
||||
const auto [id, lun] = StorageDevice::GetIdsForReservedFile(full_filename);
|
||||
if (id == -1 || lun == -1) {
|
||||
return context.ReturnStatus(false, "Can't delete image file '" + full_filename +
|
||||
if (id != -1 || lun != -1) {
|
||||
return context.ReturnStatus(false, "Can't delete image file '" + string(full_filename) +
|
||||
"', it is currently being used by device ID " + to_string(id) + ", LUN " + to_string(lun));
|
||||
}
|
||||
|
||||
try {
|
||||
remove(path(full_filename));
|
||||
}
|
||||
catch(const filesystem_error& e) {
|
||||
return context.ReturnStatus(false, "Can't delete image file '" + full_filename + "': " + e.what());
|
||||
if (error_code error; !remove(full_filename, error)) {
|
||||
return context.ReturnStatus(false, "Can't delete image file '" + string(full_filename) + "'");
|
||||
}
|
||||
|
||||
// Delete empty subfolders
|
||||
|
@ -194,12 +195,8 @@ bool RascsiImage::DeleteImage(const CommandContext& context, const PbCommand& co
|
|||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
remove(full_folder);
|
||||
}
|
||||
catch(const filesystem_error& e) {
|
||||
return context.ReturnStatus(false, "Can't delete empty image folder '" + string(full_folder)
|
||||
+ "': " + e.what());
|
||||
if (error_code error; !remove(full_folder)) {
|
||||
return context.ReturnStatus(false, "Can't delete empty image folder '" + string(full_folder) + "'");
|
||||
}
|
||||
|
||||
last_slash = folder.rfind('/');
|
||||
|
@ -218,6 +215,12 @@ bool RascsiImage::RenameImage(const CommandContext& context, const PbCommand& co
|
|||
return false;
|
||||
}
|
||||
|
||||
const auto [id, lun] = StorageDevice::GetIdsForReservedFile(from);
|
||||
if (id != -1 || lun != -1) {
|
||||
return context.ReturnStatus(false, "Can't rename/move image file '" + from +
|
||||
"', it is currently being used by device ID " + to_string(id) + ", LUN " + to_string(lun));
|
||||
}
|
||||
|
||||
if (!CreateImageFolder(context, to)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -246,6 +249,12 @@ bool RascsiImage::CopyImage(const CommandContext& context, const PbCommand& comm
|
|||
return context.ReturnStatus(false, "Can't read source image file '" + from + "'");
|
||||
}
|
||||
|
||||
const auto [id, lun] = StorageDevice::GetIdsForReservedFile(from);
|
||||
if (id != -1 || lun != -1) {
|
||||
return context.ReturnStatus(false, "Can't copy image file '" + from +
|
||||
"', it is currently being used by device ID " + to_string(id) + ", LUN " + to_string(lun));
|
||||
}
|
||||
|
||||
if (!CreateImageFolder(context, to)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "rascsi_interface.pb.h"
|
||||
#include <dirent.h>
|
||||
#include <list>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
@ -51,7 +51,7 @@ private:
|
|||
|
||||
int max_luns;
|
||||
|
||||
const list<string> log_levels = { "trace", "debug", "info", "warn", "err", "off" };
|
||||
const array<string, 6> log_levels = { "trace", "debug", "info", "warn", "err", "off" };
|
||||
|
||||
unique_ptr<PbDeviceProperties> GetDeviceProperties(const Device&) const;
|
||||
void GetDevice(const Device&, PbDevice&, const string&) const;
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
using namespace rascsi_interface;
|
||||
|
||||
volatile bool RascsiService::running = false;
|
||||
|
||||
void RascsiService::Cleanup() const
|
||||
{
|
||||
if (service_socket != -1) {
|
||||
|
|
|
@ -28,7 +28,7 @@ class RascsiService
|
|||
|
||||
thread monthread;
|
||||
|
||||
static volatile bool running;
|
||||
static inline volatile bool running = false;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -30,9 +30,10 @@ private:
|
|||
unordered_map<int, PbOperation> operations = {
|
||||
{ 'a', ATTACH },
|
||||
{ 'd', DETACH },
|
||||
{ 'i', INSERT },
|
||||
{ 'e', EJECT },
|
||||
{ 'i', INSERT },
|
||||
{ 'p', PROTECT },
|
||||
{ 's', DEVICES_INFO },
|
||||
{ 'u', UNPROTECT }
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <unistd.h>
|
||||
#include "os.h"
|
||||
#include "rasdump_fileio.h"
|
||||
#include "hal/gpiobus.h"
|
||||
#include "hal/gpiobus_factory.h"
|
||||
|
@ -41,7 +40,7 @@ int targetid; // Target ID
|
|||
int boardid; // Board ID (own ID)
|
||||
string hdsfile; // HDS file
|
||||
bool restore; // Restore flag
|
||||
BYTE buffer[BUFSIZE]; // Work Buffer
|
||||
uint8_t buffer[BUFSIZE]; // Work Buffer
|
||||
int result; // Result Code
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -249,7 +248,7 @@ void BusFree()
|
|||
bool Selection(int id)
|
||||
{
|
||||
// ID setting and SEL assert
|
||||
BYTE data = 1 << boardid;
|
||||
uint8_t data = 1 << boardid;
|
||||
data |= (1 << id);
|
||||
bus->SetDAT(data);
|
||||
bus->SetSEL(true);
|
||||
|
@ -278,7 +277,7 @@ bool Selection(int id)
|
|||
// Command Phase
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool Command(BYTE *buf, int length)
|
||||
bool Command(uint8_t *buf, int length)
|
||||
{
|
||||
// Waiting for Phase
|
||||
if (!WaitPhase(BUS::phase_t::command)) {
|
||||
|
@ -303,7 +302,7 @@ bool Command(BYTE *buf, int length)
|
|||
// Data in phase
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int DataIn(BYTE *buf, int length)
|
||||
int DataIn(uint8_t *buf, int length)
|
||||
{
|
||||
// Wait for phase
|
||||
if (!WaitPhase(BUS::phase_t::datain)) {
|
||||
|
@ -319,7 +318,7 @@ int DataIn(BYTE *buf, int length)
|
|||
// Data out phase
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int DataOut(BYTE *buf, int length)
|
||||
int DataOut(uint8_t *buf, int length)
|
||||
{
|
||||
// Wait for phase
|
||||
if (!WaitPhase(BUS::phase_t::dataout)) {
|
||||
|
@ -337,7 +336,7 @@ int DataOut(BYTE *buf, int length)
|
|||
//---------------------------------------------------------------------------
|
||||
int Status()
|
||||
{
|
||||
BYTE buf[256];
|
||||
uint8_t buf[256];
|
||||
|
||||
// Wait for phase
|
||||
if (!WaitPhase(BUS::phase_t::status)) {
|
||||
|
@ -360,7 +359,7 @@ int Status()
|
|||
//---------------------------------------------------------------------------
|
||||
int MessageIn()
|
||||
{
|
||||
BYTE buf[256];
|
||||
uint8_t buf[256];
|
||||
|
||||
// Wait for phase
|
||||
if (!WaitPhase(BUS::phase_t::msgin)) {
|
||||
|
@ -383,7 +382,7 @@ int MessageIn()
|
|||
//---------------------------------------------------------------------------
|
||||
int TestUnitReady(int id)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -425,9 +424,9 @@ exit:
|
|||
// REQUEST SENSE
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int RequestSense(int id, BYTE *buf)
|
||||
int RequestSense(int id, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -484,9 +483,9 @@ exit:
|
|||
// MODE SENSE
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int ModeSense(int id, BYTE *buf)
|
||||
int ModeSense(int id, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -544,9 +543,9 @@ exit:
|
|||
// INQUIRY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int Inquiry(int id, BYTE *buf)
|
||||
int Inquiry(int id, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -603,9 +602,9 @@ exit:
|
|||
// READ CAPACITY
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int ReadCapacity(int id, BYTE *buf)
|
||||
int ReadCapacity(int id, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -661,9 +660,9 @@ exit:
|
|||
// READ10
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int Read10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *buf)
|
||||
int Read10(int id, uint32_t bstart, uint32_t blength, uint32_t length, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -677,12 +676,12 @@ int Read10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *buf
|
|||
|
||||
// COMMAND
|
||||
cmd[0] = 0x28;
|
||||
cmd[2] = (BYTE)(bstart >> 24);
|
||||
cmd[3] = (BYTE)(bstart >> 16);
|
||||
cmd[4] = (BYTE)(bstart >> 8);
|
||||
cmd[5] = (BYTE)bstart;
|
||||
cmd[7] = (BYTE)(blength >> 8);
|
||||
cmd[8] = (BYTE)blength;
|
||||
cmd[2] = (uint8_t)(bstart >> 24);
|
||||
cmd[3] = (uint8_t)(bstart >> 16);
|
||||
cmd[4] = (uint8_t)(bstart >> 8);
|
||||
cmd[5] = (uint8_t)bstart;
|
||||
cmd[7] = (uint8_t)(blength >> 8);
|
||||
cmd[8] = (uint8_t)blength;
|
||||
if (!Command(cmd.data(), 10)) {
|
||||
result = -2;
|
||||
goto exit;
|
||||
|
@ -724,9 +723,9 @@ exit:
|
|||
// WRITE10
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int Write10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *buf)
|
||||
int Write10(int id, uint32_t bstart, uint32_t blength, uint32_t length, uint8_t *buf)
|
||||
{
|
||||
array<BYTE, 256> cmd = {};
|
||||
array<uint8_t, 256> cmd = {};
|
||||
|
||||
// Result code initialization
|
||||
result = 0;
|
||||
|
@ -740,12 +739,12 @@ int Write10(int id, uint32_t bstart, uint32_t blength, uint32_t length, BYTE *bu
|
|||
|
||||
// COMMAND
|
||||
cmd[0] = 0x2a;
|
||||
cmd[2] = (BYTE)(bstart >> 24);
|
||||
cmd[3] = (BYTE)(bstart >> 16);
|
||||
cmd[4] = (BYTE)(bstart >> 8);
|
||||
cmd[5] = (BYTE)bstart;
|
||||
cmd[7] = (BYTE)(blength >> 8);
|
||||
cmd[8] = (BYTE)blength;
|
||||
cmd[2] = (uint8_t)(bstart >> 24);
|
||||
cmd[3] = (uint8_t)(bstart >> 16);
|
||||
cmd[4] = (uint8_t)(bstart >> 8);
|
||||
cmd[5] = (uint8_t)bstart;
|
||||
cmd[7] = (uint8_t)(blength >> 8);
|
||||
cmd[8] = (uint8_t)blength;
|
||||
if (!Command(cmd.data(), 10)) {
|
||||
result = -2;
|
||||
goto exit;
|
||||
|
|
|
@ -60,7 +60,7 @@ bool Fileio::Open(const char *fname, OpenMode mode)
|
|||
return Open(fname, mode, false);
|
||||
}
|
||||
|
||||
bool Fileio::Read(BYTE *buffer, int size) const
|
||||
bool Fileio::Read(uint8_t *buffer, int size) const
|
||||
{
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
@ -69,7 +69,7 @@ bool Fileio::Read(BYTE *buffer, int size) const
|
|||
return read(handle, buffer, size) == size;
|
||||
}
|
||||
|
||||
bool Fileio::Write(const BYTE *buffer, int size) const
|
||||
bool Fileio::Write(const uint8_t *buffer, int size) const
|
||||
{
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "os.h"
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
class Fileio
|
||||
|
@ -29,8 +29,8 @@ public:
|
|||
Fileio& operator=(const Fileio&) = default;
|
||||
|
||||
bool Open(const char *fname, OpenMode mode);
|
||||
bool Read(BYTE *buffer, int size) const;
|
||||
bool Write(const BYTE *buffer, int size) const;
|
||||
bool Read(uint8_t *buffer, int size) const;
|
||||
bool Write(const uint8_t *buffer, int size) const;
|
||||
off_t GetFileSize() const;
|
||||
void Close();
|
||||
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// TODO Remove this include as soon as gpiobus.cpp/h is open for editing (adding the include there) again
|
||||
#include "bus.h"
|
||||
|
||||
namespace scsi_defs {
|
||||
enum class scsi_level : int {
|
||||
SCSI_1_CCS = 1,
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include "log.h"
|
||||
#include "hal/gpiobus.h"
|
||||
#include "hal/gpiobus_factory.h"
|
||||
|
|
|
@ -109,11 +109,15 @@ TEST(AbstractControllerTest, ProcessPhase)
|
|||
EXPECT_CALL(controller, MsgOut());
|
||||
controller.ProcessPhase();
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reselection);
|
||||
EXPECT_THROW(controller.ProcessPhase(), scsi_exception);
|
||||
controller.SetPhase(BUS::phase_t::reselection);
|
||||
EXPECT_THAT([&] { controller.ProcessPhase(); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND),
|
||||
Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION))));
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
EXPECT_THROW(controller.ProcessPhase(), scsi_exception);
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
EXPECT_THAT([&] { controller.ProcessPhase(); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND),
|
||||
Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION))));
|
||||
}
|
||||
|
||||
TEST(AbstractControllerTest, DeviceLunLifeCycle)
|
||||
|
@ -139,6 +143,7 @@ TEST(AbstractControllerTest, DeviceLunLifeCycle)
|
|||
EXPECT_EQ(nullptr, controller.GetDeviceForLun(0));
|
||||
EXPECT_TRUE(controller.RemoveDevice(device1));
|
||||
EXPECT_EQ(0, controller.GetLunCount());
|
||||
EXPECT_FALSE(controller.RemoveDevice(device1));
|
||||
}
|
||||
|
||||
TEST(AbstractControllerTest, ExtractInitiatorId)
|
||||
|
@ -159,8 +164,8 @@ TEST(AbstractControllerTest, GetOpcode)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
cmd[0] = 0x12;
|
||||
EXPECT_EQ(0x12, (int)controller.GetOpcode());
|
||||
cmd[0] = static_cast<int>(scsi_command::eCmdInquiry);
|
||||
EXPECT_EQ(scsi_command::eCmdInquiry, controller.GetOpcode());
|
||||
}
|
||||
|
||||
TEST(AbstractControllerTest, GetLun)
|
||||
|
@ -175,7 +180,17 @@ TEST(AbstractControllerTest, GetLun)
|
|||
EXPECT_EQ(LUN, controller.GetLun());
|
||||
}
|
||||
|
||||
TEST(AbstractControllerTest, SetLength)
|
||||
TEST(AbstractControllerTest, Blocks)
|
||||
{
|
||||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
|
||||
controller.SetBlocks(1);
|
||||
EXPECT_EQ(1, controller.GetBlocks());
|
||||
controller.DecrementBlocks();
|
||||
EXPECT_EQ(0, controller.GetBlocks());
|
||||
}
|
||||
|
||||
TEST(AbstractControllerTest, Length)
|
||||
{
|
||||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
TEST(CTapDriverTest, Crc32)
|
||||
{
|
||||
array<BYTE, ETH_FRAME_LEN> buf;
|
||||
array<uint8_t, ETH_FRAME_LEN> buf;
|
||||
|
||||
buf.fill(0x00);
|
||||
EXPECT_EQ(0xe3d887bb, CTapDriver::Crc32(buf.data(), ETH_FRAME_LEN));
|
||||
|
@ -30,12 +30,12 @@ TEST(CTapDriverTest, Crc32)
|
|||
EXPECT_EQ(0x29cbd638, CTapDriver::Crc32(buf.data(), ETH_FRAME_LEN));
|
||||
|
||||
for (size_t i = 0; i < buf.size(); i++) {
|
||||
buf[i] = (BYTE)i;
|
||||
buf[i] = (uint8_t)i;
|
||||
}
|
||||
EXPECT_EQ(0xe7870705, CTapDriver::Crc32(buf.data(), ETH_FRAME_LEN));
|
||||
|
||||
for (size_t i = buf.size() - 1; i > 0; i--) {
|
||||
buf[i] = (BYTE)i;
|
||||
buf[i] = (uint8_t)i;
|
||||
}
|
||||
EXPECT_EQ(0xe7870705, CTapDriver::Crc32(buf.data(), ETH_FRAME_LEN));
|
||||
}
|
||||
|
|
|
@ -23,11 +23,7 @@ TEST(DiskTest, Dispatch)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_FALSE(disk->Dispatch(scsi_command::eCmdIcd));
|
||||
|
||||
disk->SetRemovable(true);
|
||||
disk->MediumChanged();
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
EXPECT_FALSE(disk->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class";
|
||||
}
|
||||
|
||||
TEST(DiskTest, Rezero)
|
||||
|
@ -37,8 +33,10 @@ TEST(DiskTest, Rezero)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRezero), scsi_exception)
|
||||
<< "REZERO must fail because drive is not ready";
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRezero); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "REZERO must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
|
||||
|
@ -52,32 +50,38 @@ TEST(DiskTest, FormatUnit)
|
|||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
auto disk = make_shared<MockDisk>();
|
||||
|
||||
controller.AddDevice(disk);
|
||||
controller.AddDevice(disk);
|
||||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_exception);
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormat); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "FORMAT UNIT must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
disk->SetReady(true);
|
||||
|
||||
EXPECT_CALL(controller, Status());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdFormat));
|
||||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[1] = 0x10;
|
||||
cmd[4] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdFormat), scsi_exception);
|
||||
cmd[1] = 0x10;
|
||||
cmd[4] = 1;
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormat); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))));
|
||||
}
|
||||
|
||||
TEST(DiskTest, ReassignBlocks)
|
||||
{
|
||||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
auto disk = make_shared<MockDisk>();
|
||||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReassign), scsi_exception)
|
||||
<< "REASSIGN must fail because drive is not ready";
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReassign); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "REASSIGN must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
|
||||
|
@ -95,17 +99,21 @@ TEST(DiskTest, Seek6)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "SEEK(6) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek6), scsi_exception)
|
||||
// Block count
|
||||
cmd[4] = 1;
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "SEEK(6) must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
|
||||
// Block count
|
||||
cmd[4] = 1;
|
||||
EXPECT_CALL(controller, Status());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSeek6));
|
||||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
@ -120,23 +128,60 @@ TEST(DiskTest, Seek10)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "SEEK(10) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdSeek10), scsi_exception)
|
||||
// Block count
|
||||
cmd[5] = 1;
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "SEEK(10) must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
|
||||
// Block count
|
||||
cmd[5] = 1;
|
||||
EXPECT_CALL(controller, Status());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSeek10));
|
||||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
}
|
||||
|
||||
TEST(DiskTest, ReadCapacity)
|
||||
TEST(DiskTest, ReadCapacity10)
|
||||
{
|
||||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
auto disk = make_shared<MockDisk>();
|
||||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "READ CAPACITY(10) must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "READ CAPACITY(10) must fail because the medium has no capacity";
|
||||
|
||||
disk->SetBlockCount(0x12345678);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10));
|
||||
auto& buf = controller.GetBuffer();
|
||||
EXPECT_EQ(0x1234, GetInt16(buf, 0));
|
||||
EXPECT_EQ(0x5677, GetInt16(buf, 2));
|
||||
|
||||
disk->SetBlockCount(0x1234567887654321);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10));
|
||||
buf = controller.GetBuffer();
|
||||
EXPECT_EQ(0xffff, GetInt16(buf, 0));
|
||||
EXPECT_EQ(0xffff, GetInt16(buf, 2));
|
||||
}
|
||||
|
||||
TEST(DiskTest, ReadCapacity16)
|
||||
{
|
||||
MockAbstractController controller(make_shared<MockBus>(), 0);
|
||||
auto disk = make_shared<MockDisk>();
|
||||
|
@ -145,59 +190,36 @@ TEST(DiskTest, ReadCapacity)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception)
|
||||
<< "Neithed READ CAPACITY(16) nor READ LONG(16)";
|
||||
cmd[1] = 0x00;
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Neither READ CAPACITY(16) nor READ LONG(16)";
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_exception)
|
||||
<< "READ CAPACITY(10) must fail because drive is not ready";
|
||||
// READ CAPACITY(16), not READ LONG(16)
|
||||
cmd[1] = 0x10;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception)
|
||||
<< "READ CAPACITY(16) must fail because drive is not ready";
|
||||
cmd[1] = 0x00;
|
||||
|
||||
disk->SetReady(true);
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity10), scsi_exception)
|
||||
<< "READ CAPACITY(10) must fail because the medium has no capacity";
|
||||
// READ CAPACITY(16), not READ LONG(16)
|
||||
cmd[1] = 0x10;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception)
|
||||
<< "READ CAPACITY(16) must fail because the medium has no capacity";
|
||||
cmd[1] = 0x00;
|
||||
|
||||
disk->SetBlockCount(0x12345678);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10));
|
||||
EXPECT_EQ(0x12, controller.GetBuffer()[0]);
|
||||
EXPECT_EQ(0x34, controller.GetBuffer()[1]);
|
||||
EXPECT_EQ(0x56, controller.GetBuffer()[2]);
|
||||
EXPECT_EQ(0x77, controller.GetBuffer()[3]);
|
||||
|
||||
disk->SetBlockCount(0x1234567887654321);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10));
|
||||
EXPECT_EQ(0xff, controller.GetBuffer()[0]);
|
||||
EXPECT_EQ(0xff, controller.GetBuffer()[1]);
|
||||
EXPECT_EQ(0xff, controller.GetBuffer()[2]);
|
||||
EXPECT_EQ(0xff, controller.GetBuffer()[3]);
|
||||
|
||||
disk->SetSectorSizeInBytes(1024);
|
||||
// READ CAPACITY(16), not READ LONG(16)
|
||||
cmd[1] = 0x10;
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "READ CAPACITY(16) must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "READ CAPACITY(16) must fail because the medium has no capacity";
|
||||
|
||||
disk->SetBlockCount(0x1234567887654321);
|
||||
disk->SetSectorSizeInBytes(1024);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16));
|
||||
EXPECT_EQ(0x12, controller.GetBuffer()[0]);
|
||||
EXPECT_EQ(0x34, controller.GetBuffer()[1]);
|
||||
EXPECT_EQ(0x56, controller.GetBuffer()[2]);
|
||||
EXPECT_EQ(0x78, controller.GetBuffer()[3]);
|
||||
EXPECT_EQ(0x87, controller.GetBuffer()[4]);
|
||||
EXPECT_EQ(0x65, controller.GetBuffer()[5]);
|
||||
EXPECT_EQ(0x43, controller.GetBuffer()[6]);
|
||||
EXPECT_EQ(0x20, controller.GetBuffer()[7]);
|
||||
EXPECT_EQ(0x00, controller.GetBuffer()[8]);
|
||||
EXPECT_EQ(0x00, controller.GetBuffer()[9]);
|
||||
EXPECT_EQ(0x04, controller.GetBuffer()[10]);
|
||||
EXPECT_EQ(0x00, controller.GetBuffer()[11]);
|
||||
const auto& buf = controller.GetBuffer();
|
||||
EXPECT_EQ(0x1234, GetInt16(buf, 0));
|
||||
EXPECT_EQ(0x5678, GetInt16(buf, 2));
|
||||
EXPECT_EQ(0x8765, GetInt16(buf, 4));
|
||||
EXPECT_EQ(0x4320, GetInt16(buf, 6));
|
||||
EXPECT_EQ(0x0000, GetInt16(buf, 8));
|
||||
EXPECT_EQ(0x0400, GetInt16(buf, 10));
|
||||
}
|
||||
|
||||
TEST(DiskTest, Read6)
|
||||
|
@ -207,7 +229,9 @@ TEST(DiskTest, Read6)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRead6), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRead6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "READ(6) must fail for a medium with 0 blocks";
|
||||
|
||||
// Further testing requires filesystem access
|
||||
|
@ -220,7 +244,9 @@ TEST(DiskTest, Read10)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRead10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRead10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "READ(10) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
|
@ -238,7 +264,9 @@ TEST(DiskTest, Read16)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRead16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRead16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "READ(16) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
|
@ -256,7 +284,9 @@ TEST(DiskTest, Write6)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWrite6), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWrite6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "WRIte(6) must fail for a medium with 0 blocks";
|
||||
|
||||
// Further testing requires filesystem access
|
||||
|
@ -269,7 +299,9 @@ TEST(DiskTest, Write10)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWrite10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWrite10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "WRITE(10) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
|
@ -287,7 +319,9 @@ TEST(DiskTest, Write16)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWrite16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWrite16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "WRITE(16) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
|
@ -305,12 +339,14 @@ TEST(DiskTest, Verify10)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdVerify10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdVerify10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "VERIFY(10) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
EXPECT_CALL(controller, Status());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWrite10));
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdVerify10));
|
||||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
// Further testing requires filesystem access
|
||||
|
@ -323,12 +359,14 @@ TEST(DiskTest, Verify16)
|
|||
|
||||
controller.AddDevice(disk);
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdVerify16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdVerify16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "VERIFY(16) must fail for a medium with 0 blocks";
|
||||
|
||||
disk->SetBlockCount(1);
|
||||
EXPECT_CALL(controller, Status());
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWrite16));
|
||||
EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdVerify16));
|
||||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
// Further testing requires filesystem access
|
||||
|
@ -348,12 +386,16 @@ TEST(DiskTest, ReadLong10)
|
|||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[2] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadLong10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "READ LONG(10) must fail because the capacity is exceeded";
|
||||
cmd[2] = 0;
|
||||
|
||||
cmd[7] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadLong10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadLong10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "READ LONG(10) must fail because it currently only supports 0 bytes transfer length";
|
||||
}
|
||||
|
||||
|
@ -369,7 +411,9 @@ TEST(DiskTest, ReadLong16)
|
|||
// READ LONG(16), not READ CAPACITY(16)
|
||||
cmd[1] = 0x11;
|
||||
cmd[2] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "READ LONG(16) must fail because the capacity is exceeded";
|
||||
cmd[2] = 0;
|
||||
|
||||
|
@ -378,7 +422,9 @@ TEST(DiskTest, ReadLong16)
|
|||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[13] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "READ LONG(16) must fail because it currently only supports 0 bytes transfer length";
|
||||
}
|
||||
|
||||
|
@ -396,12 +442,16 @@ TEST(DiskTest, WriteLong10)
|
|||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[2] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWriteLong10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "WRITE LONG(10) must fail because the capacity is exceeded";
|
||||
cmd[2] = 0;
|
||||
|
||||
cmd[7] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong10), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWriteLong10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "WRITE LONG(10) must fail because it currently only supports 0 bytes transfer length";
|
||||
}
|
||||
|
||||
|
@ -415,7 +465,9 @@ TEST(DiskTest, WriteLong16)
|
|||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
cmd[2] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWriteLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE))))
|
||||
<< "WRITE LONG(16) must fail because the capacity is exceeded";
|
||||
cmd[2] = 0;
|
||||
|
||||
|
@ -424,7 +476,9 @@ TEST(DiskTest, WriteLong16)
|
|||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[13] = 1;
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdWriteLong16), scsi_exception)
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWriteLong16); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "WRITE LONG(16) must fail because it currently only supports 0 bytes transfer length";
|
||||
}
|
||||
|
||||
|
@ -457,12 +511,16 @@ TEST(DiskTest, StartStopUnit)
|
|||
|
||||
disk->SetReady(false);
|
||||
EXPECT_CALL(*disk, FlushCache).Times(0);
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdStartStop), scsi_exception);
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdStartStop); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LOAD_OR_EJECT_FAILED))));
|
||||
|
||||
disk->SetReady(true);
|
||||
disk->SetLocked(true);
|
||||
EXPECT_CALL(*disk, FlushCache).Times(0);
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdStartStop), scsi_exception);
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdStartStop); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::LOAD_OR_EJECT_FAILED))));
|
||||
|
||||
// Start/Unload
|
||||
cmd[4] = 0x01;
|
||||
|
@ -487,8 +545,10 @@ TEST(DiskTest, PreventAllowMediumRemoval)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(disk->Dispatch(scsi_command::eCmdRemoval), scsi_exception)
|
||||
<< "REMOVAL must fail because drive is not ready";
|
||||
EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRemoval); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))))
|
||||
<< "REMOVAL must fail because drive is not ready";
|
||||
|
||||
disk->SetReady(true);
|
||||
|
||||
|
|
|
@ -31,10 +31,6 @@ TEST(GpioBusTest, GetCommandByteCount)
|
|||
EXPECT_EQ(12, GPIOBUS::GetCommandByteCount(0xa0));
|
||||
opcodes.insert(0xa0);
|
||||
|
||||
// TODO Opcode 0x05 must be removed from gpiobus.cpp
|
||||
EXPECT_EQ(10, GPIOBUS::GetCommandByteCount(0x05));
|
||||
opcodes.insert(0x05);
|
||||
|
||||
for (int i = 0x20; i <= 0x7d; i++) {
|
||||
EXPECT_EQ(10, GPIOBUS::GetCommandByteCount(i));
|
||||
opcodes.insert(i);
|
||||
|
|
|
@ -69,7 +69,9 @@ TEST(HostServicesTest, StartStopUnit)
|
|||
|
||||
// START
|
||||
cmd[4] = 0x01;
|
||||
EXPECT_THROW(services->Dispatch(scsi_command::eCmdStartStop), scsi_exception);
|
||||
EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdStartStop); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))));
|
||||
}
|
||||
|
||||
TEST(HostServicesTest, ModeSense6)
|
||||
|
@ -79,27 +81,31 @@ TEST(HostServicesTest, ModeSense6)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense6), scsi_exception)
|
||||
<< "Unsupported mode page was returned";
|
||||
EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Unsupported mode page was returned";
|
||||
|
||||
cmd[2] = 0x20;
|
||||
EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense6), scsi_exception)
|
||||
<< "Block descriptors are not supported";
|
||||
EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Block descriptors are not supported";
|
||||
|
||||
cmd[1] = 0x08;
|
||||
// ALLOCATION LENGTH
|
||||
cmd[4] = 255;
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense6));
|
||||
vector<BYTE> &buffer = controller.GetBuffer();
|
||||
// Major version 1
|
||||
EXPECT_EQ(0x01, buffer[6]);
|
||||
// Minor version 0
|
||||
EXPECT_EQ(0x00, buffer[7]);
|
||||
// Year
|
||||
EXPECT_NE(0x00, buffer[9]);
|
||||
// Day
|
||||
EXPECT_NE(0x00, buffer[10]);
|
||||
vector<uint8_t>& buffer = controller.GetBuffer();
|
||||
// Major version 1
|
||||
EXPECT_EQ(0x01, buffer[6]);
|
||||
// Minor version 0
|
||||
EXPECT_EQ(0x00, buffer[7]);
|
||||
// Year
|
||||
EXPECT_NE(0x00, buffer[9]);
|
||||
// Day
|
||||
EXPECT_NE(0x00, buffer[10]);
|
||||
|
||||
// ALLOCATION LENGTH
|
||||
cmd[4] = 2;
|
||||
|
@ -116,27 +122,31 @@ TEST(HostServicesTest, ModeSense10)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense10), scsi_exception)
|
||||
<< "Unsupported mode page was returned";
|
||||
EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Unsupported mode page was returned";
|
||||
|
||||
cmd[2] = 0x20;
|
||||
EXPECT_THROW(services->Dispatch(scsi_command::eCmdModeSense10), scsi_exception)
|
||||
<< "Block descriptors are not supported";
|
||||
EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Block descriptors are not supported";
|
||||
|
||||
cmd[1] = 0x08;
|
||||
// ALLOCATION LENGTH
|
||||
cmd[8] = 255;
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense10));
|
||||
vector<BYTE> &buffer = controller.GetBuffer();
|
||||
// Major version 1
|
||||
EXPECT_EQ(0x01, buffer[10]);
|
||||
// Minor version 0
|
||||
EXPECT_EQ(0x00, buffer[11]);
|
||||
// Year
|
||||
EXPECT_NE(0x00, buffer[13]);
|
||||
// Day
|
||||
EXPECT_NE(0x00, buffer[14]);
|
||||
vector<uint8_t>& buffer = controller.GetBuffer();
|
||||
// Major version 1
|
||||
EXPECT_EQ(0x01, buffer[10]);
|
||||
// Minor version 0
|
||||
EXPECT_EQ(0x00, buffer[11]);
|
||||
// Year
|
||||
EXPECT_NE(0x00, buffer[13]);
|
||||
// Day
|
||||
EXPECT_NE(0x00, buffer[14]);
|
||||
|
||||
// ALLOCATION LENGTH
|
||||
cmd[8] = 2;
|
||||
|
|
|
@ -60,8 +60,39 @@ class MockBus : public BUS // NOSONAR Having many fields/methods cannot be avoid
|
|||
MOCK_METHOD(bool, GetSignal, (int), (const override));
|
||||
MOCK_METHOD(void, SetSignal, (int, bool), (override));
|
||||
|
||||
MockBus() = default;
|
||||
~MockBus() override = default;
|
||||
MOCK_METHOD(bool, Init, (mode_e), (override));
|
||||
MOCK_METHOD(void, Reset, (), (override));
|
||||
MOCK_METHOD(void, Cleanup, (), (override));
|
||||
MOCK_METHOD(bool, GetBSY, (), (const override));
|
||||
MOCK_METHOD(void, SetBSY, (bool), (override));
|
||||
MOCK_METHOD(bool, GetSEL, (), (const override));
|
||||
MOCK_METHOD(void, SetSEL, (bool), (override));
|
||||
MOCK_METHOD(bool, GetATN, (), (const override));
|
||||
MOCK_METHOD(void, SetATN, (bool), (override));
|
||||
MOCK_METHOD(bool, GetACK, (), (const override));
|
||||
MOCK_METHOD(void, SetACK, (bool), (override));
|
||||
MOCK_METHOD(bool, GetRST, (), (const override));
|
||||
MOCK_METHOD(void, SetRST, (bool), (override));
|
||||
MOCK_METHOD(bool, GetMSG, (), (const override));
|
||||
MOCK_METHOD(void, SetMSG, (bool), (override));
|
||||
MOCK_METHOD(bool, GetCD, (), (const override));
|
||||
MOCK_METHOD(void, SetCD, (bool), (override));
|
||||
MOCK_METHOD(bool, GetIO, (), (override));
|
||||
MOCK_METHOD(void, SetIO, (bool), (override));
|
||||
MOCK_METHOD(bool, GetREQ, (), (const override));
|
||||
MOCK_METHOD(void, SetREQ, (bool), (override));
|
||||
MOCK_METHOD(uint8_t, GetDAT, (), (override));
|
||||
MOCK_METHOD(void, SetDAT, (uint8_t), (override));
|
||||
MOCK_METHOD(bool, GetDP, (), (const override));
|
||||
MOCK_METHOD(uint32_t, Acquire, (), (override));
|
||||
MOCK_METHOD(int, CommandHandShake, (uint8_t *), (override));
|
||||
MOCK_METHOD(int, ReceiveHandShake, (uint8_t *, int), (override));
|
||||
MOCK_METHOD(int, SendHandShake, (uint8_t *, int, int), (override));
|
||||
MOCK_METHOD(bool, GetSignal, (int), (const override));
|
||||
MOCK_METHOD(void, SetSignal, (int, bool), (override));
|
||||
|
||||
MockBus() = default;
|
||||
~MockBus() override = default;
|
||||
};
|
||||
|
||||
class MockPhaseHandler : public PhaseHandler
|
||||
|
@ -95,7 +126,8 @@ class MockAbstractController : public AbstractController // NOSONAR Having many
|
|||
FRIEND_TEST(AbstractControllerTest, ExtractInitiatorId);
|
||||
FRIEND_TEST(AbstractControllerTest, GetOpcode);
|
||||
FRIEND_TEST(AbstractControllerTest, GetLun);
|
||||
FRIEND_TEST(AbstractControllerTest, SetLength);
|
||||
FRIEND_TEST(AbstractControllerTest, Blocks);
|
||||
FRIEND_TEST(AbstractControllerTest, Length);
|
||||
FRIEND_TEST(AbstractControllerTest, UpdateOffsetAndLength);
|
||||
FRIEND_TEST(AbstractControllerTest, Offset);
|
||||
FRIEND_TEST(PrimaryDeviceTest, Inquiry);
|
||||
|
@ -122,7 +154,8 @@ class MockAbstractController : public AbstractController // NOSONAR Having many
|
|||
FRIEND_TEST(DiskTest, Write16);
|
||||
FRIEND_TEST(DiskTest, Verify10);
|
||||
FRIEND_TEST(DiskTest, Verify16);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity10);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity16);
|
||||
FRIEND_TEST(DiskTest, ReadLong10);
|
||||
FRIEND_TEST(DiskTest, ReadLong16);
|
||||
FRIEND_TEST(DiskTest, WriteLong10);
|
||||
|
@ -168,6 +201,7 @@ class MockAbstractController : public AbstractController // NOSONAR Having many
|
|||
|
||||
// Permit access to all tests without the need for numerous FRIEND_TEST
|
||||
vector<int>& GetCmd() { return AbstractController::GetCmd(); } //NOSONAR Hides function on purpose
|
||||
shared_ptr<BUS> GetBus() { return AbstractController::GetBus(); } //NOSONAR Hides function on purpose
|
||||
};
|
||||
|
||||
class MockScsiController : public ScsiController
|
||||
|
@ -196,8 +230,9 @@ class MockScsiController : public ScsiController
|
|||
MOCK_METHOD(void, Execute, (), ());
|
||||
|
||||
using ScsiController::ScsiController;
|
||||
explicit MockScsiController(shared_ptr<NiceMock<MockBus>> bus, int target_id) : ScsiController(bus, target_id) {}
|
||||
explicit MockScsiController(shared_ptr<MockBus> bus, int target_id) : ScsiController(bus, target_id) {}
|
||||
MockScsiController(shared_ptr<MockBus> bus) : ScsiController(bus, 0) {}
|
||||
explicit MockScsiController(shared_ptr<MockBus> bus) : ScsiController(bus, 0) {}
|
||||
~MockScsiController() override = default;
|
||||
|
||||
};
|
||||
|
@ -253,8 +288,9 @@ class MockModePageDevice : public ModePageDevice
|
|||
MOCK_METHOD(int, ModeSense6, (const vector<int> &, vector<BYTE> &), (const override));
|
||||
MOCK_METHOD(int, ModeSense10, (const vector<int> &, vector<BYTE> &), (const override));
|
||||
|
||||
explicit MockModePageDevice() : ModePageDevice("test", 0) {}
|
||||
~MockModePageDevice() override = default;
|
||||
MOCK_METHOD(vector<byte>, InquiryInternal, (), (const));
|
||||
MOCK_METHOD(int, ModeSense6, (const vector<int>&, vector<uint8_t>&), (const override));
|
||||
MOCK_METHOD(int, ModeSense10, (const vector<int>&, vector<uint8_t>&), (const override));
|
||||
|
||||
MockModePageDevice() : ModePageDevice(UNDEFINED, 0) {}
|
||||
~MockModePageDevice() override = default;
|
||||
|
@ -296,8 +332,8 @@ public:
|
|||
|
||||
MOCK_METHOD(vector<byte>, InquiryInternal, (), (const));
|
||||
MOCK_METHOD(void, Open, (), (override));
|
||||
MOCK_METHOD(int, ModeSense6, (const vector<int>&, vector<BYTE>&), (const override));
|
||||
MOCK_METHOD(int, ModeSense10, (const vector<int>&, vector<BYTE>&), (const override));
|
||||
MOCK_METHOD(int, ModeSense6, (const vector<int>&, vector<uint8_t>&), (const override));
|
||||
MOCK_METHOD(int, ModeSense10, (const vector<int>&, vector<uint8_t>&), (const override));
|
||||
MOCK_METHOD(void, SetUpModePages, ((map<int, vector<byte>>&), int, bool), (const override));
|
||||
|
||||
MockStorageDevice() : StorageDevice(UNDEFINED, 0) {}
|
||||
|
@ -320,7 +356,8 @@ class MockDisk : public Disk
|
|||
FRIEND_TEST(DiskTest, Write16);
|
||||
FRIEND_TEST(DiskTest, Verify10);
|
||||
FRIEND_TEST(DiskTest, Verify16);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity10);
|
||||
FRIEND_TEST(DiskTest, ReadCapacity16);
|
||||
FRIEND_TEST(DiskTest, ReadLong10);
|
||||
FRIEND_TEST(DiskTest, ReadLong16);
|
||||
FRIEND_TEST(DiskTest, WriteLong10);
|
||||
|
|
|
@ -26,32 +26,40 @@ TEST(ModePageDeviceTest, SupportsSaveParameters)
|
|||
|
||||
TEST(ModePageDeviceTest, AddModePages)
|
||||
{
|
||||
vector<int> cdb(6);
|
||||
vector<BYTE> buf(512);
|
||||
MockModePageDevice device;
|
||||
vector<int> cdb(6);
|
||||
vector<uint8_t> buf(512);
|
||||
MockModePageDevice device;
|
||||
|
||||
// Page 0
|
||||
cdb[2] = 0x00;
|
||||
EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12, 255), scsi_exception)
|
||||
EXPECT_THAT([&] { device.AddModePages(cdb, buf, 0, 12, 255); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Data were returned for non-existing mode page 0";
|
||||
|
||||
// All pages, non changeable
|
||||
cdb[2] = 0x3f;
|
||||
EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, 0, 255));
|
||||
EXPECT_EQ(3, device.AddModePages(cdb, buf, 0, 3, 255));
|
||||
EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12, -1), scsi_exception) << "Maximum size was ignored";
|
||||
EXPECT_THAT([&] { device.AddModePages(cdb, buf, 0, 12, -1); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Maximum size was ignored";
|
||||
|
||||
// All pages, changeable
|
||||
cdb[2]= 0x7f;
|
||||
EXPECT_EQ(0, device.AddModePages(cdb, buf, 0, 0, 255));
|
||||
EXPECT_EQ(3, device.AddModePages(cdb, buf, 0, 3, 255));
|
||||
EXPECT_THROW(device.AddModePages(cdb, buf, 0, 12, -1), scsi_exception) << "Maximum size was ignored";
|
||||
EXPECT_THAT([&] { device.AddModePages(cdb, buf, 0, 12, -1); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Maximum size was ignored";
|
||||
}
|
||||
|
||||
TEST(ModePageDeviceTest, Page0)
|
||||
{
|
||||
vector<int> cdb(6);
|
||||
vector<BYTE> buf(512);
|
||||
vector<uint8_t> buf(512);
|
||||
MockPage0ModePageDevice device;
|
||||
|
||||
cdb[2] = 0x3f;
|
||||
|
@ -104,13 +112,17 @@ TEST(ModePageDeviceTest, ModeSense10)
|
|||
|
||||
TEST(ModePageDeviceTest, ModeSelect)
|
||||
{
|
||||
MockModePageDevice device;
|
||||
vector<int> cmd;
|
||||
vector<BYTE> buf;
|
||||
MockModePageDevice device;
|
||||
vector<int> cmd;
|
||||
vector<uint8_t> buf;
|
||||
|
||||
EXPECT_THROW(device.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 0), scsi_exception)
|
||||
EXPECT_THAT([&] { device.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 0); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))))
|
||||
<< "Unexpected MODE SELECT(6) default implementation";
|
||||
EXPECT_THROW(device.ModeSelect(scsi_command::eCmdModeSelect10, cmd, buf, 0), scsi_exception)
|
||||
EXPECT_THAT([&] { device.ModeSelect(scsi_command::eCmdModeSelect10, cmd, buf, 0); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))))
|
||||
<< "Unexpected MODE SELECT(10) default implementation";
|
||||
}
|
||||
|
||||
|
@ -127,8 +139,10 @@ TEST(ModePageDeviceTest, ModeSelect6)
|
|||
EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect6));
|
||||
|
||||
cmd[1] = 0x01;
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdModeSelect6), scsi_exception)
|
||||
<< "Saving parameters is not supported for most device types";
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdModeSelect6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Saving parameters is not supported by base class";
|
||||
}
|
||||
|
||||
TEST(ModePageDeviceTest, ModeSelect10)
|
||||
|
@ -144,6 +158,8 @@ TEST(ModePageDeviceTest, ModeSelect10)
|
|||
EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect10));
|
||||
|
||||
cmd[1] = 0x01;
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdModeSelect10), scsi_exception)
|
||||
<< "Saving parameters is not supported for most device types";
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdModeSelect10); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Saving parameters is not supported for by base class";
|
||||
}
|
||||
|
|
|
@ -137,29 +137,39 @@ TEST(PrimaryDeviceTest, TestUnitReady)
|
|||
|
||||
controller.AddDevice(device);
|
||||
|
||||
device->SetReset(true);
|
||||
device->SetAttn(true);
|
||||
device->SetReady(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
device->SetReset(true);
|
||||
device->SetAttn(true);
|
||||
device->SetReady(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION),
|
||||
Property(&scsi_exception::get_asc, asc::POWER_ON_OR_RESET))));
|
||||
|
||||
device->SetReset(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
device->SetReset(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION),
|
||||
Property(&scsi_exception::get_asc, asc::NOT_READY_TO_READY_CHANGE))));
|
||||
|
||||
device->SetReset(true);
|
||||
device->SetAttn(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
device->SetReset(true);
|
||||
device->SetAttn(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION),
|
||||
Property(&scsi_exception::get_asc, asc::POWER_ON_OR_RESET))));
|
||||
|
||||
device->SetReset(false);
|
||||
device->SetAttn(true);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
device->SetReset(false);
|
||||
device->SetAttn(true);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION),
|
||||
Property(&scsi_exception::get_asc, asc::NOT_READY_TO_READY_CHANGE))));
|
||||
|
||||
device->SetAttn(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdTestUnitReady), scsi_exception);
|
||||
device->SetAttn(false);
|
||||
EXPECT_CALL(controller, DataIn()).Times(0);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))));
|
||||
|
||||
device->SetReady(true);
|
||||
EXPECT_CALL(controller, Status());
|
||||
|
@ -212,11 +222,17 @@ TEST(PrimaryDeviceTest, Inquiry)
|
|||
|
||||
cmd[1] = 0x01;
|
||||
EXPECT_CALL(*controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdInquiry), scsi_exception) << "EVPD bit is not supported";
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdInquiry); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "EVPD bit is not supported";
|
||||
|
||||
cmd[2] = 0x01;
|
||||
EXPECT_CALL(*controller, DataIn()).Times(0);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdInquiry), scsi_exception) << "PAGE CODE field is not supported";
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdInquiry); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "PAGE CODE field is not supported";
|
||||
|
||||
cmd[1] = 0x00;
|
||||
cmd[2] = 0x00;
|
||||
|
@ -240,8 +256,10 @@ TEST(PrimaryDeviceTest, RequestSense)
|
|||
// ALLOCATION LENGTH
|
||||
cmd[4] = 255;
|
||||
|
||||
device->SetReady(false);
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdRequestSense), scsi_exception);
|
||||
device->SetReady(false);
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdRequestSense); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))));
|
||||
|
||||
device->SetReady(true);
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
|
@ -263,16 +281,22 @@ TEST(PrimaryDeviceTest, SendDiagnostic)
|
|||
EXPECT_EQ(status::GOOD, controller.GetStatus());
|
||||
|
||||
cmd[1] = 0x10;
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdSendDiag), scsi_exception)
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "SEND DIAGNOSTIC must fail because PF bit is not supported";
|
||||
cmd[1] = 0;
|
||||
|
||||
cmd[3] = 1;
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdSendDiag), scsi_exception)
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "SEND DIAGNOSTIC must fail because parameter list is not supported";
|
||||
cmd[3] = 0;
|
||||
cmd[4] = 1;
|
||||
EXPECT_THROW(device->Dispatch(scsi_command::eCmdSendDiag), scsi_exception)
|
||||
EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "SEND DIAGNOSTIC must fail because parameter list is not supported";
|
||||
}
|
||||
|
||||
|
@ -296,7 +320,7 @@ TEST(PrimaryDeviceTest, ReportLuns)
|
|||
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(device1->Dispatch(scsi_command::eCmdReportLuns));
|
||||
const vector<BYTE>& buffer = controller.GetBuffer();
|
||||
const vector<uint8_t>& buffer = controller.GetBuffer();
|
||||
EXPECT_EQ(0x00, buffer[0]) << "Wrong data length";
|
||||
EXPECT_EQ(0x00, buffer[1]) << "Wrong data length";
|
||||
EXPECT_EQ(0x00, buffer[2]) << "Wrong data length";
|
||||
|
@ -318,9 +342,11 @@ TEST(PrimaryDeviceTest, ReportLuns)
|
|||
EXPECT_EQ(0x00, buffer[22]) << "Wrong LUN2 number";
|
||||
EXPECT_EQ(LUN2, buffer[23]) << "Wrong LUN2 number";
|
||||
|
||||
cmd[2] = 0x01;
|
||||
EXPECT_THROW(device1->Dispatch(scsi_command::eCmdReportLuns), scsi_exception)
|
||||
<< "Only SELECT REPORT mode 0 is supported";
|
||||
cmd[2] = 0x01;
|
||||
EXPECT_THAT([&] { device1->Dispatch(scsi_command::eCmdReportLuns); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Only SELECT REPORT mode 0 is supported";
|
||||
}
|
||||
|
||||
TEST(PrimaryDeviceTest, UnknownCommand)
|
||||
|
@ -345,8 +371,8 @@ TEST(PrimaryDeviceTest, Dispatch)
|
|||
|
||||
TEST(PrimaryDeviceTest, WriteByteSequence)
|
||||
{
|
||||
vector<BYTE> data;
|
||||
MockPrimaryDevice device(0);
|
||||
vector<uint8_t> data;
|
||||
MockPrimaryDevice device(0);
|
||||
|
||||
EXPECT_FALSE(device.WriteByteSequence(data, 0)) << "Primary device does not support writing byte sequences";
|
||||
}
|
||||
|
|
|
@ -39,10 +39,10 @@ TEST_F(RascsiExecutorTest, ProcessDeviceCmd)
|
|||
const int ID = 3;
|
||||
const int LUN = 0;
|
||||
|
||||
shared_ptr<MockBus> bus_ptr = make_shared<MockBus>();
|
||||
auto bus = make_shared<MockBus>();
|
||||
DeviceFactory device_factory;
|
||||
MockAbstractController controller(bus_ptr, ID);
|
||||
ControllerManager controller_manager(bus_ptr);
|
||||
MockAbstractController controller(bus, ID);
|
||||
ControllerManager controller_manager(bus);
|
||||
RascsiImage rascsi_image;
|
||||
RascsiResponse rascsi_response(device_factory, controller_manager, 32);
|
||||
auto executor = make_shared<MockRascsiExecutor>(rascsi_response, rascsi_image, device_factory, controller_manager);
|
||||
|
@ -489,10 +489,10 @@ TEST_F(RascsiExecutorTest, ValidateImageFile)
|
|||
|
||||
string full_path;
|
||||
auto device = dynamic_pointer_cast<StorageDevice>(device_factory.CreateDevice(controller_manager, SCHD, 0, "test"));
|
||||
EXPECT_TRUE(executor.ValidateImageFile(context, device, "", full_path));
|
||||
EXPECT_TRUE(executor.ValidateImageFile(context, *device, "", full_path));
|
||||
EXPECT_TRUE(full_path.empty());
|
||||
|
||||
EXPECT_FALSE(executor.ValidateImageFile(context, device, "/non_existing_file", full_path));
|
||||
EXPECT_FALSE(executor.ValidateImageFile(context, *device, "/non_existing_file", full_path));
|
||||
EXPECT_TRUE(full_path.empty());
|
||||
}
|
||||
|
||||
|
@ -589,47 +589,47 @@ TEST_F(RascsiExecutorTest, ValidateOperationAgainstDevice)
|
|||
|
||||
auto device = make_shared<MockPrimaryDevice>(0);
|
||||
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, ATTACH));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, DETACH));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, ATTACH));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, DETACH));
|
||||
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, START));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, STOP));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, INSERT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, UNPROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, START));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, STOP));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, INSERT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, UNPROTECT));
|
||||
|
||||
device->SetStoppable(true);
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, STOP));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, INSERT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, UNPROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, STOP));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, INSERT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, UNPROTECT));
|
||||
|
||||
device->SetRemovable(true);
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, UNPROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, UNPROTECT));
|
||||
|
||||
device->SetProtectable(true);
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, device, UNPROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, EJECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, PROTECT));
|
||||
EXPECT_FALSE(executor.ValidateOperationAgainstDevice(context, *device, UNPROTECT));
|
||||
|
||||
device->SetReady(true);
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, EJECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, PROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, device, UNPROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, START));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, STOP));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, INSERT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, EJECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, PROTECT));
|
||||
EXPECT_TRUE(executor.ValidateOperationAgainstDevice(context, *device, UNPROTECT));
|
||||
}
|
||||
|
||||
TEST_F(RascsiExecutorTest, ValidateIdAndLun)
|
||||
|
@ -661,26 +661,26 @@ TEST_F(RascsiExecutorTest, SetProductData)
|
|||
|
||||
auto device = make_shared<MockPrimaryDevice>(0);
|
||||
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
|
||||
definition.set_vendor("123456789");
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_vendor("1");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_vendor("12345678");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
|
||||
definition.set_product("12345678901234567");
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_product("1");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_product("1234567890123456");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
|
||||
definition.set_revision("12345");
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_FALSE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_revision("1");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
definition.set_revision("1234");
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, device));
|
||||
EXPECT_TRUE(executor.SetProductData(context, definition, *device));
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@ TEST(ScsiCommandUtilTest, ModeSelect6)
|
|||
const int LENGTH = 26;
|
||||
|
||||
vector<int> cdb(6);
|
||||
vector<BYTE> buf(LENGTH);
|
||||
vector<uint8_t> buf(LENGTH);
|
||||
|
||||
// PF (vendor-specific parameter format)
|
||||
cdb[1] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 0), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 0); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Vendor-specific parameters are not supported";
|
||||
|
||||
cdb[0] = 0x15;
|
||||
|
@ -33,22 +35,30 @@ TEST(ScsiCommandUtilTest, ModeSelect6)
|
|||
buf[9] = 0x00;
|
||||
buf[10] = 0x02;
|
||||
buf[11] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 256), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 256); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Requested sector size does not match current sector size";
|
||||
|
||||
// Page 0
|
||||
buf[12] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Unsupported page 0 was not rejected";
|
||||
|
||||
// Page 3 (Format Device Page)
|
||||
buf[12] = 0x03;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Requested sector size does not match current sector size";
|
||||
|
||||
// Match the requested to the current sector size
|
||||
buf[24] = 0x02;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH - 1, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH - 1, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Not enough command parameters";
|
||||
|
||||
ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512);
|
||||
|
@ -59,11 +69,13 @@ TEST(ScsiCommandUtilTest, ModeSelect10)
|
|||
const int LENGTH = 30;
|
||||
|
||||
vector<int> cdb(10);
|
||||
vector<BYTE> buf(LENGTH);
|
||||
vector<uint8_t> buf(LENGTH);
|
||||
|
||||
// PF (vendor-specific parameter format)
|
||||
cdb[1] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 0), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 0); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Vendor-specific parameters are not supported";
|
||||
|
||||
// PF (standard parameter format)
|
||||
|
@ -72,22 +84,30 @@ TEST(ScsiCommandUtilTest, ModeSelect10)
|
|||
buf[13] = 0x00;
|
||||
buf[14] = 0x02;
|
||||
buf[15] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 256), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 256); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Requested sector size does not match current sector size";
|
||||
|
||||
// Page 0
|
||||
buf[16] = 0x00;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Unsupported page 0 was not rejected";
|
||||
|
||||
// Page 3 (Format Device Page)
|
||||
buf[16] = 0x03;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Requested sector size does not match current sector size";
|
||||
|
||||
// Match the requested to the current sector size
|
||||
buf[28] = 0x02;
|
||||
EXPECT_THROW(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH - 1, 512), scsi_exception)
|
||||
EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH - 1, 512); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST))))
|
||||
<< "Not enough command parameters";
|
||||
|
||||
ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512);
|
||||
|
@ -129,7 +149,7 @@ TEST(ScsiCommandUtilTest, AddAppleVendorModePage)
|
|||
|
||||
TEST(ScsiCommandUtilTest, GetInt16)
|
||||
{
|
||||
vector<BYTE> b = { 0xfe, 0xdc };
|
||||
vector<uint8_t> b = { 0xfe, 0xdc };
|
||||
EXPECT_EQ(0xfedc, GetInt16(b, 0));
|
||||
|
||||
vector<int> v = { 0x12, 0x34 };
|
||||
|
@ -164,7 +184,7 @@ TEST(ScsiCommandUtilTest, SetInt16)
|
|||
|
||||
TEST(ScsiCommandUtilTest, SetInt32)
|
||||
{
|
||||
vector<BYTE> buf(4);
|
||||
vector<uint8_t> buf(4);
|
||||
SetInt32(buf, 0, 0x12345678);
|
||||
EXPECT_EQ(0x12, buf[0]);
|
||||
EXPECT_EQ(0x34, buf[1]);
|
||||
|
@ -181,7 +201,7 @@ TEST(ScsiCommandUtilTest, SetInt32)
|
|||
|
||||
TEST(ScsiCommandUtilTest, SetInt64)
|
||||
{
|
||||
vector<BYTE> buf(8);
|
||||
vector<uint8_t> buf(8);
|
||||
SetInt64(buf, 0, 0x1234567887654321);
|
||||
EXPECT_EQ(0x12, buf[0]);
|
||||
EXPECT_EQ(0x34, buf[1]);
|
||||
|
|
|
@ -19,7 +19,7 @@ TEST(ScsiControllerTest, GetInitiatorId)
|
|||
{
|
||||
const int ID = 2;
|
||||
|
||||
MockScsiController controller(make_shared<MockBus>());
|
||||
MockScsiController controller(make_shared<NiceMock<MockBus>>());
|
||||
|
||||
controller.Process(ID);
|
||||
EXPECT_EQ(ID, controller.GetInitiatorId());
|
||||
|
@ -56,7 +56,7 @@ TEST(ScsiControllerTest, Process)
|
|||
|
||||
TEST(ScsiControllerTest, BusFree)
|
||||
{
|
||||
MockScsiController controller(make_shared<MockBus>());
|
||||
MockScsiController controller(make_shared<NiceMock<MockBus>>());
|
||||
|
||||
controller.SetPhase(BUS::phase_t::busfree);
|
||||
controller.BusFree();
|
||||
|
@ -87,7 +87,7 @@ TEST(ScsiControllerTest, BusFree)
|
|||
|
||||
TEST(ScsiControllerTest, Selection)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::selection);
|
||||
|
@ -100,6 +100,7 @@ TEST(ScsiControllerTest, Selection)
|
|||
ON_CALL(*bus, GetSEL).WillByDefault(Return(true));
|
||||
ON_CALL(*bus, GetBSY).WillByDefault(Return(false));
|
||||
EXPECT_CALL(*bus, GetATN).Times(0);
|
||||
EXPECT_CALL(controller, Status);
|
||||
controller.Selection();
|
||||
EXPECT_EQ(BUS::phase_t::selection, controller.GetPhase());
|
||||
|
||||
|
@ -142,10 +143,11 @@ TEST(ScsiControllerTest, Selection)
|
|||
|
||||
TEST(ScsiControllerTest, Command)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::command);
|
||||
EXPECT_CALL(controller, Status);
|
||||
controller.Command();
|
||||
EXPECT_EQ(BUS::phase_t::command, controller.GetPhase());
|
||||
|
||||
|
@ -168,7 +170,7 @@ TEST(ScsiControllerTest, Command)
|
|||
|
||||
TEST(ScsiControllerTest, MsgIn)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
|
@ -183,7 +185,7 @@ TEST(ScsiControllerTest, MsgIn)
|
|||
|
||||
TEST(ScsiControllerTest, MsgOut)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
|
@ -198,7 +200,7 @@ TEST(ScsiControllerTest, MsgOut)
|
|||
|
||||
TEST(ScsiControllerTest, DataIn)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
|
@ -218,7 +220,7 @@ TEST(ScsiControllerTest, DataIn)
|
|||
|
||||
TEST(ScsiControllerTest, DataOut)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
controller.SetPhase(BUS::phase_t::reserved);
|
||||
|
@ -238,7 +240,7 @@ TEST(ScsiControllerTest, DataOut)
|
|||
|
||||
TEST(ScsiControllerTest, Error)
|
||||
{
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto bus = make_shared<NiceMock<MockBus>>();
|
||||
MockScsiController controller(bus, 0);
|
||||
|
||||
ON_CALL(*bus, GetRST).WillByDefault(Return(true));
|
||||
|
@ -281,7 +283,7 @@ TEST(ScsiControllerTest, Error)
|
|||
|
||||
TEST(ScsiControllerTest, RequestSense)
|
||||
{
|
||||
MockScsiController controller(make_shared<MockBus>());
|
||||
MockScsiController controller(make_shared<NiceMock<MockBus>>());
|
||||
auto device = make_shared<MockPrimaryDevice>(0);
|
||||
|
||||
controller.AddDevice(device);
|
||||
|
|
|
@ -22,16 +22,6 @@ TEST(ScsiDaynaportTest, Dispatch)
|
|||
auto daynaport = CreateDevice(SCDP, controller);
|
||||
|
||||
EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class";
|
||||
|
||||
// TODO Remove tests below as soon as Daynaport does not inherit from Disk anymore
|
||||
EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSense6))
|
||||
<< "Non-DaynaPort commands inherited from Disk must not be supported";
|
||||
EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSelect6))
|
||||
<< "Non-DaynaPort commands inherited from Disk must not be supported";
|
||||
EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSense10))
|
||||
<< "Non-DaynaPort commands inherited from Disk must not be supported";
|
||||
EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdModeSelect10))
|
||||
<< "Non-DaynaPort commands inherited from Disk must not be supported";
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, TestUnitReady)
|
||||
|
@ -46,7 +36,7 @@ TEST(ScsiDaynaportTest, TestUnitReady)
|
|||
|
||||
TEST(ScsiDaynaportTest, Read)
|
||||
{
|
||||
vector<BYTE> buf(0);
|
||||
vector<uint8_t> buf(0);
|
||||
NiceMock<MockAbstractController> controller(make_shared<MockBus>(), 0);
|
||||
auto daynaport = dynamic_pointer_cast<SCSIDaynaPort>(CreateDevice(SCDP, controller));
|
||||
|
||||
|
@ -57,18 +47,9 @@ TEST(ScsiDaynaportTest, Read)
|
|||
EXPECT_EQ(0, daynaport->Read(cmd, buf, 0)) << "Trying to read the root sector must fail";
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, WriteCheck)
|
||||
{
|
||||
vector<BYTE> buf(0);
|
||||
NiceMock<MockAbstractController> controller(make_shared<MockBus>(), 0);
|
||||
auto daynaport = dynamic_pointer_cast<SCSIDaynaPort>(CreateDevice(SCDP, controller));
|
||||
|
||||
EXPECT_THROW(daynaport->WriteCheck(0), scsi_exception);
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, WriteBytes)
|
||||
{
|
||||
vector<BYTE> buf(0);
|
||||
vector<uint8_t> buf(0);
|
||||
NiceMock<MockAbstractController> controller(make_shared<MockBus>(), 0);
|
||||
auto daynaport = dynamic_pointer_cast<SCSIDaynaPort>(CreateDevice(SCDP, controller));
|
||||
|
||||
|
@ -87,7 +68,10 @@ TEST(ScsiDaynaportTest, Read6)
|
|||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
cmd[5] = 0xff;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdRead6), scsi_exception) << "Invalid data format";
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdRead6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Invalid data format";
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, Write6)
|
||||
|
@ -98,17 +82,26 @@ TEST(ScsiDaynaportTest, Write6)
|
|||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
cmd[5] = 0x00;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdWrite6), scsi_exception) << "Invalid transfer length";
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdWrite6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Invalid transfer length";
|
||||
|
||||
cmd[3] = -1;
|
||||
cmd[4] = -8;
|
||||
cmd[5] = 0x80;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdWrite6), scsi_exception) << "Invalid transfer length";
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdWrite6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Invalid transfer length";
|
||||
|
||||
cmd[3] = 0;
|
||||
cmd[4] = 0;
|
||||
cmd[5] = 0xff;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdWrite6), scsi_exception) << "Invalid transfer length";
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdWrite6); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Invalid transfer length";
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, TestRetrieveStats)
|
||||
|
@ -131,8 +124,10 @@ TEST(ScsiDaynaportTest, SetInterfaceMode)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
// Unknown interface command
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception);
|
||||
// Unknown interface command
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))));
|
||||
|
||||
// Not implemented, do nothing
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SETMODE;
|
||||
|
@ -144,17 +139,23 @@ TEST(ScsiDaynaportTest, SetInterfaceMode)
|
|||
EXPECT_CALL(controller, DataOut());
|
||||
EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode));
|
||||
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_STATS;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception);
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_STATS;
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))));
|
||||
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_ENABLE;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception);
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_ENABLE;
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))));
|
||||
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SET;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode), scsi_exception);
|
||||
// Not implemented
|
||||
cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SET;
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_COMMAND_OPERATION_CODE))));
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, SetMcastAddr)
|
||||
|
@ -164,7 +165,10 @@ TEST(ScsiDaynaportTest, SetMcastAddr)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdSetMcastAddr), scsi_exception) << "Length of 0 is not supported";
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetMcastAddr); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Length of 0 is not supported";
|
||||
|
||||
cmd[4] = 1;
|
||||
EXPECT_CALL(controller, DataOut());
|
||||
|
@ -178,12 +182,16 @@ TEST(ScsiDaynaportTest, EnableInterface)
|
|||
|
||||
vector<int>& cmd = controller.GetCmd();
|
||||
|
||||
// Enable
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdEnableInterface), scsi_exception);
|
||||
// Enable
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdEnableInterface); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND),
|
||||
Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION))));
|
||||
|
||||
// Disable
|
||||
cmd[5] = 0x80;
|
||||
EXPECT_THROW(daynaport->Dispatch(scsi_command::eCmdEnableInterface), scsi_exception);
|
||||
// Disable
|
||||
cmd[5] = 0x80;
|
||||
EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdEnableInterface); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND),
|
||||
Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION))));
|
||||
}
|
||||
|
||||
TEST(ScsiDaynaportTest, GetSendDelay)
|
||||
|
|
|
@ -91,7 +91,10 @@ TEST(ScsiPrinterTest, Print)
|
|||
|
||||
cmd[3] = 0xff;
|
||||
cmd[4] = 0xff;
|
||||
EXPECT_THROW(printer->Dispatch(scsi_command::eCmdPrint), scsi_exception) << "Buffer overflow was not reported";
|
||||
EXPECT_THAT([&] { printer->Dispatch(scsi_command::eCmdPrint); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST),
|
||||
Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB))))
|
||||
<< "Buffer overflow was not reported";
|
||||
}
|
||||
|
||||
TEST(ScsiPrinterTest, StopPrint)
|
||||
|
@ -109,7 +112,10 @@ TEST(ScsiPrinterTest, SynchronizeBuffer)
|
|||
NiceMock<MockAbstractController> controller(make_shared<MockBus>(), 0);
|
||||
auto printer = CreateDevice(SCLP, controller);
|
||||
|
||||
EXPECT_THROW(printer->Dispatch(scsi_command::eCmdSynchronizeBuffer), scsi_exception) << "Nothing to print";
|
||||
EXPECT_THAT([&] { printer->Dispatch(scsi_command::eCmdSynchronizeBuffer); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND),
|
||||
Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION))))
|
||||
<< "Nothing to print";
|
||||
|
||||
// Further testing would use the printing system
|
||||
}
|
||||
|
@ -119,7 +125,7 @@ TEST(ScsiPrinterTest, WriteByteSequence)
|
|||
NiceMock<MockAbstractController> controller(make_shared<MockBus>(), 0);
|
||||
auto printer = dynamic_pointer_cast<SCSIPrinter>(CreateDevice(SCLP, controller));
|
||||
|
||||
vector<BYTE> buf(1);
|
||||
vector<uint8_t> buf(1);
|
||||
EXPECT_TRUE(printer->WriteByteSequence(buf, buf.size()));
|
||||
printer->Cleanup();
|
||||
}
|
||||
|
|
|
@ -123,7 +123,9 @@ TEST(ScsiCdTest, ReadToc)
|
|||
|
||||
controller.AddDevice(cd);
|
||||
|
||||
EXPECT_THROW(cd->Dispatch(scsi_command::eCmdReadToc), scsi_exception) << "Drive is not ready";
|
||||
EXPECT_THAT([&] { cd->Dispatch(scsi_command::eCmdReadToc); }, Throws<scsi_exception>(AllOf(
|
||||
Property(&scsi_exception::get_sense_key, sense_key::NOT_READY),
|
||||
Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT))));
|
||||
|
||||
// Further testing requires filesystem access
|
||||
}
|
||||
|
|
|
@ -57,14 +57,14 @@ TEST(ScsiHdNecTest, TestAddFormatPage)
|
|||
hd.SetUpModePages(pages, 0x03, false);
|
||||
EXPECT_EQ(1, pages.size()) << "Unexpected number of mode pages";
|
||||
vector<byte>& page_3 = pages[3];
|
||||
EXPECT_EQ(0x80, (int)page_3[0] & 0x80);
|
||||
EXPECT_EQ(0, (int)page_3[20]);
|
||||
EXPECT_EQ(0x80, to_integer<int>(page_3[0]) & 0x80);
|
||||
EXPECT_EQ(0, to_integer<int>(page_3[20]));
|
||||
|
||||
hd.SetRemovable(true);
|
||||
// Non changeable
|
||||
hd.SetUpModePages(pages, 0x03, false);
|
||||
page_3 = pages[3];
|
||||
EXPECT_EQ(0x20, (int)page_3[20]);
|
||||
EXPECT_EQ(0x20, to_integer<int>(page_3[20]));
|
||||
|
||||
pages.clear();
|
||||
// Changeable
|
||||
|
|
|
@ -97,7 +97,7 @@ TEST(ScsiHdTest, ModeSelect)
|
|||
const unordered_set<uint32_t> sector_sizes = { 512 };
|
||||
MockSCSIHD hd(0, sector_sizes, false);
|
||||
vector<int> cmd(10);
|
||||
vector<BYTE> buf(255);
|
||||
vector<uint8_t> buf(255);
|
||||
|
||||
hd.SetSectorSizeInBytes(512);
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ TEST(ScsiMoTest, TestAddVendorPage)
|
|||
EXPECT_EQ(1, pages.size()) << "Unexpected number of mode pages";
|
||||
vector<byte>& page_32 = pages[32];
|
||||
EXPECT_EQ(12, page_32.size());
|
||||
EXPECT_EQ(0, (int)page_32[2]) << "Wrong format mode";
|
||||
EXPECT_EQ(0, (int)page_32[3]) << "Wrong format type";
|
||||
EXPECT_EQ(0, to_integer<int>(page_32[2])) << "Wrong format mode";
|
||||
EXPECT_EQ(0, to_integer<int>(page_32[3])) << "Wrong format type";
|
||||
EXPECT_EQ(0x12345678, GetInt32(page_32, 4)) << "Wrong number of blocks";
|
||||
EXPECT_EQ(0, GetInt16(page_32, 8)) << "Wrong number of spare blocks";
|
||||
EXPECT_EQ(0, GetInt16(page_32, 10));
|
||||
|
@ -116,8 +116,8 @@ TEST(ScsiMoTest, TestAddVendorPage)
|
|||
|
||||
// Changeable page
|
||||
mo.SetUpModePages(pages, 0x20, true);
|
||||
EXPECT_EQ(0, (int)page_32[2]);
|
||||
EXPECT_EQ(0, (int)page_32[3]);
|
||||
EXPECT_EQ(0, to_integer<int>(page_32[2]));
|
||||
EXPECT_EQ(0, to_integer<int>(page_32[3]));
|
||||
EXPECT_EQ(0, GetInt32(page_32, 4));
|
||||
EXPECT_EQ(0, GetInt16(page_32, 8));
|
||||
EXPECT_EQ(0, GetInt16(page_32, 10));
|
||||
|
@ -128,7 +128,7 @@ TEST(ScsiMoTest, ModeSelect)
|
|||
const unordered_set<uint32_t> sector_sizes = { 1024, 2048 };
|
||||
MockSCSIMO mo(0, sector_sizes);
|
||||
vector<int> cmd(10);
|
||||
vector<BYTE> buf(255);
|
||||
vector<uint8_t> buf(255);
|
||||
|
||||
mo.SetSectorSizeInBytes(2048);
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@ using namespace filesystem;
|
|||
shared_ptr<PrimaryDevice> CreateDevice(PbDeviceType type, MockAbstractController& controller, const string& extension)
|
||||
{
|
||||
DeviceFactory device_factory;
|
||||
auto bus = make_shared<MockBus>();
|
||||
auto controller_manager = make_shared<ControllerManager>(bus);
|
||||
auto controller_manager = make_shared<ControllerManager>(controller.GetBus());
|
||||
|
||||
auto device = device_factory.CreateDevice(*controller_manager, type, 0, extension);
|
||||
|
||||
|
@ -41,11 +40,11 @@ void TestInquiry(PbDeviceType type, device_type t, scsi_level l, const string& i
|
|||
cmd[4] = 255;
|
||||
EXPECT_CALL(controller, DataIn());
|
||||
EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry));
|
||||
const vector<BYTE>& buffer = controller.GetBuffer();
|
||||
EXPECT_EQ((int)t, buffer[0]);
|
||||
const vector<uint8_t>& buffer = controller.GetBuffer();
|
||||
EXPECT_EQ(t, static_cast<device_type>(buffer[0]));
|
||||
EXPECT_EQ(removable ? 0x80: 0x00, buffer[1]);
|
||||
EXPECT_EQ((int)l, buffer[2]);
|
||||
EXPECT_EQ((int)l > (int)scsi_level::SCSI_2 ? (int)scsi_level::SCSI_2 : (int)l, buffer[3]);
|
||||
EXPECT_EQ(l, static_cast<scsi_level>(buffer[2]));
|
||||
EXPECT_EQ(l > scsi_level::SCSI_2 ? scsi_level::SCSI_2 : l, static_cast<scsi_level>(buffer[3]));
|
||||
EXPECT_EQ(additional_length, buffer[4]);
|
||||
string product_data;
|
||||
if (ident.size() == 24) {
|
||||
|
@ -93,15 +92,15 @@ path CreateTempFile(int size)
|
|||
|
||||
int GetInt16(const vector<byte>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 1);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 1);
|
||||
|
||||
return ((int)buf[offset] << 8) | (int)buf[offset + 1];
|
||||
return (to_integer<int>(buf[offset]) << 8) | to_integer<int>(buf[offset + 1]);
|
||||
}
|
||||
|
||||
uint32_t GetInt32(const vector<byte>& buf, int offset)
|
||||
{
|
||||
assert(buf.size() > (size_t)offset + 3);
|
||||
assert(buf.size() > static_cast<size_t>(offset) + 3);
|
||||
|
||||
return ((uint32_t)buf[offset] << 24) | ((uint32_t)buf[offset + 1] << 16) |
|
||||
((uint32_t)buf[offset + 2] << 8) | (uint32_t)buf[offset + 3];
|
||||
return (to_integer<uint32_t>(buf[offset]) << 24) | (to_integer<uint32_t>(buf[offset + 1]) << 16) |
|
||||
(to_integer<uint32_t>(buf[offset + 2]) << 8) | to_integer<uint32_t>(buf[offset + 3]);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ RUN ./easyinstall.sh --run_choice=11
|
|||
RUN ./easyinstall.sh --run_choice=13
|
||||
|
||||
# Setup wired network bridge
|
||||
RUN ./easyinstall.sh --run_choice=6 --headless
|
||||
RUN ./easyinstall.sh --run_choice=5 --headless
|
||||
|
||||
USER root
|
||||
WORKDIR /home/pi
|
||||
|
|
283
easyinstall.sh
283
easyinstall.sh
|
@ -58,13 +58,13 @@ PYTHON_COMMON_PATH="$BASE/python/common"
|
|||
SYSTEMD_PATH="/etc/systemd/system"
|
||||
SSL_CERTS_PATH="/etc/ssl/certs"
|
||||
SSL_KEYS_PATH="/etc/ssl/private"
|
||||
HFS_FORMAT=/usr/bin/hformat
|
||||
HFDISK_BIN=/usr/bin/hfdisk
|
||||
LIDO_DRIVER=$BASE/lido-driver.img
|
||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
GIT_REMOTE=${GIT_REMOTE:-origin}
|
||||
TOKEN=""
|
||||
SECRET_FILE="$HOME/.config/rascsi/rascsi_secret"
|
||||
FILE_SHARE_PATH="$HOME/shared_files"
|
||||
FILE_SHARE_NAME="Pi File Server"
|
||||
|
||||
set -e
|
||||
|
||||
|
@ -106,7 +106,10 @@ function installPackages() {
|
|||
unar \
|
||||
disktype \
|
||||
libgmock-dev \
|
||||
man2html
|
||||
man2html \
|
||||
hfsutils \
|
||||
dosfstools \
|
||||
kpartx
|
||||
}
|
||||
|
||||
# install Debian packges for RaSCSI standalone
|
||||
|
@ -593,98 +596,30 @@ function createDriveCustom() {
|
|||
createDrive "$driveSize" "$driveName"
|
||||
}
|
||||
|
||||
# Creates an HFS file system
|
||||
function formatDrive() {
|
||||
diskPath="$1"
|
||||
volumeName="$2"
|
||||
|
||||
if [ ! -x $HFS_FORMAT ]; then
|
||||
# Install hfsutils to have hformat to format HFS
|
||||
sudo apt-get install hfsutils --assume-yes </dev/null
|
||||
fi
|
||||
|
||||
if [ ! -x $HFDISK_BIN ]; then
|
||||
# Clone, compile and install 'hfdisk', partition tool
|
||||
git clone git://www.codesrc.com/git/hfdisk.git
|
||||
cd hfdisk || exit 1
|
||||
# Clone, compile and install 'hfdisk', partition tool
|
||||
function installHfdisk() {
|
||||
HFDISK_VERSION="2022.11"
|
||||
if [ ! -x "$HFDISK_BIN" ]; then
|
||||
cd "$BASE" || exit 1
|
||||
wget -O "hfdisk-$HFDISK_VERSION.tar.gz" "https://github.com/rdmark/hfdisk/archive/refs/tags/$HFDISK_VERSION.tar.gz" </dev/null
|
||||
tar -xzvf "hfdisk-$HFDISK_VERSION.tar.gz"
|
||||
rm "hfdisk-$HFDISK_VERSION.tar.gz"
|
||||
cd "hfdisk-$HFDISK_VERSION" || exit 1
|
||||
make
|
||||
|
||||
sudo cp hfdisk /usr/bin/hfdisk
|
||||
fi
|
||||
sudo cp hfdisk "$HFDISK_BIN"
|
||||
|
||||
# Inject hfdisk commands to create Drive with correct partitions
|
||||
# https://www.codesrc.com/mediawiki/index.php/HFSFromScratch
|
||||
# i initialize partition map
|
||||
# continue with default first block
|
||||
# C Create 1st partition with type specified next)
|
||||
# continue with default
|
||||
# 32 32 blocks (required for HFS+)
|
||||
# Driver_Partition Partition Name
|
||||
# Apple_Driver Partition Type (available types: Apple_Driver, Apple_Driver43, Apple_Free, Apple_HFS...)
|
||||
# C Create 2nd partition with type specified next
|
||||
# continue with default first block
|
||||
# continue with default block size (rest of the disk)
|
||||
# ${volumeName} Partition name provided by user
|
||||
# Apple_HFS Partition Type
|
||||
# w Write partition map to disk
|
||||
# y Confirm partition table
|
||||
# p Print partition map
|
||||
(echo i; echo ; echo C; echo ; echo 32; echo "Driver_Partition"; echo "Apple_Driver"; echo C; echo ; echo ; echo "${volumeName}"; echo "Apple_HFS"; echo w; echo y; echo p;) | $HFDISK_BIN "$diskPath"
|
||||
partitionOk=$?
|
||||
|
||||
if [ $partitionOk -eq 0 ]; then
|
||||
if [ ! -f "$LIDO_DRIVER" ];then
|
||||
echo "Lido driver couldn't be found. Make sure RaSCSI is up-to-date with git pull"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Burn Lido driver to the disk
|
||||
dd if="$LIDO_DRIVER" of="$diskPath" seek=64 count=32 bs=512 conv=notrunc
|
||||
|
||||
driverInstalled=$?
|
||||
if [ $driverInstalled -eq 0 ]; then
|
||||
# Format the partition with HFS file system
|
||||
$HFS_FORMAT -l "${volumeName}" "$diskPath" 1
|
||||
hfsFormattedOk=$?
|
||||
if [ $hfsFormattedOk -eq 0 ]; then
|
||||
echo "Disk created with success."
|
||||
else
|
||||
echo "Unable to format HFS partition."
|
||||
return 4
|
||||
fi
|
||||
else
|
||||
echo "Unable to install Lido Driver."
|
||||
return 3
|
||||
fi
|
||||
else
|
||||
echo "Unable to create the partition."
|
||||
return 2
|
||||
echo "Installed $HFDISK_BIN"
|
||||
fi
|
||||
}
|
||||
|
||||
# Creates an image file
|
||||
function createDrive() {
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "To create a Drive, volume size and volume name must be provided"
|
||||
echo "$ createDrive 600 \"RaSCSI Drive\""
|
||||
echo "Drive wasn't created."
|
||||
return
|
||||
fi
|
||||
|
||||
driveSize=$1
|
||||
driveName=$2
|
||||
mkdir -p "$VIRTUAL_DRIVER_PATH"
|
||||
drivePath="${VIRTUAL_DRIVER_PATH}/${driveSize}M.hda"
|
||||
|
||||
if [ ! -f "$drivePath" ]; then
|
||||
echo "Creating a ${driveSize}MiB Drive"
|
||||
truncate --size "${driveSize}m" "$drivePath"
|
||||
|
||||
echo "Formatting drive with HFS"
|
||||
formatDrive "$drivePath" "$driveName"
|
||||
|
||||
else
|
||||
echo "Error: drive already exists"
|
||||
# Fetch HFS drivers that the Web Interface uses
|
||||
function fetchHardDiskDrivers() {
|
||||
if [ ! -f "$BASE/mac-hard-disk-drivers" ]; then
|
||||
cd "$BASE" || exit 1
|
||||
wget https://macintoshgarden.org/sites/macintoshgarden.org/files/apps/mac-hard-disk-drivers.zip
|
||||
unzip -d mac-hard-disk-drivers mac-hard-disk-drivers.zip
|
||||
rm mac-hard-disk-drivers.zip
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -837,14 +772,12 @@ function setupWirelessNetworking() {
|
|||
# Downloads, compiles, and installs Netatalk (AppleShare server)
|
||||
function installNetatalk() {
|
||||
NETATALK_VERSION="2-220801"
|
||||
AFP_SHARE_PATH="$HOME/afpshare"
|
||||
AFP_SHARE_NAME="Pi File Server"
|
||||
NETATALK_CONFIG_PATH="/etc/netatalk"
|
||||
|
||||
if [ -d "$NETATALK_CONFIG_PATH" ]; then
|
||||
echo
|
||||
echo "WARNING: Netatalk configuration dir $NETATALK_CONFIG_PATH already exists."
|
||||
echo "This installation process will overwrite existing Netatalk applications and configurations."
|
||||
echo "This installation process will overwrite existing binaries and configurations."
|
||||
echo "No shared files will be deleted, but you may have to manually restore your settings after the installation."
|
||||
echo
|
||||
echo "Do you want to proceed with the installation? [y/N]"
|
||||
|
@ -854,13 +787,27 @@ function installNetatalk() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$FILE_SHARE_PATH" ] && [ -d "$HOME/afpshare" ]; then
|
||||
echo
|
||||
echo "File server dir $HOME/afpshare detected. This script will rename it to $FILE_SHARE_PATH."
|
||||
echo
|
||||
echo "Do you want to proceed with the installation? [y/N]"
|
||||
read -r REPLY
|
||||
if [ "$REPLY" == "y" ] || [ "$REPLY" == "Y" ]; then
|
||||
sudo mv "$HOME/afpshare" "$FILE_SHARE_PATH" || exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Downloading netatalk-$NETATALK_VERSION to $HOME"
|
||||
cd $HOME || exit 1
|
||||
wget -O "netatalk-$NETATALK_VERSION.tar.gz" "https://github.com/rdmark/Netatalk-2.x/archive/refs/tags/netatalk-$NETATALK_VERSION.tar.gz" </dev/null
|
||||
tar -xzvf netatalk-$NETATALK_VERSION.tar.gz
|
||||
tar -xzvf "netatalk-$NETATALK_VERSION.tar.gz"
|
||||
rm "netatalk-$NETATALK_VERSION.tar.gz"
|
||||
|
||||
cd "$HOME/Netatalk-2.x-netatalk-$NETATALK_VERSION/contrib/shell_utils" || exit 1
|
||||
./debian_install.sh -j="${CORES:-1}" -n="$AFP_SHARE_NAME" -p="$AFP_SHARE_PATH" || exit 1
|
||||
./debian_install.sh -j="${CORES:-1}" -n="$FILE_SHARE_NAME" -p="$FILE_SHARE_PATH" || exit 1
|
||||
}
|
||||
|
||||
# Appends the images dir as a shared Netatalk volume
|
||||
|
@ -938,6 +885,65 @@ function installMacproxy {
|
|||
echo ""
|
||||
}
|
||||
|
||||
# Installs and configures Samba (SMB server)
|
||||
function installSamba() {
|
||||
SAMBA_CONFIG_PATH="/etc/samba"
|
||||
|
||||
if [ -d "$SAMBA_CONFIG_PATH" ]; then
|
||||
echo
|
||||
echo "Samba configuration dir $SAMBA_CONFIG_PATH already exists."
|
||||
echo "This installation process may overwrite existing binaries and configurations."
|
||||
echo "No shared files will be deleted, but you may have to manually restore your settings after the installation."
|
||||
echo
|
||||
echo "Do you want to proceed with the installation? [y/N]"
|
||||
read -r REPLY
|
||||
if ! [ "$REPLY" == "y" ] || [ "$REPLY" == "Y" ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$FILE_SHARE_PATH" ] && [ -d "$HOME/afpshare" ]; then
|
||||
echo
|
||||
echo "File server dir $HOME/afpshare detected. This script will rename it to $FILE_SHARE_PATH."
|
||||
echo
|
||||
echo "Do you want to proceed with the installation? [y/N]"
|
||||
read -r REPLY
|
||||
if [ "$REPLY" == "y" ] || [ "$REPLY" == "Y" ]; then
|
||||
sudo mv "$HOME/afpshare" "$FILE_SHARE_PATH" || exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
elif [ -d "$FILE_SHARE_PATH" ]; then
|
||||
echo "Found a $FILE_SHARE_PATH directory; will use it for file sharing."
|
||||
else
|
||||
echo "Creating the $FILE_SHARE_PATH directory and granting read/write permissions to all users..."
|
||||
sudo mkdir -p "$FILE_SHARE_PATH"
|
||||
sudo chown -R "$USER:$USER" "$FILE_SHARE_PATH"
|
||||
chmod -Rv 775 "$FILE_SHARE_PATH"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Installing dependencies..."
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install samba --no-install-recommends --assume-yes </dev/null
|
||||
echo ""
|
||||
echo "Modifying $SAMBA_CONFIG_PATH/smb.conf ..."
|
||||
if [[ `sudo grep -c "server min protocol = NT1" $SAMBA_CONFIG_PATH/smb.conf` -eq 0 ]]; then
|
||||
# Allow Windows XP clients and earlier to connect to the server
|
||||
sudo sed -i 's/\[global\]/\[global\]\nserver min protocol = NT1/' "$SAMBA_CONFIG_PATH/smb.conf"
|
||||
echo "server min prototol = NT1"
|
||||
fi
|
||||
if [[ `sudo grep -c "\[Pi File Server\]" $SAMBA_CONFIG_PATH/smb.conf` -eq 0 ]]; then
|
||||
# Define a shared directory with full read/write privileges, while aggressively hiding dot files
|
||||
echo -e '\n[Pi File Server]\npath = '"$FILE_SHARE_PATH"'\nbrowseable = yes\nwriteable = yes\nhide dot files = yes\nveto files = /.*/' | sudo tee -a "$SAMBA_CONFIG_PATH/smb.conf"
|
||||
fi
|
||||
|
||||
sudo systemctl restart smbd
|
||||
|
||||
echo "Please create a Samba password for user $USER"
|
||||
sudo smbpasswd -a "$USER"
|
||||
}
|
||||
|
||||
# updates configuration files and installs packages needed for the OLED screen script
|
||||
function installRaScsiScreen() {
|
||||
if [[ -f "$SECRET_FILE" && -z "$TOKEN" ]] ; then
|
||||
|
@ -1183,6 +1189,8 @@ function runChoice() {
|
|||
stopOldWebInterface
|
||||
updateRaScsiGit
|
||||
installPackages
|
||||
installHfdisk
|
||||
fetchHardDiskDrivers
|
||||
stopRaScsiScreen
|
||||
stopRaScsi
|
||||
compileRaScsi
|
||||
|
@ -1255,16 +1263,19 @@ function runChoice() {
|
|||
echo "Installing / Updating RaSCSI OLED Screen - Complete!"
|
||||
;;
|
||||
4)
|
||||
echo "Creating an HFS formatted 600 MiB drive image with LIDO driver"
|
||||
createDrive600M
|
||||
echo "Creating an HFS formatted 600 MiB drive image with LIDO driver - Complete!"
|
||||
echo "Installing / Updating RaSCSI Control Board UI"
|
||||
echo "This script will make the following changes to your system:"
|
||||
echo "- Install additional packages with apt-get"
|
||||
echo "- Add and modify systemd services"
|
||||
echo "- Stop and disable the RaSCSI OLED service if it is running"
|
||||
echo "- Modify the Raspberry Pi boot configuration (may require a reboot)"
|
||||
sudoCheck
|
||||
preparePythonCommon
|
||||
installRaScsiCtrlBoard
|
||||
showRaScsiCtrlBoardStatus
|
||||
echo "Installing / Updating RaSCSI Control Board UI - Complete!"
|
||||
;;
|
||||
5)
|
||||
echo "Creating an HFS formatted drive image with LIDO driver"
|
||||
createDriveCustom
|
||||
echo "Creating an HFS formatted drive image with LIDO driver - Complete!"
|
||||
;;
|
||||
6)
|
||||
echo "Configuring wired network bridge"
|
||||
echo "This script will make the following changes to your system:"
|
||||
echo "- Create a virtual network bridge interface in /etc/network/interfaces.d"
|
||||
|
@ -1274,7 +1285,7 @@ function runChoice() {
|
|||
setupWiredNetworking
|
||||
echo "Configuring wired network bridge - Complete!"
|
||||
;;
|
||||
7)
|
||||
6)
|
||||
echo "Configuring wifi network bridge"
|
||||
echo "This script will make the following changes to your system:"
|
||||
echo "- Install additional packages with apt-get"
|
||||
|
@ -1285,10 +1296,22 @@ function runChoice() {
|
|||
setupWirelessNetworking
|
||||
echo "Configuring wifi network bridge - Complete!"
|
||||
;;
|
||||
8)
|
||||
7)
|
||||
echo "Installing AppleShare File Server"
|
||||
installNetatalk
|
||||
echo "Installing AppleShare File Server - Complete!"
|
||||
;;
|
||||
8)
|
||||
echo "Installing SMB File Server"
|
||||
echo "This script will make the following changes to your system:"
|
||||
echo " - Install packages with apt-get"
|
||||
echo " - Enable Samba systemd services"
|
||||
echo " - Create a directory in the current user's home directory where shared files will be stored"
|
||||
echo " - Create a Samba user for the current user"
|
||||
sudoCheck
|
||||
installSamba
|
||||
echo "Installing SMB File Server - Complete!"
|
||||
;;
|
||||
9)
|
||||
echo "Installing Web Proxy Server"
|
||||
echo "This script will make the following changes to your system:"
|
||||
|
@ -1328,6 +1351,8 @@ function runChoice() {
|
|||
createCfgDir
|
||||
updateRaScsiGit
|
||||
installPackages
|
||||
installHfdisk
|
||||
fetchHardDiskDrivers
|
||||
preparePythonCommon
|
||||
cachePipPackages
|
||||
installRaScsiWebInterface
|
||||
|
@ -1353,19 +1378,6 @@ function runChoice() {
|
|||
echo "Enabling or disabling Web Interface authentication - Complete!"
|
||||
;;
|
||||
14)
|
||||
echo "Installing / Updating RaSCSI Control Board UI"
|
||||
echo "This script will make the following changes to your system:"
|
||||
echo "- Install additional packages with apt-get"
|
||||
echo "- Add and modify systemd services"
|
||||
echo "- Stop and disable the RaSCSI OLED service if it is running"
|
||||
echo "- Modify the Raspberry Pi boot configuration (may require a reboot)"
|
||||
sudoCheck
|
||||
preparePythonCommon
|
||||
installRaScsiCtrlBoard
|
||||
showRaScsiCtrlBoardStatus
|
||||
echo "Installing / Updating RaSCSI Control Board UI - Complete!"
|
||||
;;
|
||||
15)
|
||||
shareImagesWithNetatalk
|
||||
echo "Configuring AppleShare File Server - Complete!"
|
||||
;;
|
||||
|
@ -1383,7 +1395,7 @@ function readChoice() {
|
|||
choice=-1
|
||||
|
||||
until [ $choice -ge "0" ] && [ $choice -le "15" ]; do
|
||||
echo -n "Enter your choice (0-13) or CTRL-C to exit: "
|
||||
echo -n "Enter your choice (0-14) or CTRL-C to exit: "
|
||||
read -r choice
|
||||
done
|
||||
|
||||
|
@ -1395,27 +1407,24 @@ function showMenu() {
|
|||
echo ""
|
||||
echo "Choose among the following options:"
|
||||
echo "INSTALL/UPDATE RASCSI (${CONNECT_TYPE-FULLSPEC} version)"
|
||||
echo " 1) install or update RaSCSI Service + Web Interface"
|
||||
echo " 2) install or update RaSCSI Service"
|
||||
echo " 3) install or update RaSCSI OLED Screen (requires hardware)"
|
||||
echo "CREATE HFS FORMATTED (MAC) IMAGE WITH LIDO DRIVERS"
|
||||
echo "** For the Mac Plus, it's better to create an image through the Web Interface **"
|
||||
echo " 4) 600 MiB drive (suggested size)"
|
||||
echo " 5) custom drive size (up to 4000 MiB)"
|
||||
echo " 1) Install or update RaSCSI Service + Web Interface"
|
||||
echo " 2) Install or update RaSCSI Service"
|
||||
echo " 3) Install or update RaSCSI OLED Screen (requires hardware)"
|
||||
echo " 4) Install or update RaSCSI Control Board UI (requires hardware)"
|
||||
echo "NETWORK BRIDGE ASSISTANT"
|
||||
echo " 6) configure network bridge for Ethernet (DHCP)"
|
||||
echo " 7) configure network bridge for WiFi (static IP + NAT)"
|
||||
echo " 5) Configure network bridge for Ethernet (DHCP)"
|
||||
echo " 6) Configure network bridge for WiFi (static IP + NAT)"
|
||||
echo "INSTALL COMPANION APPS"
|
||||
echo " 8) install AppleShare File Server (Netatalk)"
|
||||
echo " 9) install Web Proxy Server (Macproxy)"
|
||||
echo " 7) Install AppleShare File Server (Netatalk)"
|
||||
echo " 8) Install SMB File Server (Samba)"
|
||||
echo " 9) Install Web Proxy Server (Macproxy)"
|
||||
echo "ADVANCED OPTIONS"
|
||||
echo " 10) compile and install RaSCSI stand-alone"
|
||||
echo " 11) configure the RaSCSI Web Interface stand-alone"
|
||||
echo " 12) enable or disable RaSCSI back-end authentication"
|
||||
echo " 13) enable or disable RaSCSI Web Interface authentication"
|
||||
echo " 10) Compile and install RaSCSI stand-alone"
|
||||
echo " 11) Configure the RaSCSI Web Interface stand-alone"
|
||||
echo " 12) Enable or disable RaSCSI back-end authentication"
|
||||
echo " 13) Enable or disable RaSCSI Web Interface authentication"
|
||||
echo "EXPERIMENTAL FEATURES"
|
||||
echo " 14) install or update RaSCSI Control Board UI (requires hardware)"
|
||||
echo " 15) share the images dir over AppleShare (requires Netatalk)"
|
||||
echo " 14) Share the images dir over AppleShare (requires Netatalk)"
|
||||
}
|
||||
|
||||
# parse arguments passed to the script
|
||||
|
@ -1431,8 +1440,8 @@ while [ "$1" != "" ]; do
|
|||
CONNECT_TYPE=$VALUE
|
||||
;;
|
||||
-r | --run_choice)
|
||||
if ! [[ $VALUE =~ ^[1-9][0-9]?$ && $VALUE -ge 1 && $VALUE -le 15 ]]; then
|
||||
echo "ERROR: The run choice parameter must have a numeric value between 1 and 15"
|
||||
if ! [[ $VALUE =~ ^[1-9][0-9]?$ && $VALUE -ge 1 && $VALUE -le 14 ]]; then
|
||||
echo "ERROR: The run choice parameter must have a numeric value between 1 and 14"
|
||||
exit 1
|
||||
fi
|
||||
RUN_CHOICE=$VALUE
|
||||
|
|
BIN
lido-driver.img
BIN
lido-driver.img
Binary file not shown.
|
@ -8,11 +8,12 @@ from os import path, walk
|
|||
from functools import lru_cache
|
||||
from pathlib import PurePath, Path
|
||||
from zipfile import ZipFile, is_zipfile
|
||||
from subprocess import run, CalledProcessError
|
||||
from subprocess import run, Popen, PIPE, CalledProcessError, TimeoutExpired
|
||||
from json import dump, load
|
||||
from shutil import copyfile
|
||||
from urllib.parse import quote
|
||||
from tempfile import TemporaryDirectory
|
||||
from re import search
|
||||
|
||||
import requests
|
||||
|
||||
|
@ -366,6 +367,222 @@ class FileCmds:
|
|||
}
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def partition_disk(self, file_name, volume_name, disk_format):
|
||||
"""
|
||||
Creates a partition table on an image file.
|
||||
Takes (str) file_name, (str) volume_name, (str) disk_format as arguments.
|
||||
disk_format is either HFS or FAT
|
||||
Returns (dict) with (bool) status, (str) msg
|
||||
"""
|
||||
server_info = self.ractl.get_server_info()
|
||||
full_file_path = Path(server_info["image_dir"]) / file_name
|
||||
|
||||
# Inject hfdisk commands to create Drive with correct partitions
|
||||
# https://www.codesrc.com/mediawiki/index.php/HFSFromScratch
|
||||
# i initialize partition map
|
||||
# continue with default first block
|
||||
# C Create 1st partition with type specified next)
|
||||
# continue with default
|
||||
# 32 32 blocks (required for HFS+)
|
||||
# Driver_Partition Partition Name
|
||||
# Apple_Driver Partition Type (available types: Apple_Driver,
|
||||
# Apple_Driver43, Apple_Free, Apple_HFS...)
|
||||
# C Create 2nd partition with type specified next
|
||||
# continue with default first block
|
||||
# continue with default block size (rest of the disk)
|
||||
# ${volumeName} Partition name provided by user
|
||||
# Apple_HFS Partition Type
|
||||
# w Write partition map to disk
|
||||
# y Confirm partition table
|
||||
# p Print partition map
|
||||
if disk_format == "HFS":
|
||||
partitioning_tool = "hfdisk"
|
||||
commands = [
|
||||
"i",
|
||||
"",
|
||||
"C",
|
||||
"",
|
||||
"32",
|
||||
"Driver_Partition",
|
||||
"Apple_Driver",
|
||||
"C",
|
||||
"",
|
||||
"",
|
||||
volume_name,
|
||||
"Apple_HFS",
|
||||
"w",
|
||||
"y",
|
||||
"p",
|
||||
]
|
||||
# Create a DOS label, primary partition, W95 FAT type
|
||||
elif disk_format == "FAT":
|
||||
partitioning_tool = "fdisk"
|
||||
commands = [
|
||||
"o",
|
||||
"n",
|
||||
"p",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"t",
|
||||
"b",
|
||||
"w",
|
||||
]
|
||||
try:
|
||||
process = Popen(
|
||||
[partitioning_tool, str(full_file_path)],
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
)
|
||||
for command in commands:
|
||||
process.stdin.write(bytes(command + "\n", "utf-8"))
|
||||
process.stdin.flush()
|
||||
try:
|
||||
outs, errs = process.communicate(timeout=15)
|
||||
if outs:
|
||||
logging.info(str(outs, "utf-8"))
|
||||
if errs:
|
||||
logging.error(str(errs, "utf-8"))
|
||||
if process.returncode:
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": errs}
|
||||
except TimeoutExpired:
|
||||
process.kill()
|
||||
outs, errs = process.communicate()
|
||||
if outs:
|
||||
logging.info(str(outs, "utf-8"))
|
||||
if errs:
|
||||
logging.error(str(errs, "utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": errs}
|
||||
|
||||
except (OSError, IOError) as error:
|
||||
logging.error(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
return {"status": True, "msg": ""}
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def format_hfs(self, file_name, volume_name, driver_path):
|
||||
"""
|
||||
Initializes an HFS file system and injects a hard disk driver
|
||||
Takes (str) file_name, (str) volume_name and (Path) driver_path as arguments.
|
||||
Returns (dict) with (bool) status, (str) msg
|
||||
"""
|
||||
server_info = self.ractl.get_server_info()
|
||||
full_file_path = Path(server_info["image_dir"]) / file_name
|
||||
|
||||
try:
|
||||
run(
|
||||
[
|
||||
"dd",
|
||||
f"if={driver_path}",
|
||||
f"of={full_file_path}",
|
||||
"seek=64",
|
||||
"count=32",
|
||||
"bs=512",
|
||||
"conv=notrunc",
|
||||
],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
except (FileNotFoundError, CalledProcessError) as error:
|
||||
logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
try:
|
||||
process = run(
|
||||
[
|
||||
"hformat",
|
||||
"-l",
|
||||
volume_name,
|
||||
str(full_file_path),
|
||||
"1",
|
||||
],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
logging.info(process.stdout.decode("utf-8"))
|
||||
except (FileNotFoundError, CalledProcessError) as error:
|
||||
logging.error(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
return {"status": True, "msg": ""}
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def format_fat(self, file_name, volume_name, fat_size):
|
||||
"""
|
||||
Initializes a FAT file system
|
||||
Takes (str) file_name, (str) volume_name and (str) FAT size (12|16|32) as arguments.
|
||||
Returns (dict) with (bool) status, (str) msg
|
||||
"""
|
||||
server_info = self.ractl.get_server_info()
|
||||
full_file_path = Path(server_info["image_dir"]) / file_name
|
||||
loopback_device = ""
|
||||
|
||||
try:
|
||||
process = run(
|
||||
["kpartx", "-av", str(full_file_path)],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
logging.info(process.stdout.decode("utf-8"))
|
||||
if process.returncode == 0:
|
||||
loopback_device = search(r"(loop\d\D\d)", process.stdout.decode("utf-8")).group(1)
|
||||
else:
|
||||
logging.info(process.stdout.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
except (FileNotFoundError, CalledProcessError) as error:
|
||||
logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
args = [
|
||||
"mkfs.fat",
|
||||
"-v",
|
||||
"-F",
|
||||
fat_size,
|
||||
"-n",
|
||||
volume_name,
|
||||
"/dev/mapper/" + loopback_device,
|
||||
]
|
||||
try:
|
||||
process = run(
|
||||
args,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
logging.info(process.stdout.decode("utf-8"))
|
||||
except (FileNotFoundError, CalledProcessError) as error:
|
||||
logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
try:
|
||||
process = run(
|
||||
["kpartx", "-dv", str(full_file_path)],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
logging.info(process.stdout.decode("utf-8"))
|
||||
if process.returncode:
|
||||
logging.info(process.stderr.decode("utf-8"))
|
||||
logging.warning("Failed to delete loopback device. You may have to do it manually")
|
||||
except (FileNotFoundError, CalledProcessError) as error:
|
||||
logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8"))
|
||||
self.delete_file(Path(file_name))
|
||||
return {"status": False, "msg": error.stderr.decode("utf-8")}
|
||||
|
||||
return {"status": True, "msg": ""}
|
||||
|
||||
|
||||
def download_file_to_iso(self, url, *iso_args):
|
||||
"""
|
||||
Takes (str) url and one or more (str) *iso_args
|
||||
|
@ -446,9 +663,12 @@ class FileCmds:
|
|||
headers={"User-Agent": "Mozilla/5.0"},
|
||||
) as req:
|
||||
req.raise_for_status()
|
||||
with open(f"{save_dir}/{file_name}", "wb") as download:
|
||||
for chunk in req.iter_content(chunk_size=8192):
|
||||
download.write(chunk)
|
||||
try:
|
||||
with open(f"{save_dir}/{file_name}", "wb") as download:
|
||||
for chunk in req.iter_content(chunk_size=8192):
|
||||
download.write(chunk)
|
||||
except FileNotFoundError as error:
|
||||
return {"status": False, "msg": str(error)}
|
||||
except requests.exceptions.RequestException as error:
|
||||
logging.warning("Request failed: %s", str(error))
|
||||
return {"status": False, "msg": str(error)}
|
||||
|
|
|
@ -8,7 +8,7 @@ import rascsi.common_settings
|
|||
WEB_DIR = getcwd()
|
||||
HOME_DIR = "/".join(WEB_DIR.split("/")[0:3])
|
||||
|
||||
AFP_DIR = f"{HOME_DIR}/afpshare"
|
||||
FILE_SERVER_DIR = f"{HOME_DIR}/shared_files"
|
||||
|
||||
MAX_FILE_SIZE = getenv("MAX_FILE_SIZE", str(1024 * 1024 * 1024 * 4)) # 4gb
|
||||
|
||||
|
|
|
@ -439,7 +439,7 @@
|
|||
<ul>
|
||||
<li>{{ _("The largest file size accepted in this form is %(max_file_size)s MiB. Use other file transfer means for larger files.", max_file_size=max_file_size) }}</li>
|
||||
<li>{{ _("File uploads will progress only if you stay on this page. If you navigate away before the transfer is completed, you will end up with an incomplete file.") }}</li>
|
||||
<li>{{ _("Install <a href=\"%(url)s\" target=\"_blank\">Netatalk</a> to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}</li>
|
||||
<li>{{ _("Install Netatalk or Samba to use the File Server.") }}</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
|
@ -447,8 +447,8 @@
|
|||
<p>
|
||||
<label for="upload_destination">{{ _("Target directory:") }}</label>
|
||||
<select name="destination" id="upload_destination">
|
||||
<option value="images">Images - {{ env["image_dir"] }}</option>
|
||||
<option value="afp">AppleShare - {{ AFP_DIR }}</option>
|
||||
<option value="images">{{ _("Disk Images") }} - {{ env["image_dir"] }}</option>
|
||||
<option value="file_server">{{ _("File Server") }} - {{ FILE_SERVER_DIR }}</option>
|
||||
</select>
|
||||
</p>
|
||||
</form>
|
||||
|
@ -489,15 +489,15 @@
|
|||
{{ _("Download File from the Web") }}
|
||||
</summary>
|
||||
<ul>
|
||||
<li>{{ _("Install <a href=\"%(url)s\" target=\"_blank\">Netatalk</a> to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}</li>
|
||||
<li>{{ _("Install Netatalk or Samba to use the File Server.") }}</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<form action="/files/download_url" method="post">
|
||||
<label for="download_destination">{{ _("Target directory:") }}</label>
|
||||
<select name="destination" id="download_destination">
|
||||
<option value="images">Images - {{ env["image_dir"] }}</option>
|
||||
<option value="afp">AppleShare - {{ AFP_DIR }}</option>
|
||||
<option value="images">{{ _("Disk Images") }} - {{ env["image_dir"] }}</option>
|
||||
<option value="file_server">{{ _("File Server") }} - {{ FILE_SERVER_DIR }}</option>
|
||||
</select>
|
||||
<label for="download_url">{{ _("URL:") }}</label>
|
||||
<input name="url" id="download_url" required="" type="url">
|
||||
|
@ -560,6 +560,7 @@
|
|||
</summary>
|
||||
<ul>
|
||||
<li>{{ _("Please refer to <a href=\"%(url)s\" target=\"_blank\">wiki documentation</a> to learn more about the supported image file types.", url="https://github.com/akuker/RASCSI/wiki/Supported-Device-Types#image-types") }}</li>
|
||||
<li>{{ _("It is not recommended to use the Lido hard disk driver with the Macintosh Plus.") }}</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
|
@ -587,6 +588,24 @@
|
|||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="drive_format">{{ _("Format as:") }}</label>
|
||||
<select name="drive_format" id="drive_format">
|
||||
<option value="">
|
||||
{{ _("None") }}
|
||||
</option>
|
||||
<option value="Lido 7.56">
|
||||
HFS + Lido
|
||||
</option>
|
||||
<option value="SpeedTools 3.6">
|
||||
HFS + SpeedTools
|
||||
</option>
|
||||
<option value="FAT16">
|
||||
FAT16
|
||||
</option>
|
||||
<option value="FAT32">
|
||||
FAT32
|
||||
</option>
|
||||
</select>
|
||||
<input type="submit" value="{{ _("Create") }}">
|
||||
</form>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue