mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Takes a first shot at INQUIRY.
This commit is contained in:
parent
6e0e9afe2f
commit
00ce7f8ae0
@ -24,3 +24,26 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectAccessDevice::inquiry(const Target::CommandState &state, Target::Responder &responder) {
|
||||
if(!device_) return false;
|
||||
|
||||
std::vector<uint8_t> response = {
|
||||
0x00, /* Peripheral device type: directly addressible. */
|
||||
0x00, /* Non-removeable (0x80 = removeable). */
|
||||
0x00, /* Version: does not claim conformance to any standard. */
|
||||
0x00, /* Response data format: 0 for SCSI-1? */
|
||||
0x00, /* Additional length. */
|
||||
};
|
||||
|
||||
const auto allocated_bytes = state.allocated_inquiry_bytes();
|
||||
if(allocated_bytes < response.size()) {
|
||||
response.resize(allocated_bytes);
|
||||
}
|
||||
|
||||
responder.send_data(std::move(response), [] (const Target::CommandState &state, Target::Responder &responder) {
|
||||
responder.terminate_command(Target::Responder::Status::Good);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class DirectAccessDevice: public Target::Executor {
|
||||
|
||||
/* SCSI commands. */
|
||||
bool read(const Target::CommandState &, Target::Responder &);
|
||||
bool inquiry(const Target::CommandState &, Target::Responder &);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Storage::MassStorage::MassStorageDevice> device_;
|
||||
|
@ -39,3 +39,7 @@ uint16_t CommandState::number_of_blocks() const {
|
||||
return uint16_t((data_[7] << 8) | data_[8]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t CommandState::allocated_inquiry_bytes() const {
|
||||
return size_t(((data_[4] - 1) & 0xff) + 1);
|
||||
}
|
||||
|
@ -24,9 +24,13 @@ class CommandState {
|
||||
public:
|
||||
CommandState(const std::vector<uint8_t> &data);
|
||||
|
||||
// For read and write commands.
|
||||
uint32_t address() const;
|
||||
uint16_t number_of_blocks() const;
|
||||
|
||||
// For inquiry commands.
|
||||
size_t allocated_inquiry_bytes() const;
|
||||
|
||||
private:
|
||||
const std::vector<uint8_t> &data_;
|
||||
};
|
||||
@ -88,12 +92,6 @@ struct Responder {
|
||||
responder.end_command();
|
||||
});
|
||||
});
|
||||
|
||||
// send_message(Target::Responder::Message::CommandComplete, [status] (const Target::CommandState &state, Target::Responder &responder) {
|
||||
// responder.send_status(status, [] (const Target::CommandState &state, Target::Responder &responder) {
|
||||
// responder.end_command();
|
||||
// });
|
||||
// });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -73,9 +73,12 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
|
||||
command_[command_pointer_] = uint8_t(new_state);
|
||||
++command_pointer_;
|
||||
if(command_pointer_ == command_.size()) {
|
||||
dispatch_command();
|
||||
|
||||
// TODO: if(!dispatch_command()) signal_error_somehow();
|
||||
if(!dispatch_command()) {
|
||||
// This is just a guess for now; I don't know how SCSI
|
||||
// devices are supposed to respond if they don't support
|
||||
// a command.
|
||||
terminate_command(Responder::Status::TaskAborted);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -103,9 +106,9 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
|
||||
case 0:
|
||||
if(data_pointer_ == data_.size()) {
|
||||
next_function_(CommandState(command_), *this);
|
||||
} else {
|
||||
bus_state_ |= Line::Request;
|
||||
}
|
||||
|
||||
bus_state_ |= Line::Request;
|
||||
break;
|
||||
}
|
||||
set_device_output(bus_state_);
|
||||
@ -129,16 +132,16 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
|
||||
(phase_ == Phase::SendingData && data_pointer_ == data_.size())
|
||||
) {
|
||||
next_function_(CommandState(command_), *this);
|
||||
}
|
||||
} else {
|
||||
bus_state_ |= Line::Request;
|
||||
bus_state_ &= ~0xff;
|
||||
|
||||
bus_state_ |= Line::Request;
|
||||
bus_state_ &= ~0xff;
|
||||
|
||||
switch(phase_) {
|
||||
case Phase::SendingData: bus_state_ |= data_[data_pointer_]; break;
|
||||
case Phase::SendingStatus: bus_state_ |= BusState(status_); break;
|
||||
default:
|
||||
case Phase::SendingMessage: bus_state_ |= BusState(message_); break;
|
||||
switch(phase_) {
|
||||
case Phase::SendingData: bus_state_ |= data_[data_pointer_]; break;
|
||||
case Phase::SendingStatus: bus_state_ |= BusState(status_); break;
|
||||
default:
|
||||
case Phase::SendingMessage: bus_state_ |= BusState(message_); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -171,6 +174,8 @@ template <typename Executor> bool Target<Executor>::dispatch_command() {
|
||||
#define G1(x) (0x20|x)
|
||||
#define G5(x) (0xa0|x)
|
||||
|
||||
printf("---Command %02x---\n", command_[0]);
|
||||
|
||||
switch(command_[0]) {
|
||||
default: return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user