Page 1 of 1

ATA PIO LBA48 - by Wiki

Posted: Wed Dec 09, 2009 4:13 pm
by djsilence
Hi. I read Wiki chapter about ATA PIO. It has explained how to read/write hdd via chs, lba24 and lba48. Actualy CHS is not interesting to me, LBA24 I have already implemented. But the problem whas that If I want to read sector with number > 0x1000000 I get nothing because 0xFFFFFF - it is high level of 24bit value. But I need to load sectors of HDD at such addresses as tenth and hundreds of GB. For this I have to use LBA48. So:

when I tried to do reading via LBA24:

Code: Select all

void read_24()
{
   uint32_t LBA = 0x3F;                           //let's say I need to read this sector.
   uint8_t slavebit = 0;                            //I'm using master drive.
   uint8_t count = 1;

   outb(0x1F6, 0xE0 | (slavebit << 4) | ((LBA >> 24) & 0x0F));
   outb(0x1F1, 0x00) ;
   outb(0x1F2, (unsigned char) count);
   outb(0x1F3, (unsigned char) LBA));
   outb(0x1F4, (unsigned char)(LBA >> 8));
   outb(0x1F5, (unsigned char)(LBA >> 16));
   outb(0x1F7, 0x20);
   _asm {                                                  //it is pool... I used it from my driver because it is written in ASM, but used by C.
                mov edx, 0x1F7
       hddwait:
   		in    	al,dx
   		test  al,128
   		jnz   	hddwait
   }
   uint16_t v = inportw(0x1F0);                 //to check reading enough to read one value.
   printf("0x%h", v);                                    //and right value is displayed (according to my hex-redactor   
}
this is code for LBA24 and it works.

when I try to read via LBA48:

Code: Select all

void read_48()
{
   uint8_t slavebit = 0;                            //I'm using master drive.

   outb(0x1F6, 0x40 | (slavebit << 4));
   outb (0x1F2, 0x00);  //this is count high value, as I'm reading 1 sector - high value is 0.
   outb (0x1F3, 0x00);  //i'm reading sector 0x3F, that's why LBA2, LBA3, LBA4, LBA5, LBA6 - are zeros.
   outb (0x1F4, 0x00);
   outb (0x1F5, 0x00);
   outb (0x1F2, 0x01);
   outb (0x1F3, 0x3F);  //LBA1
   outb (0x1F4, 0x00);
   outb (0x1F5, 0x00);
   outb(0x1F7, 0x24);
   _asm {                                                  //it is pool... I used it from my driver because it is written in ASM, but used by C.
                mov edx, 0x1F7
       hddwait:
   		in    	al,dx
   		test  al,128
   		jnz   	hddwait
   }
   uint16_t v = inportw(0x1F0);                 //to check reading enough to read one value.
   printf("0x%h", v);                                    //and right value is displayed (according to my hex-redactor   
}
in this case I get 0xFFFF. If I know right - byte value 0xFF (or word 0xFFFF, dword 0xFFFFFFFF) are kinda indicators of result.
what is wrong to read_48()?

Thanks for any help, Daniel.

Re: ATA PIO LBA48 - by Wiki

Posted: Thu Dec 10, 2009 8:13 pm
by bewing
Is this on real hardware, or on bochs?
If it is on real hardware, you are missing lots of required timing commands.

I suspect the problem is that you are not testing the DRQ bit in the asm section. The BSY bit is clearing before DRQ is set, and you are reading port 0x1f0 too soon.

Re: ATA PIO LBA48 - by Wiki

Posted: Thu Dec 10, 2009 11:57 pm
by djsilence
I'm using VMWare.

But why LBA24 works, LBA48 - doesn't?

Re: ATA PIO LBA48 - by Wiki

Posted: Fri Dec 11, 2009 5:51 am
by -m32
djsilence wrote:I'm using VMWare.

But why LBA24 works, LBA48 - doesn't?
You just got lucky.

Especially since you keep calling the first one LBA "24"

Re: ATA PIO LBA48 - by Wiki

Posted: Fri Dec 11, 2009 6:29 am
by Solar
djsilence wrote:But why LBA24 works, LBA48 - doesn't?
Because "it works" does not mean "it was done right"...