From bf278af950fcec693ea18e9b365984597c1cad89 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 8 Dec 2023 11:05:03 +0100 Subject: [PATCH] scsidevice: add get_more_data() method. It is required for supporting large data transfers split into multiple chunks. --- devices/common/scsi/sc53c94.h | 1 + devices/common/scsi/scsi.h | 1 + devices/common/scsi/scsidevice.cpp | 14 +++++++++++++- devices/common/scsi/scsihd.h | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/devices/common/scsi/sc53c94.h b/devices/common/scsi/sc53c94.h index 38d4251..ffbdbe8 100644 --- a/devices/common/scsi/sc53c94.h +++ b/devices/common/scsi/sc53c94.h @@ -180,6 +180,7 @@ public: // ScsiDevice methods void notify(ScsiMsg msg_type, int param); bool prepare_data() { return false; }; + bool get_more_data() { return false; }; bool has_data() { return this->data_fifo_pos != 0; }; int send_data(uint8_t* dst_ptr, int count); void process_command() {}; diff --git a/devices/common/scsi/scsi.h b/devices/common/scsi/scsi.h index 84219ae..65c1fc1 100644 --- a/devices/common/scsi/scsi.h +++ b/devices/common/scsi/scsi.h @@ -183,6 +183,7 @@ public: virtual int rcv_data(const uint8_t* src_ptr, const int count); virtual bool prepare_data() = 0; + virtual bool get_more_data() = 0; virtual void process_command() = 0; void set_bus_object_ptr(ScsiBus *bus_obj_ptr) { diff --git a/devices/common/scsi/scsidevice.cpp b/devices/common/scsi/scsidevice.cpp index 7dbadad..b02d373 100644 --- a/devices/common/scsi/scsidevice.cpp +++ b/devices/common/scsi/scsidevice.cpp @@ -113,7 +113,7 @@ void ScsiDevice::prepare_xfer(ScsiBus* bus_obj, int& bytes_in, int& bytes_out) switch (this->cur_phase) { case ScsiPhase::COMMAND: this->data_ptr = this->cmd_buf; - this->data_size = 0; //bytes_in; + this->data_size = 0; bytes_out = 0; break; case ScsiPhase::STATUS: @@ -189,6 +189,18 @@ int ScsiDevice::send_data(uint8_t* dst_ptr, const int count) this->data_ptr += actual_count; this->data_size -= actual_count; + // attempt to return the requested amount of data + // when data_size drops down to zero + if (!this->data_size) { + if (this->get_more_data() && count > actual_count) { + dst_ptr += actual_count; + actual_count = std::min(this->data_size, count - actual_count); + std::memcpy(dst_ptr, this->data_ptr, actual_count); + this->data_ptr += actual_count; + this->data_size -= actual_count; + } + } + return actual_count; } diff --git a/devices/common/scsi/scsihd.h b/devices/common/scsi/scsihd.h index 680f656..92bf115 100644 --- a/devices/common/scsi/scsihd.h +++ b/devices/common/scsi/scsihd.h @@ -43,6 +43,7 @@ public: void insert_image(std::string filename); void process_command(); bool prepare_data(); + bool get_more_data() { return false; }; protected: int test_unit_ready();