Skip to content

Commit

Permalink
Say hello to Streamer (tape) device support
Browse files Browse the repository at this point in the history
Implements the mandatory and a few optional commands for tandberd see
https://bitsavers.org/pdf/tandbergData/
TDC4100/6047-1_TDC-4100_SCSI-2_Interface_Functional_Specification_Aug1991.pdf
for more info.

Fixed #480
  • Loading branch information
bog-dan-ro committed Aug 22, 2024
1 parent 657d22a commit 3736d19
Show file tree
Hide file tree
Showing 29 changed files with 1,208 additions and 104 deletions.
2 changes: 1 addition & 1 deletion cpp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## CROSS_COMPILE : Specify which compiler toolchain to use.
## To cross compile set this accordingly, e.g. to:
## arm-linux-gnueabihf-
CROSS_COMPILE =
CROSS_COMPILE ?=

CXX = $(CROSS_COMPILE)g++

Expand Down
2 changes: 1 addition & 1 deletion cpp/controllers/abstract_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class AbstractController : public PhaseHandler

int ExtractInitiatorId(int) const;

using ctrl_t = struct _ctrl_t {
struct ctrl_t {
// Command data, dynamically resized if required
vector<int> cmd = vector<int>(16);

Expand Down
18 changes: 9 additions & 9 deletions cpp/controllers/scsi_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -739,9 +739,9 @@ bool ScsiController::XferIn(vector<uint8_t>& buf)
case scsi_command::eCmdRead6:
case scsi_command::eCmdRead10:
case scsi_command::eCmdRead16:
// Read from disk
// Read from StorageDevice
try {
SetLength(dynamic_pointer_cast<Disk>(GetDeviceForLun(lun))->Read(buf, GetNext()));
SetLength(dynamic_pointer_cast<StorageDevice>(GetDeviceForLun(lun))->Read(buf, GetNext()));
}
catch(const scsi_exception&) {
// If there is an error, go to the status phase
Expand Down Expand Up @@ -819,13 +819,13 @@ bool ScsiController::XferOutBlockOriented(bool cont)
break;
}

auto disk = dynamic_pointer_cast<Disk>(device);
if (disk == nullptr) {
auto storage = dynamic_pointer_cast<StorageDevice>(device);
if (storage == nullptr) {
return false;
}

try {
disk->Write(GetBuffer(), GetNext() - 1);
storage->Write(GetBuffer(), GetNext() - 1);
}
catch(const scsi_exception& e) {
Error(e.get_sense_key(), e.get_asc());
Expand All @@ -836,7 +836,7 @@ bool ScsiController::XferOutBlockOriented(bool cont)
// If you do not need the next block, end here
IncrementNext();
if (cont) {
SetLength(disk->GetSectorSizeInBytes());
SetLength(storage->GetSectorSizeInBytes());
ResetOffset();
}

Expand All @@ -846,15 +846,15 @@ bool ScsiController::XferOutBlockOriented(bool cont)
case scsi_command::eCmdVerify10:
case scsi_command::eCmdVerify16:
{
auto disk = dynamic_pointer_cast<Disk>(device);
if (disk == nullptr) {
auto storage = dynamic_pointer_cast<StorageDevice>(device);
if (storage == nullptr) {
return false;
}

// If you do not need the next block, end here
IncrementNext();
if (cont) {
SetLength(disk->GetSectorSizeInBytes());
SetLength(storage->GetSectorSizeInBytes());
ResetOffset();
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/controllers/scsi_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ScsiController : public AbstractController

const int DEFAULT_BUFFER_SIZE = 0x1000;

using scsi_t = struct _scsi_t {
struct scsi_t {
// Synchronous transfer
bool syncenable; // Synchronous transfer possible
uint8_t syncperiod = MAX_SYNC_PERIOD; // Synchronous transfer period
Expand Down
4 changes: 4 additions & 0 deletions cpp/devices/device_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "scsi_daynaport.h"
#include "host_services.h"
#include "device_factory.h"
#include "scsi_streamer.h"

using namespace std;
using namespace piscsi_util;
Expand Down Expand Up @@ -60,6 +61,9 @@ shared_ptr<PrimaryDevice> DeviceFactory::CreateDevice(PbDeviceType type, int lun
}
break;
}
case SCST:
device = make_shared<SCSIST>(lun);
break;

case SCRM:
device = make_shared<SCSIHD>(lun, true, scsi_level::scsi_2);
Expand Down
38 changes: 0 additions & 38 deletions cpp/devices/disk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ bool Disk::Init(const param_map& params)
AddCommand(scsi_command::eCmdWrite6, [this] { Write6(); });
AddCommand(scsi_command::eCmdSeek6, [this] { Seek6(); });
AddCommand(scsi_command::eCmdStartStop, [this] { StartStopUnit(); });
AddCommand(scsi_command::eCmdPreventAllowMediumRemoval, [this]{ PreventAllowMediumRemoval(); });
AddCommand(scsi_command::eCmdReadCapacity10, [this] { ReadCapacity10(); });
AddCommand(scsi_command::eCmdRead10, [this] { Read10(); });
AddCommand(scsi_command::eCmdWrite10, [this] { Write10(); });
Expand Down Expand Up @@ -232,18 +231,7 @@ void Disk::StartStopUnit()
EnterStatusPhase();
}

void Disk::PreventAllowMediumRemoval()
{
CheckReady();

const bool lock = GetController()->GetCmdByte(4) & 0x01;

LogTrace(lock ? "Locking medium" : "Unlocking medium");

SetLocked(lock);

EnterStatusPhase();
}

void Disk::SynchronizeCache()
{
Expand Down Expand Up @@ -682,32 +670,6 @@ tuple<bool, uint64_t, uint32_t> Disk::CheckAndGetStartAndCount(access_mode mode)
return tuple(true, start, count);
}

uint32_t Disk::CalculateShiftCount(uint32_t size_in_bytes)
{
const auto& it = shift_counts.find(size_in_bytes);
return it != shift_counts.end() ? it->second : 0;
}

uint32_t Disk::GetSectorSizeInBytes() const
{
return size_shift_count ? 1 << size_shift_count : 0;
}

void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes)
{
if (!GetSupportedSectorSizes().contains(size_in_bytes)) {
throw io_exception("Invalid sector size of " + to_string(size_in_bytes) + " byte(s)");
}

size_shift_count = CalculateShiftCount(size_in_bytes);
assert(size_shift_count);
}

uint32_t Disk::GetConfiguredSectorSize() const
{
return configured_sector_size;
}

bool Disk::SetConfiguredSectorSize(uint32_t configured_size)
{
if (!supported_sector_sizes.contains(configured_size)) {
Expand Down
25 changes: 4 additions & 21 deletions cpp/devices/disk.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ class Disk : public StorageDevice, private ScsiBlockCommands

unique_ptr<DiskCache> cache;

unordered_set<uint32_t> supported_sector_sizes;
uint32_t configured_sector_size = 0;

// Sector size shift count (9=512, 10=1024, 11=2048, 12=4096)
uint32_t size_shift_count = 0;

uint64_t sector_read_count = 0;
uint64_t sector_write_count = 0;

Expand All @@ -49,7 +43,7 @@ class Disk : public StorageDevice, private ScsiBlockCommands
public:

Disk(PbDeviceType type, int lun, const unordered_set<uint32_t>& s)
: StorageDevice(type, lun), supported_sector_sizes(s) {}
: StorageDevice(type, lun, s) {}
~Disk() override = default;

bool Init(const param_map&) override;
Expand All @@ -59,13 +53,11 @@ class Disk : public StorageDevice, private ScsiBlockCommands

bool Eject(bool) override;

virtual void Write(span<const uint8_t>, uint64_t);
void Write(span<const uint8_t>, uint64_t) override;

virtual int Read(span<uint8_t> , uint64_t);
int Read(span<uint8_t> , uint64_t) override;

uint32_t GetSectorSizeInBytes() const;
bool IsSectorSizeConfigurable() const { return supported_sector_sizes.size() > 1; }
const auto& GetSupportedSectorSizes() const { return supported_sector_sizes; }
bool SetConfiguredSectorSize(uint32_t);
void FlushCache() override;

Expand All @@ -75,7 +67,6 @@ class Disk : public StorageDevice, private ScsiBlockCommands

// Commands covered by the SCSI specifications (see https://www.t10.org/drafts.htm)
void StartStopUnit();
void PreventAllowMediumRemoval();
void SynchronizeCache();
void ReadDefectData10() const;
virtual void Read6() { Read(RW6); }
Expand All @@ -100,14 +91,12 @@ class Disk : public StorageDevice, private ScsiBlockCommands
void ReadCapacity16_ReadLong16();

void ValidateBlockAddress(access_mode) const;

tuple<bool, uint64_t, uint32_t> CheckAndGetStartAndCount(access_mode) const;

int ModeSense6(cdb_t, vector<uint8_t>&) const override;
int ModeSense10(cdb_t, vector<uint8_t>&) const override;

static inline const unordered_map<uint32_t, uint32_t> shift_counts =
{ { 512, 9 }, { 1024, 10 }, { 2048, 11 }, { 4096, 12 } };

protected:

void SetUpCache(off_t, bool = false);
Expand All @@ -119,10 +108,4 @@ class Disk : public StorageDevice, private ScsiBlockCommands
virtual void AddDrivePage(map<int, vector<byte>>&, bool) const;
void AddCachePage(map<int, vector<byte>>&, bool) const;

unordered_set<uint32_t> GetSectorSizes() const;
void SetSectorSizeInBytes(uint32_t);
uint32_t GetSectorSizeShiftCount() const { return size_shift_count; }
void SetSectorSizeShiftCount(uint32_t count) { size_shift_count = count; }
uint32_t GetConfiguredSectorSize() const;
static uint32_t CalculateShiftCount(uint32_t);
};
2 changes: 1 addition & 1 deletion cpp/devices/mode_page_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void ModePageDevice::ModeSense10() const
EnterDataInPhase();
}

void ModePageDevice::ModeSelect(scsi_command, cdb_t, span<const uint8_t>, int) const
void ModePageDevice::ModeSelect(scsi_command, cdb_t, span<const uint8_t>, int)
{
// There is no default implementation of MODE SELECT
throw scsi_exception(sense_key::illegal_request, asc::invalid_command_operation_code);
Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/mode_page_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ModePageDevice : public PrimaryDevice

bool Init(const param_map&) override;

virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int) const;
virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span<const uint8_t>, int);

protected:

Expand Down
2 changes: 1 addition & 1 deletion cpp/devices/primary_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class PrimaryDevice: private ScsiPrimaryCommands, public Device
virtual bool Init(const param_map&);
virtual void CleanUp() {
// Override if cleanup work is required for a derived device
};
}

virtual void Dispatch(scsi_command);

Expand Down
5 changes: 0 additions & 5 deletions cpp/devices/scsi_command_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,7 @@ void scsi_command_util::AddAppleVendorModePage(map<int, vector<byte>>& pages, bo
}
}

int scsi_command_util::GetInt24(span <const int> buf, int offset)
{
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(span <const int> buf, int offset)
{
Expand Down
18 changes: 16 additions & 2 deletions cpp/devices/scsi_command_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace scsi_command_util
assert(buf.size() > static_cast<size_t>(offset) + 1);

return (static_cast<int>(buf[offset]) << 8) | buf[offset + 1];
};
}

template<typename T>
void SetInt16(vector<T>& buf, int offset, int value)
Expand All @@ -52,8 +52,22 @@ namespace scsi_command_util
buf[offset + 2] = static_cast<T>(value >> 8);
buf[offset + 3] = static_cast<T>(value);
}
template<typename T>
void SetInt24(vector<T>& buf, int offset, uint32_t value)
{
assert(buf.size() > static_cast<size_t>(offset) + 3);

buf[offset + 0] = static_cast<T>(value >> 16);
buf[offset + 1] = static_cast<T>(value >> 8);
buf[offset + 2] = static_cast<T>(value);
}

int GetInt24(span<const int>, int);
inline int GetInt24(const auto buf, int offset)
{
assert(buf.size() > static_cast<size_t>(offset) + 2);

return (int(buf[offset]) << 16) | (int(buf[offset + 1]) << 8) | buf[offset + 2];
}
uint32_t GetInt32(span <const int>, int);
uint64_t GetInt64(span<const int>, int);
void SetInt64(vector<uint8_t>&, int, uint64_t);
Expand Down
Loading

0 comments on commit 3736d19

Please sign in to comment.