qwn wrote:
But all the data which I receive seems to be 0xffff.
Hi,
When reading from a non-existent port, the return value is usually 0xFF. You are probably reading from a non-existent hard drive port address.
Some time ago, years in fact, you could assume there was a hard drive at address 0x1F0. However, this was because of an ISA bus. The ISA bus has been gone for some time and only emulated by newer hardware. In fact, the newer hardware (PCI and the BIOS) would even default the first hard drive to 0x1F0 for this backward compatibility. However, now you cannot and should not rely upon this. You really need to enumerate the PCI(e) and see if and where a hard drive exists. In fact, it could even be an non ATA emulating AHCI controller.
qwn wrote:
I have checked the boot_disk value in my boot loader. and the value of dl is 080h so qemu does boot from hard disk.
The 0x80 in DL has absolutely nothing to do with the type of hard drive and location of this drive. This is a firmware (in this case, the Legacy BIOS) identity byte.
How new/old is your test machine. Are you using an actual test machine or are you using an emulator such as QEMU or Bochs? If you are using one of these emulators, they do, be default, emulate the ISA address of 0x1F0.
Please don't think I am criticizing your code with the following questions, I am just curious.
Why do you call assembly routines for your ata_disk_wait() functions? A good C compiler can and probably will produce as good or better code than you can. Also, by doing it the way you have, there is no way of changing the location of the port address. i.e.: You have hard-coded the address.
Does your insw() function actually use the insw instruction? If so, this isn't recommended. There is not enough of a delay between the reading of each word with this instruction. A loop and the single inpw instruction is required/recommended.
When you wait for the controller to not be busy *and* for the DRQ bit to be set, you can do this with one read while in a loop. No need to check for busy, then check for DRQ. What if the busy bit becomes set between the function calls? i.e.: Check for non-busy *and* DRQ asserted at the same time.
While in real mode, the following
Code:
mov [010000h], al
won't do what you think it does. In fact, the assembler should return an error. If it does not, it is truncating the value to 0000h and depending what DS points to, may be overwriting your IVT.
Please read up on 16-bit real-mode, the mode the CPU boots into, and also how to enumerate the PCI.
One more thing, if this is actually your boot code, why not let the firmware (Legacy BIOS or EFI) do the disk access for you? I.e: Call the BIOS to read from the disk?
- Ben
http://www.fysnet.net/osdesign_book_series.htm