Skip to content

Commit 1f2256e

Browse files
dingusdevWack0
andcommitted
Additional ATA commands
Mostly from Wack0's NT4 fork. Co-Authored-By: Rairii <2650838+Wack0@users.noreply.github.com>
1 parent 0518f2a commit 1f2256e

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

devices/common/ata/atahd.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ int AtaHardDisk::perform_command() {
8585
switch (this->r_command) {
8686
case NOP:
8787
break;
88+
case ATAPI_SOFT_RESET: // for ATA devices, is a no-op
89+
this->r_status &= ~BSY;
90+
break;
8891
case RECALIBRATE: // is optional in ATA-3; disappeared in >= ATA-4
8992
// OF 3.1.1 won't boot off the drive that reports error for this command
9093
this->r_cylinder_hi = 0;
@@ -94,25 +97,48 @@ int AtaHardDisk::perform_command() {
9497
this->r_status &= ~BSY;
9598
this->update_intrq(1);
9699
break;
100+
case READ_MULTIPLE:
97101
case READ_SECTOR:
98102
case READ_SECTOR_NR: {
99103
uint16_t sec_count = this->r_sect_count ? this->r_sect_count : 256;
100104
int xfer_size = sec_count * ATA_HD_SEC_SIZE;
101105
uint64_t offset = this->get_lba() * ATA_HD_SEC_SIZE;
106+
uint32_t ints_size = ATA_HD_SEC_SIZE;
107+
if (this->r_command == READ_MULTIPLE) {
108+
if (this->multiple_sector_count == 0) {
109+
LOG_F(ERROR, "%s: READ MULTIPLE with SET MULTIPLE==0", this->name.c_str());
110+
this->r_status |= ERR;
111+
this->r_status &= ~BSY;
112+
break;
113+
}
114+
ints_size *= this->multiple_sector_count;
115+
}
102116
hdd_img.read(buffer, offset, xfer_size);
103117
this->data_ptr = (uint16_t *)this->buffer;
104118
// those commands should generate IRQ for each sector
105-
this->prepare_xfer(xfer_size, ATA_HD_SEC_SIZE);
119+
this->prepare_xfer(xfer_size, ints_size);
106120
this->signal_data_ready();
107121
}
108122
break;
123+
case WRITE_MULTIPLE:
109124
case WRITE_SECTOR:
110125
case WRITE_SECTOR_NR: {
111126
uint16_t sec_count = this->r_sect_count ? this->r_sect_count : 256;
112127
this->cur_fpos = this->get_lba() * ATA_HD_SEC_SIZE;
113128
this->data_ptr = (uint16_t *)this->buffer;
114129
this->cur_data_ptr = this->data_ptr;
115-
this->prepare_xfer(sec_count * ATA_HD_SEC_SIZE, ATA_HD_SEC_SIZE);
130+
uint32_t xfer_size = sec_count * ATA_HD_SEC_SIZE;
131+
uint32_t ints_size = ATA_HD_SEC_SIZE;
132+
if (this->r_command == WRITE_MULTIPLE) {
133+
if (this->multiple_sector_count == 0) {
134+
LOG_F(ERROR, "%s: WRITE MULTIPLE with SET MULTIPLE==0", this->name.c_str());
135+
this->r_status |= ERR;
136+
this->r_status &= ~BSY;
137+
break;
138+
}
139+
ints_size *= this->multiple_sector_count;
140+
}
141+
this->prepare_xfer(xfer_size, ints_size);
116142
this->post_xfer_action = [this]() {
117143
this->hdd_img.write(this->data_ptr, this->cur_fpos, this->chunk_size);
118144
this->cur_fpos += this->chunk_size;
@@ -127,6 +153,11 @@ int AtaHardDisk::perform_command() {
127153
this->r_status &= ~BSY;
128154
this->update_intrq(1);
129155
break;
156+
case READ_VERIFY:
157+
// verify sectors are readable, just no-op
158+
this->r_status &= ~BSY;
159+
this->update_intrq(1);
160+
break;
130161
case INIT_DEV_PARAM:
131162
// update fictive disk geometry with parameters from host
132163
this->sectors = this->r_sect_count;

0 commit comments

Comments
 (0)