How to find the maximum size of a hard disk?

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.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

How to find the maximum size of a hard disk?

Post 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
Pavia
Posts: 23
Joined: Mon Jun 25, 2007 2:54 pm
Location: Russia

Post 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.
Sorry, my bed english. =)
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

[EDIT]

Thank you lots,
Lster
Last edited by Lprogster on Tue Oct 23, 2007 10:49 am, edited 1 time in total.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post 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.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

I can't figure this out. A small code example would be great, if possible.

Thank you for you help,
Lster
Pavia
Posts: 23
Joined: Mon Jun 25, 2007 2:54 pm
Location: Russia

Post 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.
Last edited by Pavia on Sun Aug 05, 2007 11:49 am, edited 1 time in total.
Sorry, my bed english. =)
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post 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
Pavia
Posts: 23
Joined: Mon Jun 25, 2007 2:54 pm
Location: Russia

Post by Pavia »

Max_LBA is maximum sector. Multiplication Max_LBA on sector size,512 byte to have HD size in bytes.
Sorry, my bed english. =)
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post 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
Last edited by Lprogster on Sun Aug 05, 2007 9:54 am, edited 1 time in total.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post 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!
Pavia
Posts: 23
Joined: Mon Jun 25, 2007 2:54 pm
Location: Russia

Post by Pavia »

I'm think the bag of QEMU.
Sorry, my bed english. =)
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

Do you mean, you think that Qemu is wrong?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

As I said I'm testing using Qemu. Also, my read and write functions use LBA 48 - they work great.
Lprogster
Member
Member
Posts: 174
Joined: Tue Nov 14, 2006 11:59 am

Post by Lprogster »

Is the code I posted above correct? Should it work?
Post Reply