Page 1 of 2
How to find the maximum size of a hard disk?
Posted: Thu Aug 02, 2007 2:15 pm
by Lprogster
Using the tutorial on OS Dever for LBA HD access I have created LBA 48 functions to load and save a sector on the hard disk. However, how can I tell how much space is available? Is there any port IO to do this?
Also, am I right in think that trying to access a sector out of bounds results in an out of bounds fault?
Thanks,
Lster
Posted: Thu Aug 02, 2007 2:34 pm
by Pavia
It easy. Read ATA/ATAPI scpecification.
if disk support LBA48 then
Do comand "READ NATIVE MAX ADDRESS EXT"=$27
Wite comand complete.
Read from registers "LBA Low", "LBA Mid" , "LBA High"
Set HOB to 1. And read again "LBA Low", "LBA Mid" , "LBA High".
Command Block
Code: Select all
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Register | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Error |na |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Sector Count |Reserved |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA Low |HOB=0 |Native max address LBA (7:0) |
|LBA Low |HOB=1 |Native max address LBA (31:24) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA Mid |HOB=0 |Native max address LBA (15:8) |
|LBA Mid |HOB=1 |Native max address LBA (39:32) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA High|HOB=0 |Native max address LBA (23:16) |
|LBA High|HOB=1 |Native max address LBA (47:40) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Device |obs | na | obs | DEV | Reserved |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Status |BSY |DRDY | DF | na | DRQ | na | na | ERR |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
Control Block
Code: Select all
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Register | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Device Control | HOB | r | r | r | r | SRST| nIEN| 0 |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
if disk not support LBA48 use
READ NATIVE MAX ADDRESS=0F8h
Code: Select all
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Register | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Error |na |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Sector Count |na |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA Low |Native max address LBA (7:0) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA Mid |Native max address LBA (15:8) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|LBA High |Native max address LBA (23:16) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Device |obs | na | obs | DEV | LBA (27:24) |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
|Status |BSY |DRDY | DF | na | DRQ | na | na | ERR |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+
Also, am I right in think that trying to access a sector out of bounds results in an out of bounds fault?
Yes rightly.
Posted: Fri Aug 03, 2007 2:09 am
by Lprogster
[EDIT]
Thank you lots,
Lster
Posted: Fri Aug 03, 2007 3:25 am
by XCHG
You must use the "READ NATIVE MAX ADDRESS" command with the value of 0xF8. You have to write this value to the COMMAND register of either the Primary or the Secondary IDE controller. The Primary IDE Controller's base port is located at 0x01F0 and the Secondary IDE's base port is at 0x0170.
The offset of the COMMAND register from the base port of either the Primary or the Secondary IDE Controllers is +7. So if you want to find the COMMAND register of the Primary IDE Controller just do this:
0x01F0 + 7 = 0x01F7 = The COMMAND register of the Primary IDE Controller
Now you have to specify which IDE Device on the selected IDE Controller you want to send the "READ NATIVE MAX ADDRESS" to. This is done by setting or clearing the DEV bit in the Device/Head register of the selected IDE Controller. If DEV is 0 then it means DRIVE0 and if it is set, it will be DEV1.
After sending the "READ NATIVE MAX ADDRESS" to the IDE Controller, you will be given the MAX LBA address in various IDE registers like the Sector Number (LBA 0:7) and etc. I recommend that you
read the ATA specifications at T13.
Good luck.
Posted: Fri Aug 03, 2007 7:16 am
by Lprogster
I can't figure this out. A small code example would be great, if possible.
Thank you for you help,
Lster
Posted: Fri Aug 03, 2007 10:08 am
by Pavia
It my mistake 27 is hexadecimal
Code: Select all
#define DRDY 0x40
#define BSY 0x80
#define HOB 0x80
#define Sector_Count 2
#define LBA_Low 3
#define LBA_Mid 4
#define LBA_High 5
#define Device 6
#define Status 7
#define Command 7
#define Device_Control 2
unsigned int d=0x1F0; //for example
unsigned int dd=0x3F4;
char Dev=0; // 0-Master 1-Slave
char LBA48=0;
unsigned long long Max_LBA;
outportb(d+6, (Dev << 4) + (1 << 6)); //Select Device and set LBA
while (inportb(d+Status) & DRDY == 0) ;
// Test device is ready to do comand
if (LBA48 !=0) {
outportb(d+Command, 0x27); //READ NATIVE MAX ADDRESS EXT
while (inportb(d+Status) & BSY != 0) {};
// wait command completed
Max_LBA = (unsigned long long )inportb(d+LBA_Low);
Max_LBA += (unsigned long long )inportb(d+LBA_Mid) <<8;
Max_LBA += (unsigned long long )inportb(d+LBA_High) <<16;
outportb(dd+Device_Control, HOB); // Set HOB to 1
Max_LBA += (unsigned long long )inportb(d+LBA_Low)<<24;
Max_LBA += (unsigned long long )inportb(d+LBA_Mid) <<32;
Max_LBA += (unsigned long long )inportb(d+LBA_High) <<40;
} else {
outportb(d+Command, 0xF8); //READ NATIVE MAX ADDRESS
while (inportb (d+Status) & BSY != 0) ;
// wait command completed
Max_LBA = (unsigned long long )inportb(d+LBA_Low);
Max_LBA += (unsigned long long )inportb(d+LBA_Mid) <<8;
Max_LBA += (unsigned long long )inportb(d+LBA_High) <<16;
Max_LBA += ((unsigned long long )inportb(d+Device) & 0xF) <<24;
}
Test for error don't add.
Posted: Fri Aug 03, 2007 10:56 am
by Lprogster
I think it is working great now! In the code you gave me, is Max_LBA the maximum sector of the HD or the size of HD in bytes?
Thanks,
Lster
Posted: Fri Aug 03, 2007 12:30 pm
by Pavia
Max_LBA is maximum sector. Multiplication Max_LBA on sector size,512 byte to have HD size in bytes.
Posted: Sat Aug 04, 2007 2:21 am
by Lprogster
I think there is a problem then - though I can't see what it is. My code gives me huge numbers that I am sure are wrong. I am testing using Qemu so isn't my HD the image file I create? In which case it should only be 234 sectors.
This is my code:
...
It's aim is to use LBA 48 to find the maximum sector for the first HD. I'm confused - what's wrong with my code?
Thank you lots,
Lster
Posted: Sat Aug 04, 2007 12:06 pm
by Lprogster
Just say if you need more information. As I say though, I just can't see what's wrong with my code - could Pavia's code have a bug in it? I feel so close to getting this working!
Posted: Sat Aug 04, 2007 2:32 pm
by Pavia
I'm think the bag of QEMU.
Posted: Sun Aug 05, 2007 2:23 am
by Lprogster
Do you mean, you think that Qemu is wrong?
Posted: Sun Aug 05, 2007 3:06 am
by Brendan
Hi,
I'm just curious, but did you check if the hard drive actually supports LBA-48? I'd assume that a 117 KB hard disk might not support it....
Cheers,
Brendan
Posted: Sun Aug 05, 2007 3:15 am
by Lprogster
As I said I'm testing using Qemu. Also, my read and write functions use LBA 48 - they work great.
Posted: Sun Aug 05, 2007 4:33 am
by Lprogster
Is the code I posted above correct? Should it work?