From 85d5b10f61d0930cc38e399edc1b96d772327a56 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Sun, 3 Nov 2024 15:05:45 +0100 Subject: [PATCH] sc53c94: switch to the new DMA API. --- devices/common/scsi/sc53c94.cpp | 69 ++++++++++++++++++++++++++++++++- devices/common/scsi/sc53c94.h | 6 ++- devices/ioctrl/grandcentral.cpp | 4 +- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/devices/common/scsi/sc53c94.cpp b/devices/common/scsi/sc53c94.cpp index 643bf75..5c5abca 100644 --- a/devices/common/scsi/sc53c94.cpp +++ b/devices/common/scsi/sc53c94.cpp @@ -33,7 +33,7 @@ along with this program. If not, see . #include #include -Sc53C94::Sc53C94(uint8_t chip_id, uint8_t my_id) : ScsiDevice("SC53C94", my_id) +Sc53C94::Sc53C94(uint8_t chip_id, uint8_t my_id) : ScsiDevice("SC53C94", my_id), DmaDevice() { this->chip_id = chip_id; this->my_bus_id = my_id; @@ -751,6 +751,73 @@ void Sc53C94::dma_stop() } } +int Sc53C94::xfer_from(uint8_t *buf, int len) { + if (len > this->xfer_count + this->data_fifo_pos) + LOG_F(WARNING, "%s: DMA xfer len > command xfer len", this->name.c_str()); + + if (this->data_fifo_pos) { + int fifo_bytes = std::min(this->data_fifo_pos, len); + std::memcpy(buf, this->data_fifo, fifo_bytes); + this->data_fifo_pos -= fifo_bytes; + this->xfer_count -= fifo_bytes; + len -= fifo_bytes; + buf += fifo_bytes; + if (!this->xfer_count) { + this->status |= STAT_TC; // signal zero transfer count + this->cur_state = SeqState::XFER_END; + this->sequencer(); + return 0; + } + } + + if (this->bus_obj->pull_data(this->target_id, buf, this->xfer_count)) { + this->xfer_count = 0; + this->status |= STAT_TC; // signal zero transfer count + this->cur_state = SeqState::XFER_END; + this->sequencer(); + return 0; + } + + return len; +} + +int Sc53C94::xfer_to(uint8_t *buf, int len) { + if (!this->xfer_count) + return len; + + // Being in the DATA_OUT phase means that we're about to move + // a big chunk of data. The real device uses its FIFO as buffer. + // For simplicity, the code below transfers the whole chunk at once. + // This can be broken into smaller chunks later if desired. + if (this->cur_bus_phase == ScsiPhase::DATA_OUT) { + if (this->bus_obj->push_data(this->target_id, buf, len)) { + this->xfer_count -= len; + if (!this->xfer_count) { + this->status |= STAT_TC; // signal zero transfer count + this->cur_state = SeqState::XFER_END; + this->sequencer(); + } + len = 0; + } else + LOG_F(WARNING, "%s: xfer_to failed to transfer data", this->name.c_str()); + } + + if (this->xfer_count) { + // fill in the data FIFO first + uint32_t fifo_bytes = std::min(len, DATA_FIFO_MAX - this->data_fifo_pos); + std::memcpy(&this->data_fifo[this->data_fifo_pos], buf, fifo_bytes); + len -= fifo_bytes; + this->data_fifo_pos += fifo_bytes; + this->xfer_count -= fifo_bytes; + if (!this->xfer_count) { + this->status |= STAT_TC; // signal zero transfer count + this->sequencer(); + } + } + + return len; +} + static const PropMap Sc53C94_properties = { {"hdd_img", new StrProperty("")}, {"cdr_img", new StrProperty("")}, diff --git a/devices/common/scsi/sc53c94.h b/devices/common/scsi/sc53c94.h index 48a40ee..f525361 100644 --- a/devices/common/scsi/sc53c94.h +++ b/devices/common/scsi/sc53c94.h @@ -187,7 +187,7 @@ typedef struct { typedef std::function DrqCb; -class Sc53C94 : public ScsiDevice { +class Sc53C94 : public ScsiDevice, public DmaDevice { public: Sc53C94(uint8_t chip_id=12, uint8_t my_id=7); ~Sc53C94() = default; @@ -235,6 +235,10 @@ public: int send_data(uint8_t* dst_ptr, int count); void process_command() {}; + // DmaChannel methods + int xfer_from(uint8_t *buf, int len); // Must be marked override! + int xfer_to(uint8_t *buf, int len); // Must be marked override! + protected: void reset_device(); void update_command_reg(uint8_t cmd); diff --git a/devices/ioctrl/grandcentral.cpp b/devices/ioctrl/grandcentral.cpp index 0ef8d40..b94518e 100644 --- a/devices/ioctrl/grandcentral.cpp +++ b/devices/ioctrl/grandcentral.cpp @@ -125,7 +125,9 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io_grandcentral"), InterruptCtrl() this->curio = dynamic_cast(gMachineObj->get_comp_by_name("Sc53C94")); this->curio_dma = std::unique_ptr (new DMAChannel("curio_scsi")); this->curio_dma->register_dma_int(this, this->register_dma_int(IntSrc::DMA_SCSI_CURIO)); - this->curio->set_dma_channel(this->curio_dma.get()); + this->curio_dma->connect(this->curio); + this->curio->connect(this->curio_dma.get()); + //this->curio->set_dma_channel(this->curio_dma.get()); this->curio->set_drq_callback([this](const uint8_t drq_state) { this->curio_dma->set_stat((drq_state & 1) << 5); });