Read from hard drive (LBA vs CHS)

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
mangaluve
Member
Member
Posts: 110
Joined: Mon Feb 23, 2009 6:53 am

Read from hard drive (LBA vs CHS)

Post by mangaluve »

Currently I'm using the following code to read from a hard drive

Code: Select all

void read_hdd_blocks(u8int count, u8int sector, u16int cylinder, u8int *buffer)
{
	u16int i, tmpword;

	outb(0x1f6, 0x0);
	outb(0x1f2, count);
	outb(0x1f3, sector);
	outb(0x1f4, (u32int)(cylinder & 0xFF));
	outb(0x1f5, cylinder >> 8);
	outb(0x1f7, 0x20);

	while(!(inb(0x1f7) & 0x8)) {}

	for(i = 0; i < 256 * count; i++) {
		tmpword = inw(0x1F0);
		buffer[i * 2] = (unsigned char)tmpword;
		buffer[i * 2 + 1] = (unsigned char)(tmpword >> 8);
	}
}
But I've also looked at a tutorial at http://www.osdever.net/tutorials/lba.php, which seems to do it another way (using other ports). They are also using LBA addressing instead of CHS, which I would like to do aswell. But I've tried the code in the tutorial, but it does not work, nothing happens and the computer hangs. Anyone who has any comments? I used the code (following the tutorial):

Code: Select all

void read_hdd_blocks_lba(u8int drive, u8int count, u32int addr, u16int cylinder, u8int *buffer)
{
	u16int i, tmpword;

	outb(0x1F1, 0x00);
	outb(0x1f2, count);
	outb(0x1F3, (unsigned char)addr);
	outb(0x1F4, (unsigned char)(addr >> 8));
	outb(0x1F5, (unsigned char)(addr >> 16));
	outb(0x1F6, 0xE0 | (drive << 4) | ((addr >> 24) & 0x0F));
	outb(0x1f7, 0x20);

	while(!(inb(0x1f7) & 0x8)) {}

	for(i = 0; i < 256 * count; i++) {
		tmpword = inw(0x1F0);
		buffer[i * 2] = (unsigned char)tmpword;
		buffer[i * 2 + 1] = (unsigned char)(tmpword >> 8);
	}
}
[code]
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Read from hard drive (LBA vs CHS)

Post by bewing »

You are missing several bits, and the entire "head number", in the value you put into port 1f6. There is also a TON of timing-related testing that you are skipping. It would be wise of you to read the article in our wiki on ATA_PIO_Mode.
mangaluve
Member
Member
Posts: 110
Joined: Mon Feb 23, 2009 6:53 am

Re: Read from hard drive (LBA vs CHS)

Post by mangaluve »

Thanks for the link!

What do you mean by missing the head number? I have the head number in the second function (that's not working). In the first I just assume that the drive/headnumber is zero. I was just wondering if it's harder to use LBA and if I can modify the first (working) code slightly to achieve that
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Read from hard drive (LBA vs CHS)

Post by bewing »

Using LBA is much *easier*. You don't need lots of separate artificial calculations to determine the head, cyl, and sector. You don't need to worry about sector==0 errors. The bits to set in port 0x1f6 are simpler. The way you pass LBA info to the drive is almost identical to what you do for CHS.
Post Reply