atabasedevice: transfer data in chunks.
This commit is contained in:
parent
fef5bde0c7
commit
ebdefb5acd
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue