Problem with 0x1F0 and disk size..

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
danipiresk
Posts: 6
Joined: Mon Nov 30, 2009 10:40 am
Location: Florianópolis - Santa Catarina - Brasil

Problem with 0x1F0 and disk size..

Post by danipiresk »

Hi people
I am using the port 0x1F0 for get features of hard disk's, but as everyone knows the bios only supports 8gb and returns max 8063 mb.

How can I fix it?

My calc: size = (sectors per track * cylinders * heads) * 0.5) / 1024;

My code..

Code: Select all

int buscar_dispositivos_ata()
{
    printf("[SISTEMA] Buscando dispositivos ATA...\n");

    int ndispositivos = 0;

    unsigned int dados [256];
    unsigned int dados_off;
    unsigned int loop, size;

    ndispositivos = peekb(0x40, 0x75); // Byte at Segment 40H Offset 75H

    for (loop = 0; loop < ndispositivos; loop++)
    {
        while (inportb(0x1F7) != 0x50);  // Wait for controller not busy

        outportb(0x1F6, (loop == 0 ? 0xA0 : 0xB0)); // Get first/second drive

        outportb(0x1F7, 0xEC);          // Get drive info data

        while (inportb(0x1F7) != 0x58);  // Wait for data ready

        for (dados_off = 0; dados_off != 256; dados_off++) // Read "sector"
            dados[dados_off] = inportbw(0x1F0);

        hard_disks[loop].Modelo  = getascii(dados, 27, 46);
        hard_disks[loop].Serial  = getascii(dados, 10, 19);
        size = 0;
        size = ((dados[1] * dados[3] * dados[6]) * 0.5) / 1024;
        hard_disks[loop].Tamanho = tamanho;
        hard_disks[loop].Canal   = (loop == 0 || loop == 1) ? 0 : 1;
        hard_disks[loop].Drive   = (loop == 0 || loop == 2) ? 0 : 1;

        printf("DRIVE %d:\n", loop);
        printf("Modelo____________________: %s\n", getascii(dados, 27, 46));
        printf("Serial____________________: %s\n", getascii(dados, 10, 19));
        printf("Dados do HD:\n");
        printf("Tamanho___________________: %d\n", tamanho);
        printf("Cilindros_________________: %d\n", dados[1]);
        printf("Cabeças___________________: %d\n", dados[3]);
        printf("Setores por Trilha________: %d\n\n", dados[6]);
    }

    if (ndispositivos == 0)
    {
        printf("[SISTEMA] Nenhum dispositivo ATA encontrado...\n");
        return 0;
    }
    else printf("[SISTEMA] %d dispositivo(s) ATA encontrado(s)...\n", ndispositivos);

    return 1;
}
Thanks
User avatar
-m32
Member
Member
Posts: 120
Joined: Thu Feb 21, 2008 5:59 am
Location: Ottawa, Canada

Re: Problem with 0x1F0 and disk size..

Post by -m32 »

Don't use CHS values. See offsets 60-61 in the ATA spec on IDENTIFY DEVICE
danipiresk
Posts: 6
Joined: Mon Nov 30, 2009 10:40 am
Location: Florianópolis - Santa Catarina - Brasil

Re: Problem with 0x1F0 and disk size..

Post by danipiresk »

I'm wondering how to read the number of cylinders, heads and sectors in lba mode.
Do you have a link / example?
Thanks.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Problem with 0x1F0 and disk size..

Post by Owen »

You don't. You read the number of sectors total; the drive handles converting that to it's internal CHS format.
danipiresk
Posts: 6
Joined: Mon Nov 30, 2009 10:40 am
Location: Florianópolis - Santa Catarina - Brasil

Re: Problem with 0x1F0 and disk size..

Post by danipiresk »

How so?
From what I know LBA addressing is done by this formula:
(Cylinder Head * TotalCabeças +) * SetoresPorTrilha + (Sector - 1)

Well, but my problem is to calculate the size of disks larger than 8GB.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Problem with 0x1F0 and disk size..

Post by Owen »

To quote
Don't use CHS values. See offsets 60-61 in the ATA spec on IDENTIFY DEVICE
Offsets 60 and 61 give you the sector count of the disk, total. You don't touch CHS values when working with LBA - you just use numbers from 0 to count-1
User avatar
djsilence
Member
Member
Posts: 70
Joined: Wed Oct 01, 2008 11:18 am
Location: Ukraine, Kiev
Contact:

Re: Problem with 0x1F0 and disk size..

Post by djsilence »

You should not calculate anything. Read sector 0 (MBR sector) than read this struct:

Code: Select all

typedef struct
{
	unsigned char Status;
	unsigned char FHead;
	unsigned char FSector;
	unsigned char FCylinder;
	unsigned char PartitionType;
	unsigned char LHead;
	unsigned char LSector;
	unsigned char LCylinder;
	unsigned int  LBAFirstSector;
	unsigned int  NumberofBlocks;
} PartitionInfo;
This struct is used in MBR. First goes to 0x1BE. LBAFirstSector contains number of first LBA sector. Choose maximum of possible (that should be last partition), the plus to it partition's size: NumberofBlocks*0x200. You get disk size (almost: my calculations differs from reality in 5Kb, I gues I forget something else but it is tiny).

Daniel.
Don't think a ****, but in ukrainian schools English is TOO BAD!
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Problem with 0x1F0 and disk size..

Post by pcmattman »

djsilence wrote:You should not calculate anything. Read sector 0 (MBR sector) than read this struct:
<snip>
Not all disks have an MBR in their first sector. The ATA spec itself gives a method for getting the LBA count of the medium so you don't need to figure it out yourself (IDENTIFY DEVICE), the section for which in the spec has a full description of all fields returned from the command.

CHS values are available for backwards compatibility (and for any modern devices which do not support LBA, which are very rare), but are limited - as you have seen.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Problem with 0x1F0 and disk size..

Post by Owen »

And the MBR doesn't tell you the full story for 2TB+ disks
Post Reply