Page 1 of 1

Problem with 0x1F0 and disk size..

Posted: Wed Dec 02, 2009 3:59 pm
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

Re: Problem with 0x1F0 and disk size..

Posted: Wed Dec 02, 2009 6:48 pm
by -m32
Don't use CHS values. See offsets 60-61 in the ATA spec on IDENTIFY DEVICE

Re: Problem with 0x1F0 and disk size..

Posted: Fri Dec 04, 2009 10:34 am
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.

Re: Problem with 0x1F0 and disk size..

Posted: Fri Dec 04, 2009 10:51 am
by Owen
You don't. You read the number of sectors total; the drive handles converting that to it's internal CHS format.

Re: Problem with 0x1F0 and disk size..

Posted: Fri Dec 04, 2009 11:32 am
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.

Re: Problem with 0x1F0 and disk size..

Posted: Fri Dec 04, 2009 12:08 pm
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

Re: Problem with 0x1F0 and disk size..

Posted: Sat Dec 05, 2009 6:59 pm
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.

Re: Problem with 0x1F0 and disk size..

Posted: Sun Dec 06, 2009 12:40 am
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.

Re: Problem with 0x1F0 and disk size..

Posted: Sun Dec 06, 2009 6:16 am
by Owen
And the MBR doesn't tell you the full story for 2TB+ disks