diff --git a/devices/common/ata/atabasedevice.cpp b/devices/common/ata/atabasedevice.cpp index 86e623c..ee6212b 100644 --- a/devices/common/ata/atabasedevice.cpp +++ b/devices/common/ata/atabasedevice.cpp @@ -64,9 +64,15 @@ uint16_t AtaBaseDevice::read(const uint8_t reg_addr) { case ATA_Reg::DATA: if (this->has_data()) { uint16_t ret_data = this->get_data(); - this->xfer_cnt -= 2; - if (this->xfer_cnt <= 0) { - this->r_status &= ~DRQ; + this->chunk_cnt -= 2; + if (this->chunk_cnt <= 0) { + this->xfer_cnt -= this->chunk_size; + if (this->xfer_cnt <= 0) + this->r_status &= ~DRQ; + else { + this->chunk_cnt = this->chunk_size; + this->update_intrq(1); + } } return ret_data; } else { @@ -98,8 +104,23 @@ uint16_t AtaBaseDevice::read(const uint8_t reg_addr) { void AtaBaseDevice::write(const uint8_t reg_addr, const uint16_t value) { switch (reg_addr) { case ATA_Reg::DATA: - if (this->has_data()) - LOG_F(WARNING, "Pushing data to %s", this->name.c_str()); + if (this->has_data()) { + *this->cur_data_ptr++ = BYTESWAP_16(value); + this->chunk_cnt -= 2; + if (this->chunk_cnt <= 0) { + this->post_xfer_action(); + this->xfer_cnt -= this->chunk_size; + if (this->xfer_cnt <= 0) { // transfer complete? + this->r_status &= ~DRQ; + this->r_status &= ~BSY; + this->update_intrq(1); + } else { + this->cur_data_ptr = this->data_ptr; + this->chunk_cnt = this->chunk_size; + this->signal_data_ready(); + } + } + } break; case ATA_Reg::FEATURES: this->r_features = value; @@ -161,6 +182,12 @@ void AtaBaseDevice::update_intrq(uint8_t new_intrq_state) { this->host_obj->report_intrq(new_intrq_state); } +void AtaBaseDevice::prepare_xfer(int xfer_size, int block_size) { + this->chunk_cnt = std::min(xfer_size, block_size); + this->xfer_cnt = xfer_size; + this->chunk_size = block_size; +} + void AtaBaseDevice::signal_data_ready() { this->r_status |= DRQ; this->r_status &= ~BSY; diff --git a/devices/common/ata/atabasedevice.h b/devices/common/ata/atabasedevice.h index 3472986..5c34b29 100644 --- a/devices/common/ata/atabasedevice.h +++ b/devices/common/ata/atabasedevice.h @@ -30,6 +30,7 @@ along with this program. If not, see . #include #include +#include class IdeChannel; @@ -69,6 +70,8 @@ public: protected: bool is_selected() { return ((this->r_dev_head >> 4) & 1) == this->my_dev_id; }; + void prepare_xfer(int xfer_size, int block_size); + uint8_t my_dev_id = 0; // my IDE device ID configured by the host uint8_t device_type = ata_interface::DEVICE_TYPE_UNKNOWN; uint8_t intrq_state = 0; // INTRQ deasserted @@ -88,9 +91,14 @@ protected: uint8_t r_status_save; uint8_t r_dev_ctrl = 0x08; - uint16_t *data_ptr = nullptr; - uint8_t data_buf[512] = {}; - int xfer_cnt = 0; + uint16_t *data_ptr = nullptr; + uint16_t *cur_data_ptr = nullptr; + uint8_t data_buf[512] = {}; + int xfer_cnt = 0; + int chunk_cnt = 0; + int chunk_size = 0; + + std::function post_xfer_action = nullptr; }; #endif // ATA_BASE_DEVICE_H