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

Takes a shot at completing a full SCSI interaction.

This commit is contained in:
Thomas Harte 2019-09-03 21:15:30 -04:00
parent 1c7e0f3c9d
commit a4ab0afce3
3 changed files with 28 additions and 13 deletions

View File

@ -19,7 +19,11 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond
if(!device_) return false;
responder.send_data(device_->get_block(state.address()), [] (const Target::CommandState &state, Target::Responder &responder) {
responder.end_command();
responder.send_message(Target::Responder::Message::CommandComplete, [] (const Target::CommandState &state, Target::Responder &responder) {
responder.send_status(Target::Responder::Status::Good, [] (const Target::CommandState &state, Target::Responder &responder) {
responder.end_command();
});
});
});
return true;

View File

@ -174,6 +174,8 @@ template <typename Executor> class Target: public Bus::Observer, public Responde
void begin_command(uint8_t first_byte);
std::vector<uint8_t> command_;
Status status_;
Message message_;
size_t command_pointer_ = 0;
bool dispatch_command();

View File

@ -29,14 +29,6 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
return;
}
// Check for an unexpected change of SCSI state.
if((phase_ > Phase::Command) && (new_state & (Line::Control | Line::Input | Line::Message)) != expected_control_state_) {
phase_ = Phase::AwaitingSelection;
bus_state_ = DefaultBusState;
set_device_output(bus_state_);
return;
}
switch(phase_) {
/*
While awaiting selection the SCSI target is passively watching the bus waiting for its ID
@ -119,20 +111,33 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
break;
case Phase::SendingData:
case Phase::SendingStatus:
case Phase::SendingMessage:
switch(new_state & (Line::Request | Line::Acknowledge)) {
case Line::Request | Line::Acknowledge:
bus_state_ &= ~(Line::Request | 0xff);
++data_pointer_;
printf("DP: %zu\n", data_pointer_);
if(data_pointer_ == data_.size()) {
if(
phase_ == Phase::SendingMessage ||
phase_ == Phase::SendingStatus ||
(phase_ == Phase::SendingData && data_pointer_ == data_.size())
) {
next_function_(CommandState(command_), *this);
}
break;
case 0:
bus_state_ |= Line::Request;
bus_state_ = (bus_state_ & ~0xff) | data_[data_pointer_];
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;
}
break;
}
set_device_output(bus_state_);
@ -224,22 +229,24 @@ template <typename Executor> void Target<Executor>::receive_data(size_t length,
set_device_output(bus_state_);
}
template <typename Executor> void Target<Executor>::send_status(Status, continuation next) {
template <typename Executor> void Target<Executor>::send_status(Status status, continuation next) {
// Status phase: message reset, control and input set.
bus_state_ &= ~(Line::Control | Line::Input | Line::Message);
bus_state_ |= Line::Input | Line::Control;
status_ = status;
phase_ = Phase::SendingStatus;
next_function_ = next;
set_device_output(bus_state_);
}
template <typename Executor> void Target<Executor>::send_message(Message, continuation next) {
template <typename Executor> void Target<Executor>::send_message(Message message, continuation next) {
// Message out phase: message and control set, input reset.
bus_state_ &= ~(Line::Control | Line::Input | Line::Message);
bus_state_ |= Line::Message | Line::Control;
message_ = message;
phase_ = Phase::SendingMessage;
next_function_ = next;
@ -253,4 +260,6 @@ template <typename Executor> void Target<Executor>::end_command() {
phase_ = Phase::AwaitingSelection;
bus_state_ = DefaultBusState;
set_device_output(bus_state_);
printf("---Done---\n");
}