1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Adds format and write to the SCSI target.

Now I think I need to switch back to the 5380 to ensure proper DMA mode interactions when writing.
This commit is contained in:
Thomas Harte 2019-09-12 21:58:09 -04:00
parent 87e8dade2f
commit c849188016
5 changed files with 62 additions and 5 deletions

View File

@ -25,6 +25,17 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond
return true;
}
bool DirectAccessDevice::write(const Target::CommandState &state, Target::Responder &responder) {
if(!device_) return false;
const auto target_address = state.address();
responder.receive_data(device_->get_block_size(), [target_address] (const Target::CommandState &state, Target::Responder &responder) {
responder.terminate_command(Target::Responder::Status::Good);
});
return true;
}
bool DirectAccessDevice::read_capacity(const Target::CommandState &state, Target::Responder &responder) {
const auto final_block = device_->get_number_of_blocks() - 1;
const auto block_size = device_->get_block_size();
@ -50,3 +61,9 @@ bool DirectAccessDevice::read_capacity(const Target::CommandState &state, Target
Target::Executor::Inquiry DirectAccessDevice::inquiry_values() {
return Inquiry("Apple", "ProFile", "1"); // All just guesses.
}
bool DirectAccessDevice::format_unit(const Target::CommandState &state, Target::Responder &responder) {
// Formatting: immediate.
responder.terminate_command(Target::Responder::Status::Good);
return true;
}

View File

@ -26,8 +26,10 @@ class DirectAccessDevice: public Target::Executor {
/* SCSI commands. */
bool read(const Target::CommandState &, Target::Responder &);
bool write(const Target::CommandState &, Target::Responder &);
Inquiry inquiry_values();
bool read_capacity(const Target::CommandState &, Target::Responder &);
bool format_unit(const Target::CommandState &, Target::Responder &);
private:
std::shared_ptr<Storage::MassStorage::MassStorageDevice> device_;

View File

@ -10,7 +10,7 @@
using namespace SCSI::Target;
CommandState::CommandState(const std::vector<uint8_t> &data) : data_(data) {}
CommandState::CommandState(const std::vector<uint8_t> &data, const std::vector<uint8_t> &received) : data_(data), received_(received) {}
uint32_t CommandState::address() const {
switch(data_.size()) {
@ -68,3 +68,14 @@ CommandState::ReadBuffer CommandState::read_buffer_specs() const {
return specs;
}
CommandState::ModeSelect CommandState::mode_select_specs() const {
ModeSelect specs;
specs.parameter_list_length = number_of_blocks();
specs.content_is_vendor_specific = !(data_[1] & 0x10);
specs.revert_to_default = (data_[1] & 0x02);
specs.save_pages = (data_[1] & 0x01);
return specs;
}

View File

@ -23,7 +23,7 @@ namespace Target {
*/
class CommandState {
public:
CommandState(const std::vector<uint8_t> &data);
CommandState(const std::vector<uint8_t> &command, const std::vector<uint8_t> &received);
// For read and write commands.
uint32_t address() const;
@ -47,6 +47,14 @@ class CommandState {
};
ModeSense mode_sense_specs() const;
struct ModeSelect {
bool content_is_vendor_specific = true;
bool revert_to_default = false;
bool save_pages = false;
uint16_t parameter_list_length = 0;
};
ModeSelect mode_select_specs() const;
struct ReadBuffer {
enum class Mode {
CombinedHeaderAndData = 0,
@ -60,8 +68,13 @@ class CommandState {
};
ReadBuffer read_buffer_specs() const;
const std::vector<uint8_t> &received_data() {
return received_;
}
private:
const std::vector<uint8_t> &data_;
const std::vector<uint8_t> &received_;
};
/*!
@ -179,6 +192,17 @@ struct Executor {
return true;
}
bool mode_select(const CommandState &state, Responder &responder) {
const auto specs = state.mode_select_specs();
responder.receive_data(specs.parameter_list_length, [] (const Target::CommandState &state, Target::Responder &responder) {
// TODO: parse data according to current sense mode.
responder.terminate_command(Target::Responder::Status::Good);
});
return true;
}
/// Inquiry: the default implementation will call the structured version and
/// package appropriately.
struct Inquiry {

View File

@ -105,7 +105,7 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
case 0:
if(data_pointer_ == data_.size()) {
next_function_(CommandState(command_), *this);
next_function_(CommandState(command_, data_), *this);
} else {
bus_state_ |= Line::Request;
}
@ -131,7 +131,7 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
(phase_ == Phase::SendingStatus && data_pointer_ == 1) ||
(phase_ == Phase::SendingData && data_pointer_ == data_.size())
) {
next_function_(CommandState(command_), *this);
next_function_(CommandState(command_, data_), *this);
} else {
bus_state_ |= Line::Request;
bus_state_ &= ~0xff;
@ -168,7 +168,7 @@ template <typename Executor> void Target<Executor>::begin_command(uint8_t first_
template <typename Executor> bool Target<Executor>::dispatch_command() {
CommandState arguments(command_);
CommandState arguments(command_, data_);
#define G0(x) x
#define G1(x) (0x20|x)
@ -187,6 +187,7 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
case G0(0x0a): return executor_.write(arguments, *this);
case G0(0x0b): return executor_.seek(arguments, *this);
case G0(0x12): return executor_.inquiry(arguments, *this);
case G0(0x15): return executor_.mode_select(arguments, *this);
case G0(0x16): return executor_.reserve_unit(arguments, *this);
case G0(0x17): return executor_.release_unit(arguments, *this);
case G0(0x1a): return executor_.mode_sense(arguments, *this);
@ -202,6 +203,8 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
case G1(0x10): return executor_.search_data_high(arguments, *this);
case G1(0x12): return executor_.search_data_low(arguments, *this);
case G1(0x1c): return executor_.read_buffer(arguments, *this);
case G1(0x15): return executor_.mode_select(arguments, *this);
case G5(0x09): return executor_.set_block_limits(arguments, *this);
}