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