Page 1 of 1

ATA drive LBA48 read

Posted: Fri Mar 03, 2023 5:13 pm
by Matt1223
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:

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;
}
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:

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);
    }
}
If you think the problem may lay in polling function here it is:

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

Re: ATA drive LBA48 read

Posted: Fri Mar 03, 2023 5:37 pm
by Octocontrabass
Turn up the log level in Bochs and see what messages it outputs. It might tell you what you're doing wrong that way.

Otherwise, I don't see any obvious problems...

Re: ATA drive LBA48 read

Posted: Fri Mar 03, 2023 6:08 pm
by Matt1223
Octocontrabass wrote:Turn up the log level in Bochs and see what messages it outputs. It might tell you what you're doing wrong that way.
Do you mean I should check out bochsout.txt file? I don't see anything interesting in there... Maybe I just don't know what to look for.

Re: ATA drive LBA48 read

Posted: Fri Mar 03, 2023 6:17 pm
by Octocontrabass
That's where the log will be, once you enable more logging in your bochsrc.

Re: ATA drive LBA48 read

Posted: Fri Mar 03, 2023 6:44 pm
by Matt1223
Octocontrabass wrote:That's where the log will be, once you enable more logging in your bochsrc.
I found the problem. I was getting such message in the log:

12780670378e[DEV ] write to port 0x01f6 with len 2 ignored

Apparently I was using outw instead of outb in one spot.

Thank you for help.