How to read 48 bit IDE registers

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
maximus
Posts: 2
Joined: Sun Oct 15, 2017 6:19 pm

How to read 48 bit IDE registers

Post by maximus »

I am using the following C code in Linux to attempt to read 48 bit IDE registers after a command. But I am not getting proper results for the high registers, only the low ones. The high registers seem to just be duplicate of the low registers, when I know the data to be be different. What am I doing wrong to read them? I can write high and low just fine.

error = inb(reg_base+1);
count_high = inb(reg_base+2);
lba_low_high = inb(reg_base+3);
lba_mid_high = inb(reg_base+4);
lba_high_high = inb(reg_base+5);
count_low = inb(reg_base+2);
lba_low_low = inb(reg_base+3);
lba_mid_low = inb(reg_base+4);
lba_high_low = inb(reg_base+5);
device = inb(reg_base+6);
status = inb(reg_base+7);
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: How to read 48 bit IDE registers

Post by jnc100 »

You need to set the high order bit (bit 7) of the device control register to 1 to read the high order bytes in command responses. This is not required when writing 48-bit LBAs. You also shouldn't need to reset it to zero again after reading the high order bytes as this is done for you on the next write to a command register.

I'm not sure how you obtain the IO address of the control registers on Linux, but once you have it, you would want to do something like:

Code: Select all

error = inb(reg_base+1);
count_low = inb(reg_base+2);
lba_low_low = inb(reg_base+3);
lba_mid_low = inb(reg_base+4);
lba_high_low = inb(reg_base+5);
outb(ctrl_base, 0x80);
count_high = inb(reg_base+2);
lba_low_high = inb(reg_base+3);
lba_mid_high = inb(reg_base+4);
lba_high_high = inb(reg_base+5);
device = inb(reg_base+6);
status = inb(reg_base+7);
Bear in mind that many commands do not return a sector count value. The setting of the device control register to 0x80 also has the side effect of enabling interrupts although these are probably already enabled anyway.

Regards,
John.
maximus
Posts: 2
Joined: Sun Oct 15, 2017 6:19 pm

Re: How to read 48 bit IDE registers

Post by maximus »

Wow, I can't believe I missed that. And I was just looking through the documentation on here where that is shown before I posted. Thank you very much, I was stumped.

As for interrupts, I do my best to keep them turned off for my purpose, so I am sending 0x02 to the control base address before the command, as bit 1 is supposed to tell the drive to suppress interrupts. I may want to send that again after setting the high order bit and reading the high order registers just to be safe. I also read the control base address (alt status) afterwards which I thought was also supposed to clear any interrupts. All of this is done with the drive (port) disabled from the Linux OS during boot so that it can be worked with without the OS interfering.

Thanks again very much :)
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to read 48 bit IDE registers

Post by Octocontrabass »

maximus wrote:As for interrupts, I do my best to keep them turned off for my purpose, so I am sending 0x02 to the control base address before the command, as bit 1 is supposed to tell the drive to suppress interrupts.
In that case, you can send 0x82 to leave interrupts disabled while you're reading the high-order bytes.
Post Reply