sc53c94: switch to the new DMA API.

This commit is contained in:
Maxim Poliakovski 2024-11-03 15:05:45 +01:00
parent 5057792d4d
commit 85d5b10f61
3 changed files with 76 additions and 3 deletions

View File

@ -33,7 +33,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <cstring>
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("")},

View File

@ -187,7 +187,7 @@ typedef struct {
typedef std::function<void(const uint8_t drq_state)> 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);

View File

@ -125,7 +125,9 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io_grandcentral"), InterruptCtrl()
this->curio = dynamic_cast<Sc53C94*>(gMachineObj->get_comp_by_name("Sc53C94"));
this->curio_dma = std::unique_ptr<DMAChannel> (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);
});