ATA drive LBA48 read

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Matt1223
Member
Member
Posts: 45
Joined: Mon Jul 30, 2018 2:58 am

ATA drive LBA48 read

Post 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;
}
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: ATA drive LBA48 read

Post 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...
Matt1223
Member
Member
Posts: 45
Joined: Mon Jul 30, 2018 2:58 am

Re: ATA drive LBA48 read

Post 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.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: ATA drive LBA48 read

Post by Octocontrabass »

That's where the log will be, once you enable more logging in your bochsrc.
Matt1223
Member
Member
Posts: 45
Joined: Mon Jul 30, 2018 2:58 am

Re: ATA drive LBA48 read

Post 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.
Post Reply