1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 23:29:06 +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; if(!device_) return false;
responder.send_data(device_->get_block(state.address()), [] (const Target::CommandState &state, Target::Responder &responder) { 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; 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); void begin_command(uint8_t first_byte);
std::vector<uint8_t> command_; std::vector<uint8_t> command_;
Status status_;
Message message_;
size_t command_pointer_ = 0; size_t command_pointer_ = 0;
bool dispatch_command(); bool dispatch_command();

View File

@ -29,14 +29,6 @@ template <typename Executor> void Target<Executor>::scsi_bus_did_change(Bus *, B
return; 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_) { switch(phase_) {
/* /*
While awaiting selection the SCSI target is passively watching the bus waiting for its ID 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; break;
case Phase::SendingData: case Phase::SendingData:
case Phase::SendingStatus:
case Phase::SendingMessage:
switch(new_state & (Line::Request | Line::Acknowledge)) { switch(new_state & (Line::Request | Line::Acknowledge)) {
case Line::Request | Line::Acknowledge: case Line::Request | Line::Acknowledge:
bus_state_ &= ~(Line::Request | 0xff); bus_state_ &= ~(Line::Request | 0xff);
++data_pointer_; ++data_pointer_;
printf("DP: %zu\n", 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); next_function_(CommandState(command_), *this);
} }
break; break;
case 0: case 0:
bus_state_ |= Line::Request; 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; break;
} }
set_device_output(bus_state_); 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_); 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. // Status phase: message reset, control and input set.
bus_state_ &= ~(Line::Control | Line::Input | Line::Message); bus_state_ &= ~(Line::Control | Line::Input | Line::Message);
bus_state_ |= Line::Input | Line::Control; bus_state_ |= Line::Input | Line::Control;
status_ = status;
phase_ = Phase::SendingStatus; phase_ = Phase::SendingStatus;
next_function_ = next; next_function_ = next;
set_device_output(bus_state_); 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. // Message out phase: message and control set, input reset.
bus_state_ &= ~(Line::Control | Line::Input | Line::Message); bus_state_ &= ~(Line::Control | Line::Input | Line::Message);
bus_state_ |= Line::Message | Line::Control; bus_state_ |= Line::Message | Line::Control;
message_ = message;
phase_ = Phase::SendingMessage; phase_ = Phase::SendingMessage;
next_function_ = next; next_function_ = next;
@ -253,4 +260,6 @@ template <typename Executor> void Target<Executor>::end_command() {
phase_ = Phase::AwaitingSelection; phase_ = Phase::AwaitingSelection;
bus_state_ = DefaultBusState; bus_state_ = DefaultBusState;
set_device_output(bus_state_); set_device_output(bus_state_);
printf("---Done---\n");
} }