mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-26 19:17:52 +00:00
Introduces real hard disk images to the nascent world of SCSI.
This commit is contained in:
@@ -10,13 +10,15 @@
|
||||
|
||||
using namespace SCSI;
|
||||
|
||||
bool DirectAccessDevice::read(const Target::CommandState &state, Target::Responder &responder) {
|
||||
std::vector<uint8_t> data(512);
|
||||
for(size_t c = 0; c < 512; ++c) {
|
||||
data[c] = uint8_t(c);
|
||||
}
|
||||
|
||||
responder.send_data(std::move(data), [] (const Target::CommandState &state, Target::Responder &responder) {
|
||||
void DirectAccessDevice::set_storage(const std::shared_ptr<Storage::MassStorage::MassStorageDevice> &device) {
|
||||
device_ = device;
|
||||
}
|
||||
|
||||
bool DirectAccessDevice::read(const Target::CommandState &state, Target::Responder &responder) {
|
||||
if(!device_) return false;
|
||||
|
||||
responder.send_data(device_->get_block(state.address()), [] (const Target::CommandState &state, Target::Responder &responder) {
|
||||
responder.end_command();
|
||||
});
|
||||
|
||||
|
||||
@@ -10,12 +10,25 @@
|
||||
#define SCSI_DirectAccessDevice_hpp
|
||||
|
||||
#include "Target.hpp"
|
||||
#include "../MassStorageDevice.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SCSI {
|
||||
|
||||
class DirectAccessDevice: public Target::Executor {
|
||||
public:
|
||||
|
||||
/*!
|
||||
Sets the backing storage exposed by this direct-access device.
|
||||
*/
|
||||
void set_storage(const std::shared_ptr<Storage::MassStorage::MassStorageDevice> &device);
|
||||
|
||||
/* SCSI commands. */
|
||||
bool read(const Target::CommandState &, Target::Responder &);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Storage::MassStorage::MassStorageDevice> device_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using namespace SCSI::Target;
|
||||
|
||||
CommandState::CommandState(const std::vector<uint8_t> &data) : data_(data) {}
|
||||
|
||||
uint32_t CommandState::address() {
|
||||
uint32_t CommandState::address() const {
|
||||
switch(data_.size()) {
|
||||
default: return 0;
|
||||
case 6:
|
||||
@@ -30,7 +30,7 @@ uint32_t CommandState::address() {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t CommandState::number_of_blocks() {
|
||||
uint16_t CommandState::number_of_blocks() const {
|
||||
switch(data_.size()) {
|
||||
default: return 0;
|
||||
case 6:
|
||||
|
||||
@@ -24,8 +24,8 @@ class CommandState {
|
||||
public:
|
||||
CommandState(const std::vector<uint8_t> &data);
|
||||
|
||||
uint32_t address();
|
||||
uint16_t number_of_blocks();
|
||||
uint32_t address() const;
|
||||
uint16_t number_of_blocks() const;
|
||||
|
||||
private:
|
||||
const std::vector<uint8_t> &data_;
|
||||
@@ -134,9 +134,13 @@ template <typename Executor> class Target: public Bus::Observer, public Responde
|
||||
*/
|
||||
Target(Bus &bus, int scsi_id);
|
||||
|
||||
Executor executor;
|
||||
inline Executor *operator->() {
|
||||
return &executor_;
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
|
||||
// Bus::Observer.
|
||||
void scsi_bus_did_change(Bus *, BusState new_state) final;
|
||||
|
||||
|
||||
@@ -147,29 +147,29 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
|
||||
switch(command_[0]) {
|
||||
default: return false;
|
||||
|
||||
case G0(0x00): return executor.test_unit_ready(arguments, *this);
|
||||
case G0(0x01): return executor.rezero_unit(arguments, *this);
|
||||
case G0(0x03): return executor.request_sense(arguments, *this);
|
||||
case G0(0x04): return executor.format_unit(arguments, *this);
|
||||
case G0(0x08): return executor.read(arguments, *this);
|
||||
case G0(0x0a): return executor.write(arguments, *this);
|
||||
case G0(0x0b): return executor.seek(arguments, *this);
|
||||
case G0(0x16): return executor.reserve_unit(arguments, *this);
|
||||
case G0(0x17): return executor.release_unit(arguments, *this);
|
||||
case G0(0x1c): return executor.read_diagnostic(arguments, *this);
|
||||
case G0(0x1d): return executor.write_diagnostic(arguments, *this);
|
||||
case G0(0x12): return executor.inquiry(arguments, *this);
|
||||
case G0(0x00): return executor_.test_unit_ready(arguments, *this);
|
||||
case G0(0x01): return executor_.rezero_unit(arguments, *this);
|
||||
case G0(0x03): return executor_.request_sense(arguments, *this);
|
||||
case G0(0x04): return executor_.format_unit(arguments, *this);
|
||||
case G0(0x08): return executor_.read(arguments, *this);
|
||||
case G0(0x0a): return executor_.write(arguments, *this);
|
||||
case G0(0x0b): return executor_.seek(arguments, *this);
|
||||
case G0(0x16): return executor_.reserve_unit(arguments, *this);
|
||||
case G0(0x17): return executor_.release_unit(arguments, *this);
|
||||
case G0(0x1c): return executor_.read_diagnostic(arguments, *this);
|
||||
case G0(0x1d): return executor_.write_diagnostic(arguments, *this);
|
||||
case G0(0x12): return executor_.inquiry(arguments, *this);
|
||||
|
||||
case G1(0x05): return executor.read_capacity(arguments, *this);
|
||||
case G1(0x08): return executor.read(arguments, *this);
|
||||
case G1(0x0a): return executor.write(arguments, *this);
|
||||
case G1(0x0e): return executor.write_and_verify(arguments, *this);
|
||||
case G1(0x0f): return executor.verify(arguments, *this);
|
||||
case G1(0x11): return executor.search_data_equal(arguments, *this);
|
||||
case G1(0x10): return executor.search_data_high(arguments, *this);
|
||||
case G1(0x12): return executor.search_data_low(arguments, *this);
|
||||
case G1(0x05): return executor_.read_capacity(arguments, *this);
|
||||
case G1(0x08): return executor_.read(arguments, *this);
|
||||
case G1(0x0a): return executor_.write(arguments, *this);
|
||||
case G1(0x0e): return executor_.write_and_verify(arguments, *this);
|
||||
case G1(0x0f): return executor_.verify(arguments, *this);
|
||||
case G1(0x11): return executor_.search_data_equal(arguments, *this);
|
||||
case G1(0x10): return executor_.search_data_high(arguments, *this);
|
||||
case G1(0x12): return executor_.search_data_low(arguments, *this);
|
||||
|
||||
case G5(0x09): return executor.set_block_limits(arguments, *this);
|
||||
case G5(0x09): return executor_.set_block_limits(arguments, *this);
|
||||
}
|
||||
|
||||
#undef G0
|
||||
|
||||
Reference in New Issue
Block a user