1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Implements READ BUFFER to do, you know, *something*. Plus READ CAPACITY.

The HD SC utility now offers up drive 6 for formatting. That's progress.
This commit is contained in:
Thomas Harte 2019-09-11 21:52:02 -04:00
parent 6fc5b4e825
commit 87e8dade2f
5 changed files with 63 additions and 4 deletions

View File

@ -25,6 +25,28 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond
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();
std::vector<uint8_t> data = {
uint8_t(final_block >> 24),
uint8_t(final_block >> 16),
uint8_t(final_block >> 8),
uint8_t(final_block >> 0),
uint8_t(block_size >> 24),
uint8_t(block_size >> 16),
uint8_t(block_size >> 8),
uint8_t(block_size >> 0),
};
responder.send_data(std::move(data), [] (const Target::CommandState &state, Target::Responder &responder) {
responder.terminate_command(Target::Responder::Status::Good);
});
return true;
}
Target::Executor::Inquiry DirectAccessDevice::inquiry_values() {
return Inquiry("Apple", "ProFile", "1"); // All just guesses.
}

View File

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

View File

@ -46,7 +46,7 @@ size_t CommandState::allocated_inquiry_bytes() const {
}
CommandState::ModeSense CommandState::mode_sense_specs() const {
CommandState::ModeSense specs;
ModeSense specs;
specs.exclude_block_descriptors = (data_[1] & 0x08);
specs.page_control_values = ModeSense::PageControlValues(data_[2] >> 5);
@ -56,3 +56,15 @@ CommandState::ModeSense CommandState::mode_sense_specs() const {
return specs;
}
CommandState::ReadBuffer CommandState::read_buffer_specs() const {
ReadBuffer specs;
specs.mode = ReadBuffer::Mode(data_[1]&7);
if(specs.mode > ReadBuffer::Mode::Reserved) specs.mode = ReadBuffer::Mode::Reserved;
specs.buffer_id = data_[2];
specs.buffer_offset = uint32_t((data_[3] << 16) | (data_[4] << 8) | data_[5]);
specs.buffer_length = uint32_t((data_[6] << 16) | (data_[7] << 8) | data_[8]);
return specs;
}

View File

@ -47,6 +47,19 @@ class CommandState {
};
ModeSense mode_sense_specs() const;
struct ReadBuffer {
enum class Mode {
CombinedHeaderAndData = 0,
VendorSpecific = 1,
Data = 2,
Descriptor = 3,
Reserved = 4
} mode = Mode::CombinedHeaderAndData;
uint8_t buffer_id = 0;
uint32_t buffer_offset = 0, buffer_length = 0;
};
ReadBuffer read_buffer_specs() const;
private:
const std::vector<uint8_t> &data_;
};
@ -137,7 +150,7 @@ struct Executor {
bool write_diagnostic(const CommandState &, Responder &) { return false; }
/// Mode sense: the default implementation will call into the appropriate
/// strucutred getter.
/// structured getter.
bool mode_sense(const CommandState &state, Responder &responder) {
const auto specs = state.mode_sense_specs();
std::vector<uint8_t> response = {
@ -270,6 +283,16 @@ struct Executor {
bool search_data_equal(const CommandState &, Responder &) { return false; }
bool search_data_high(const CommandState &, Responder &) { return false; }
bool search_data_low(const CommandState &, Responder &) { return false; }
bool read_buffer(const CommandState &state, Responder &responder) {
// Since I have no idea what earthly function READ BUFFER is meant to allow,
// the default implementation just returns an empty buffer of the requested size.
const auto specs = state.read_buffer_specs();
responder.send_data(std::vector<uint8_t>(specs.buffer_length), [] (const Target::CommandState &, Target::Responder &responder) {
responder.terminate_command(Target::Responder::Status::Good);
});
return true;
}
/* Group 5 commands. */
bool set_block_limits(const CommandState &, Responder &) { return false; }

View File

@ -186,12 +186,12 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
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(0x12): return executor_.inquiry(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);
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(0x1a): return executor_.mode_sense(arguments, *this);
case G1(0x05): return executor_.read_capacity(arguments, *this);
case G1(0x08): return executor_.read(arguments, *this);
@ -201,6 +201,7 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
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(0x1c): return executor_.read_buffer(arguments, *this);
case G5(0x09): return executor_.set_block_limits(arguments, *this);
}