From a4ab0afce33a1e203a83a4f8a9add1ec7b5cf11c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 3 Sep 2019 21:15:30 -0400 Subject: [PATCH] Takes a shot at completing a full SCSI interaction. --- .../MassStorage/SCSI/DirectAccessDevice.cpp | 6 +++- Storage/MassStorage/SCSI/Target.hpp | 2 ++ .../MassStorage/SCSI/TargetImplementation.hpp | 33 ++++++++++++------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Storage/MassStorage/SCSI/DirectAccessDevice.cpp b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp index 5194056ce..f09f94367 100644 --- a/Storage/MassStorage/SCSI/DirectAccessDevice.cpp +++ b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp @@ -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; diff --git a/Storage/MassStorage/SCSI/Target.hpp b/Storage/MassStorage/SCSI/Target.hpp index 2b1a0aaca..9d25eb8fa 100644 --- a/Storage/MassStorage/SCSI/Target.hpp +++ b/Storage/MassStorage/SCSI/Target.hpp @@ -174,6 +174,8 @@ template class Target: public Bus::Observer, public Responde void begin_command(uint8_t first_byte); std::vector command_; + Status status_; + Message message_; size_t command_pointer_ = 0; bool dispatch_command(); diff --git a/Storage/MassStorage/SCSI/TargetImplementation.hpp b/Storage/MassStorage/SCSI/TargetImplementation.hpp index 29cc8616e..51ed40519 100644 --- a/Storage/MassStorage/SCSI/TargetImplementation.hpp +++ b/Storage/MassStorage/SCSI/TargetImplementation.hpp @@ -29,14 +29,6 @@ template void Target::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 void Target::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 void Target::receive_data(size_t length, set_device_output(bus_state_); } -template void Target::send_status(Status, continuation next) { +template void Target::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 void Target::send_message(Message, continuation next) { +template void Target::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 void Target::end_command() { phase_ = Phase::AwaitingSelection; bus_state_ = DefaultBusState; set_device_output(bus_state_); + + printf("---Done---\n"); }