12 #include "drv/atapi.h"
13 #include "net/endianess.h"
14 #include "debug/hexview.h"
23 bool ata_scsi_status_wait(uint8_t bus) {
25 uint8_t status = inb(ATA_PORT(bus) + ATA_REG_COMMAND);
27 if ((status & 0x01) == 1)
30 if (!(status & 0x80) && (status & 0x08))
33 ide_400ns_delay(ATA_PORT(bus));
47 bool ata_scsi_send(uint16_t bus,
bool slave, uint16_t lba_mid_hi, uint8_t command[12]) {
51 ide_select_drive(bus, slave);
53 ide_400ns_delay(ATA_PORT(bus));
55 outb(ATA_PORT(bus) + ATA_REG_ERROR, 0x00);
56 outb(ATA_PORT(bus) + ATA_REG_LBA1, lba_mid_hi & 0xFF);
57 outb(ATA_PORT(bus) + ATA_REG_LBA2, (lba_mid_hi >> 8) & 0xFF);
58 outb(ATA_PORT(bus) + ATA_REG_COMMAND, ATA_CMD_PACKET);
60 ide_400ns_delay(ATA_PORT(bus));
62 bool error = ata_scsi_status_wait(bus);
69 outsw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t *)command, 6);
81 size_t ata_scsi_receive_size_of_transfer(uint16_t bus) {
82 bool error = ata_scsi_status_wait(bus);
85 qemu_log(
"ATAPI size receive error");
89 return (inb(ATA_PORT(bus) + ATA_REG_LBA2) << 8)
90 | inb(ATA_PORT(bus) + ATA_REG_LBA1);
99 void ata_scsi_read_result(uint16_t bus,
size_t size, uint16_t* buffer) {
100 insw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t*)((uint8_t *)buffer), size);
109 size_t atapi_read_size(uint16_t bus,
bool slave) {
113 uint8_t command[12] = {
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
118 ata_scsi_send(bus, slave, 0x0008, command);
120 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
127 uint16_t* data = kcalloc(transf_size, 1);
129 ata_scsi_read_result(bus, transf_size, data);
131 uint32_t* data2 = (uint32_t*)data;
133 uint32_t maxlba = data2[0];
136 maxlba = ntohl(maxlba);
151 size_t atapi_read_block_size(uint16_t bus,
bool slave) {
152 uint8_t command[12] = {
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
157 ata_scsi_send(bus, slave, 0x0008, command);
159 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
161 uint16_t* data = (uint16_t*)kcalloc(transf_size, 1);
163 ata_scsi_read_result(bus, transf_size, data);
165 uint32_t blocksize = ntohl(*((uint32_t*)(data) + 1));
182 bool atapi_read_sectors(uint16_t drive, uint8_t *buf, uint32_t lba,
size_t sector_count) {
183 uint8_t bus = (drive >> 1) & 1;
184 bool slave = (bool)((drive >> 0) & 1);
186 uint8_t command[12] = {
189 (lba >> 0x18) & 0xFF,
190 (lba >> 0x10) & 0xFF,
191 (lba >> 0x08) & 0xFF,
192 (lba >> 0x00) & 0xFF,
193 (sector_count >> 0x18) & 0xFF,
194 (sector_count >> 0x10) & 0xFF,
195 (sector_count >> 0x08) & 0xFF,
196 (sector_count >> 0x00) & 0xFF,
201 size_t block_size = atapi_read_block_size(bus, slave);
202 bool error = ata_scsi_send(bus, slave, block_size, command);
209 size_t transf_size = ata_scsi_receive_size_of_transfer(bus);
212 qemu_log(
"Error: Transfer size can't be 0!");
216 for (uint32_t i = 0; i < sector_count; i++) {
217 error = ata_scsi_status_wait(bus);
222 size_t size = ata_scsi_receive_size_of_transfer(bus);
224 insw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t*)((uint8_t*)buf + i * block_size), size / 2);
236 bool atapi_eject(uint8_t bus,
bool slave) {
247 uint8_t command[12] = {
248 ATAPI_CMD_START_STOP,
254 bool error = ata_scsi_send(bus, slave, 0, command);
260 command[4] = (1 << 1);
262 error = ata_scsi_send(bus, slave, 0, command);
278 atapi_error_code atapi_request_sense(uint8_t bus,
bool slave, uint8_t out[18]) {
279 uint8_t command[12] = {
280 ATAPI_CMD_RQ_SENSE, 0, 0, 0,
285 ata_scsi_send(bus, slave, 18, command);
287 ata_scsi_receive_size_of_transfer(bus);
289 ata_scsi_read_result(bus, 18, (uint16_t*)out);
293 hexview_advanced(out, 18, 10,
false, new_qemu_printf);
295 return (
atapi_error_code){(out[0] >> 7) & 1, out[2] & 0b00001111, out[12], out[13]};
304 bool atapi_check_media_presence(uint8_t bus,
bool slave) {
305 uint8_t command[12] = {
306 ATAPI_CMD_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
309 bool error = ata_scsi_send(bus, slave, 0, command);
316 uint8_t errorcode[18];
320 return !(error_code.valid && error_code.sense_key == 0x02 && error_code.sense_code == 0x3A);