Simple OS Support

Yasin Yenidunya machka at gmail.com
Thu Mar 25 14:56:37 PDT 2010


i have chek it already, but most examples are not working i think the our
system is not capable to run that code or something like that. finally i
found an guide for it but i didn't work. here the guide
LBA HDD Access via PIO

Every operating system will eventually find a need for reliable, long-term
storage. There are only a handful of commonly used storage devices:

   -

   Floppy
   -

   Flash media
   -

   CD-ROM
   -

   Hard drive

 Hard drives are by far the most widely used mechanism for data storage, and
this tutorial will familiarize you with a practical method for accessing
them. In the past, a method known as CHS was used. With CHS, you specified
the cylinder, head, and sector where your data was located. The problem with
this method is that the number of cylinders that could be addressed was
rather limited. To solve this problem, a new method for accessing hard
drives was created: Linear Block Addressing (LBA). With LBA, you simply
specify the address of the block you want to access. Blocks are 512-byte
chunks of data, so the first 512 bytes of data on the disk are in block 0,
the next 512 bytes are in block 1, etc. This is clearly superior to having
to calculate and specify three separate bits of information, as with CHS.
However, there is one hitch with LBA. There are two forms of LBA, which are
slightly different: LBA28 and LBA48. LBA28 uses 28 bits to specify the block
address, and LBA48 uses 48 bits. Most drives support LBA28, but not all
drives support LBA48. In particular, the Bochs emulator supports LBA28, and
not LBA48. This isn't a serious problem, but something to be aware of. Now
that you know how LBA works, it's time to see the actual methods involved.

To read a sector using LBA28:

   1.

   Send a NULL byte to port 0x1F1: outb(0x1F1, 0x00);
   2.

   Send a sector count to port 0x1F2: outb(0x1F2, 0x01);
   3.

   Send the low 8 bits of the block address to port 0x1F3: outb(0x1F3,
   (unsigned char)addr);
   4.

   Send the next 8 bits of the block address to port 0x1F4: outb(0x1F4,
   (unsigned char)(addr >> 8);
   5.

   Send the next 8 bits of the block address to port 0x1F5: outb(0x1F5,
   (unsigned char)(addr >> 16);
   6.

   Send the drive indicator, some magic bits, and highest 4 bits of the
   block address to port 0x1F6: outb(0x1F6, 0xE0 | (drive << 4) | ((addr >> 24)
   & 0x0F));
   7.

   Send the command (0x20) to port 0x1F7: outb(0x1F7, 0x20);

To write a sector using LBA28:

Do all the same as above, but send 0x30 for the command byte instead of
0x20: outb(0x1F7, 0x30);

To read a sector using LBA48:

   1.

   Send two NULL bytes to port 0x1F1: outb(0x1F1, 0x00); outb(0x1F1, 0x00);
   2.

   Send a 16-bit sector count to port 0x1F2: outb(0x1F2, 0x00); outb(0x1F2,
   0x01);
   3.

   Send bits 24-31 to port 0x1F3: outb(0x1F3, (unsigned char)(addr >> 24));
   4.

   Send bits 0-7 to port 0x1F3: outb(0x1F3, (unsigned char)addr);
   5.

   Send bits 32-39 to port 0x1F4: outb(0x1F4, (unsigned char)(addr >> 32));
   6.

   Send bits 8-15 to port 0x1F4: outb(0x1F4, (unsigned char)(addr >> 8));
   7.

   Send bits 40-47 to port 0x1F5: outb(0x1F5, (unsigned char)(addr >> 40));
   8.

   Send bits 16-23 to port 0x1F5: outb(0x1F5, (unsigned char)(addr >> 16));
   9.

   Send the drive indicator and some magic bits to port 0x1F6: outb(0x1F6,
   0x40 | (drive << 4));
   10.

   Send the command (0x24) to port 0x1F7: outb(0x1F7, 0x24);

To write a sector using LBA48:

Do all the same as above, but send 0x34 for the command byte, instead of
0x24: outb(0x1F7, 0x34);



 Once you've done all this, you just have to wait for the drive to signal
that it's ready:

while (!(inb(0x1F7) & 0x08)) {}

And then read/write your data from/to port 0x1F0:

// for read:

for (idx = 0; idx < 256; idx++)

{

tmpword = inw(0x1F0);

buffer[idx * 2] = (unsigned char)tmpword;

buffer[idx * 2 + 1] = (unsigned char)(tmpword >> 8);

}

// for write:

for (idx = 0; idx < 256; idx++)

{

tmpword = buffer[8 + idx * 2] | (buffer[8 + idx * 2 + 1] << 8);

outw(0x1F0, tmpword);

}

Of course, all of this is useless if you don't know what drives you actually
have hooked up. Each IDE controller can handle 2 drives, and most computers
have 2 IDE controllers. The primary controller, which is the one I have been
dealing with thus-far has its registers located from port 0x1F0 to port
0x1F7. The secondary controller has its registers in ports 0x170-0x177.
Detecting whether controllers are present is fairly easy:

   1.

   Write a magic value to the low LBA port for that controller (0x1F3 for
   the primary controller, 0x173 for the secondary): outb(0x1F3, 0x88);
   2.

   Read back from the same port, and see if what you read is what you wrote.
   If it is, that controller exists.

 Now, you have to detect which drives are present on each controller. To do
this, you simply select the appropriate drive with the drive/head select
register (0x1F6 for the primary controller, 0x176 for the secondary
controller), wait a small amount of time (I wait 1/250th of a second), and
then read the status register and see if the busy bit is set:

outb(0x1F6, 0xA0); // use 0xB0 instead of 0xA0 to test the second drive on
the controller

sleep(1); // wait 1/250th of a second

tmpword = inb(0x1F7); // read the status port

if (tmpword & 0x40) // see if the busy bit is set

{

printf("Primary master exists\n");

}

And that about wraps it up. Note that I haven't actually tested my LBA48
code, because I'm stuck with Bochs, which only supports LBA28. It should
work, according to the ATA specification.


On Thu, Mar 25, 2010 at 11:43 PM, brad martin <emclinux at gmail.com> wrote:

> Check out osdev.org
>
> On Thu, Mar 25, 2010 at 5:41 PM, Yasin Yenidunya <machka at gmail.com> wrote:
>
>> hi all,
>>
>> i have the project that building simple operating system for university.
>> is there anyone that help me to access hard disk drive in real mode. i just
>> boot the computer in real mode. then i started to generate GDT and access
>> the hard disk drive in chs mode like c=x, h=y and s=z. i don't need to
>> partition hdd. i just need the write something on specified block like
>> "1111110111" and read it. is there any guide to help me?
>>
>> regards
>>
>>
>> --
>> machka at gmail.com
>>
>> --
>> http://linuxfromscratch.org/mailman/listinfo/lfs-support
>> FAQ: http://www.linuxfromscratch.org/lfs/faq.html
>> Unsubscribe: See the above information page
>>
>>
>
>
> --
> My site: http://www.emclinux.homelinux.com
>
> http://bccplease.com/
>
> --
> http://linuxfromscratch.org/mailman/listinfo/lfs-support
> FAQ: http://www.linuxfromscratch.org/lfs/faq.html
> Unsubscribe: See the above information page
>
>


-- 
Yasin Yenidünya machka at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfromscratch.org/pipermail/lfs-support/attachments/20100325/bab8642e/attachment.html>


More information about the lfs-support mailing list