atabasedevice: transfer data in chunks.

This commit is contained in:
Maxim Poliakovski 2023-12-29 21:10:44 +01:00
parent fef5bde0c7
commit ebdefb5acd
2 changed files with 43 additions and 8 deletions

View File

@ -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;

View File

@ -30,6 +30,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <string>
#include <functional>
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<void()> post_xfer_action = nullptr;
};
#endif // ATA_BASE_DEVICE_H