mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-05 05:34:20 +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:
parent
87e8dade2f
commit
c849188016
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user