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);
});