ATA drive LBA48 read
Posted: Fri Mar 03, 2023 5:13 pm
Hello,
I'm having a problem with an ATA LBA48 read funtion. Can you help me solve the issue? Here is the funtion I wrote:
For some reason I'm getting an "Aborted command" error on bochs. It works on quemu though. The bochs drive should support LBA48 because I'm making sure it does before deciding wheather to use LBA28 or LBA48 like so:
If you think the problem may lay in polling function here it is:
I'm having a problem with an ATA LBA48 read funtion. Can you help me solve the issue? Here is the funtion I wrote:
Code: Select all
static int ATA_read48_pio(ATADevice *device, uint32_t LBA, unsigned int count, uint8_t *buffer){
int ch = device->channel;
int dr = device->drive;
outw(channels[ch].base + ATA_REG_HDDEVSEL, (uint8_t []){0x40, 0x50}[dr]);
io_wait();
outb(channels[ch].base + ATA_REG_ERROR, 0); // Supposedly it's useless
io_wait();
outb(channels[ch].base + ATA_REG_SECCOUNT0, (uint8_t)(count >> 8)); // high sector count byte
io_wait();
outb(channels[ch].base + ATA_REG_LBAlo, (uint8_t)(LBA >> 24));
io_wait();
outb(channels[ch].base + ATA_REG_LBAmid, 0);
io_wait();
outb(channels[ch].base + ATA_REG_LBAhi, 0);
io_wait();
outb(channels[ch].base + ATA_REG_SECCOUNT0, (uint8_t)(count)); // low sector count byte
io_wait();
outb(channels[ch].base + ATA_REG_LBAlo, (uint8_t)LBA);
io_wait();
outb(channels[ch].base + ATA_REG_LBAmid, (uint8_t)(LBA >> 8));
io_wait();
outb(channels[ch].base + ATA_REG_LBAhi, (uint8_t)(LBA >> 16));
io_wait();
outb(channels[ch].base + ATA_REG_COMMAND, (uint8_t)(ATA_CMD_READ_PIO_EXT));
long_wait();
for(int i=0; i<count; i++){
int ret = poll_channel(ch);
if(ret) // Error code 1: Device not responding!, Error code 2: Unexpected error occured!
return ret;
insw(channels[ch].base + ATA_REG_DATA, (uint16_t *)(buffer + i*512), 256);
}
long_wait();
return 0;
}
Code: Select all
int ATA_read_pio(ATADevice *device, uint32_t LBA, unsigned int count, uint8_t *buffer){
if(!device->exists)
return 3; // Error code 3: Device does not exist
if(device->commandSets & (1 << 26)){ // Device uses 48-Bit Addressing
terminal_print(debugTerminal, "[DEBUG] LBA48\n");
if((LBA + count > device->size) || count > 0xFFFF)
return 4; // Error code 4: Inapropriate LBA and count
return ATA_read48_pio(device, LBA, count, buffer);
}
else{
terminal_print(debugTerminal, "[DEBUG] LBA28\n");
if((LBA + count > device->size) || LBA > 0xfffffff || count > 0xFF)
return 4; // Error code 4: Inapropriate LBA and count
return ATA_read28_pio(device, LBA, count, buffer);
}
}
Code: Select all
static int poll_channel(int channel){
uint8_t error = 0;
uint8_t status = 0xff;
int counter = 0;
while((status & ATA_SR_BSY) && counter < 10000){
status = inb(channels[channel].base + ATA_REG_STATUS);
counter++;
}
if(counter >= 10000)
return 1; // Error code 1: Device not responding!
counter = 0;
while(!(status & ATA_SR_DRQ) && counter < 10000){
status = inb(channels[channel].base + ATA_REG_STATUS);
if(status & ATA_SR_ERR){
error = inb(channels[channel].base + ATA_REG_ERROR);
break;
}
counter++;
}
if(counter >= 10000)
return 1; // Error code 1: Device not responding!
if(error){
print_error(error);
soft_reset(channel);
return 2; // Error code 2: Unexpected error ocured
}
return 0;
}