From 2ce1f0a3b14d3cb52da03e18f9bbbca2c2682225 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 16 Sep 2019 22:20:42 -0400 Subject: [PATCH] Implements multi-sector read/write. This once again unblocks Apple HD SC Setup. Progress! --- Components/5380/ncr5380.cpp | 2 ++ .../MassStorage/SCSI/DirectAccessDevice.cpp | 22 ++++++++++++++++--- Storage/MassStorage/SCSI/Target.cpp | 9 ++++++++ Storage/MassStorage/SCSI/Target.hpp | 9 ++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/Components/5380/ncr5380.cpp b/Components/5380/ncr5380.cpp index 1a21f0758..7621ed911 100644 --- a/Components/5380/ncr5380.cpp +++ b/Components/5380/ncr5380.cpp @@ -27,6 +27,8 @@ void NCR5380::write(int address, uint8_t value, bool dma_acknowledge) { data_bus_ = value; if(dma_request_ && dma_operation_ == DMAOperation::Send) { + if(value) + printf("!"); printf("w %02x\n", value); dma_acknowledge_ = true; dma_request_ = false; diff --git a/Storage/MassStorage/SCSI/DirectAccessDevice.cpp b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp index f17e78eb1..00c20c221 100644 --- a/Storage/MassStorage/SCSI/DirectAccessDevice.cpp +++ b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp @@ -18,7 +18,15 @@ void DirectAccessDevice::set_storage(const std::shared_ptrget_block(state.address()), [] (const Target::CommandState &state, Target::Responder &responder) { + const auto specs = state.read_write_specs(); + + std::vector output = device_->get_block(specs.address); + for(uint32_t offset = 1; offset < specs.number_of_blocks; ++offset) { + const auto next_block = device_->get_block(specs.address + offset); + std::copy(next_block.begin(), next_block.end(), std::back_inserter(output)); + } + + responder.send_data(std::move(output), [] (const Target::CommandState &state, Target::Responder &responder) { responder.terminate_command(Target::Responder::Status::Good); }); @@ -28,8 +36,16 @@ bool DirectAccessDevice::read(const Target::CommandState &state, Target::Respond bool DirectAccessDevice::write(const Target::CommandState &state, Target::Responder &responder) { if(!device_) return false; - responder.receive_data(device_->get_block_size(), [this] (const Target::CommandState &state, Target::Responder &responder) { - this->device_->set_block(state.address(), state.received_data()); + const auto specs = state.read_write_specs(); + + responder.receive_data(device_->get_block_size() * specs.number_of_blocks, [this, specs] (const Target::CommandState &state, Target::Responder &responder) { + const auto received_data = state.received_data(); + const auto block_size = device_->get_block_size(); + for(uint32_t offset = 0; offset < specs.number_of_blocks; ++offset) { + // TODO: clean up this gross inefficiency when std::span is standard. + std::vector sub_vector(received_data.begin() + size_t(offset)*block_size, received_data.begin() + size_t(offset+1)*block_size); + this->device_->set_block(specs.address + offset, sub_vector); + } responder.terminate_command(Target::Responder::Status::Good); }); diff --git a/Storage/MassStorage/SCSI/Target.cpp b/Storage/MassStorage/SCSI/Target.cpp index a576f1501..558d3f331 100644 --- a/Storage/MassStorage/SCSI/Target.cpp +++ b/Storage/MassStorage/SCSI/Target.cpp @@ -40,6 +40,15 @@ uint16_t CommandState::number_of_blocks() const { } } +CommandState::ReadWrite CommandState::read_write_specs() const { + ReadWrite specs; + + specs.address = address(); + specs.number_of_blocks = number_of_blocks(); + + return specs; +} + size_t CommandState::allocated_inquiry_bytes() const { // 0 means 256 bytes allocated for inquiry. return size_t(((data_[4] - 1) & 0xff) + 1); diff --git a/Storage/MassStorage/SCSI/Target.hpp b/Storage/MassStorage/SCSI/Target.hpp index 1346f8ee3..b5e46e194 100644 --- a/Storage/MassStorage/SCSI/Target.hpp +++ b/Storage/MassStorage/SCSI/Target.hpp @@ -26,8 +26,11 @@ class CommandState { CommandState(const std::vector &command, const std::vector &received); // For read and write commands. - uint32_t address() const; - uint16_t number_of_blocks() const; + struct ReadWrite { + uint32_t address; + uint16_t number_of_blocks; + }; + ReadWrite read_write_specs() const; // For inquiry commands. size_t allocated_inquiry_bytes() const; @@ -73,6 +76,8 @@ class CommandState { } private: + uint32_t address() const; + uint16_t number_of_blocks() const; const std::vector &data_; const std::vector &received_; };