Page 1 of 1
ATA driver help
Posted: Tue May 10, 2005 3:49 pm
by Anthony
I have been reading the specs at this website on programming for the ATA controllers.
http://www.nondot.org/sabre/os/files/Disk/IDE-tech.html
and i have read taht one of the first things i need to do is issue the Identify Drive command. so i assume by looking at those specs, i need to do something similar to:
Code: Select all
oubportb(0x1f6, 0xb0); // selects drive 0
outportb(0x1f7, 0xec); //identify drive command
from here it says it will set BUSY, store the required info into the sector buffer (?), set DRQ, and generate an interrupt. Then i am supposed to read the info from the sector buffer.
my question is...1. i assume i need to have the IDE irq interrupt handlers read from the sector buffer whenever the irq is triggered. but where do i read the data from. where is this 'sector buffer' that the document speaks of.
i do see the Read buffer command (0xe4), so i assume i need to use that? it says that also will set BUSY, then set up the sector buffer for a read, set DRQ, clear BUSY, and generate an interrupt.
So i would have 2 interrupts generated in order to read the info from the Identify Drive command? and even after executing the read buffer command...i still don't know where i read in the data in the sector buffer. all the read buffer command says is that i can read up to 512bytes from the sector buffer? i am sorry if this is a bit of a ramble. thanks for any help in advance. :)
Re:ATA driver help
Posted: Wed May 11, 2005 12:28 am
by DennisCGc
Hi,
my question is...1. i assume i need to have the IDE irq interrupt handlers read from the sector buffer whenever the irq is triggered. but where do i read the data from. where is this 'sector buffer' that the document speaks of.
When you do those commands, the IDE controller calls either IRQ 14 or IRQ 15, depends what controller you used. (IRQ 14 is the primary, 15 is the secondary)
So you have to put on IRQ 14 the handler who reads the bytes.
You can read from it by using:
Code: Select all
mov dx,1f0h ;base of IDE controller
in ax,dx ;read 16 bit (2 bytes) of the harddisk, whether it's the identify command or just a sector
It's just an example, but it should you give an idea
(Yes, the Identify command also triggers this IRQ and then you can read the 512 bytes, just like you read a sector)
HTH,
DennisCGc.
PS. When you read a sector or use the ID command, the IDE controller just triggers ONE IRQ.
Re:ATA driver help
Posted: Wed May 11, 2005 12:59 am
by Anthony
ok, thanks. so when i read in from the drive, i read in 2 bytes at a time, do i just loops the inportw() to read 256 times in a row to read the whole sector?
Re:ATA driver help
Posted: Wed May 11, 2005 1:27 am
by B.E
you can also you DMA. I don't know how. Try reading an official document about the controller. The tutorial that you are reading is very confusing
Re:ATA driver help
Posted: Wed May 11, 2005 2:12 am
by Anthony
ugh...just typed a huge thing and the browser messed up when posting. so here we go one more time...
i created a struct to hold all the info returned from the identify drive command. here is some code i whipped up really quick to test that the command was working.
Code: Select all
ataidentify_t *ata_id; //struct to hold returned info
unsigned char ata_id_data[512]; //512byte buffer to read data into;
unsigned short *data = &ata_id_data[0]; //pointer to data buffer
outportb(0x1f6, 0xb0); //select drive 0
while((inportb(0x1f7) & 0x80)); //BUSY clear
while(!(inportb(0x1f7) & 0x40)); //DRDY set
outportb(0x1f7, 0xec); //indetify drive command
while((inportb(0x1f7) & 0x80)); //BUSY clear
while(!(inportb(0x1f7) & 0x40)); //DRDY set
for(i = 0; i<256; i++)
{
*data = inportw(0x1f0); // read in 2bytes into buffer
data++;
}
ata_id = &ata_id_data[0];
k_printf("ata model: %s\n", ata_id->model;
unfortunantly i seem to not be getting data when i read or something. as anything i try to print out from the struct is just blank. i even tried printing the entire 512byte buffer as ascii, and it still prints nothing.
i take it i'm not doing this correctly?
also, for future setup, i decided to make sure that it was firing the IRQ's, so i unmask irq's 14 and 15, but my ISR never gets triggered? which i find very odd. i know that my IDT and ISR's are working though because my keyboard driver and PIT works just fine. thanks for any help.
Re:ATA driver help
Posted: Wed May 11, 2005 11:28 am
by DennisCGc
Hi,
Anthony wrote:
Code: Select all
ataidentify_t *ata_id; //struct to hold returned info
unsigned char ata_id_data[512]; //512byte buffer to read data into;
unsigned short *data = &ata_id_data[0]; //pointer to data buffer
outportb(0x1f6, 0xb0); //select drive 0
while((inportb(0x1f7) & 0x80)); //BUSY clear
while(!(inportb(0x1f7) & 0x40)); //DRDY set
outportb(0x1f7, 0xec); //indetify drive command
while((inportb(0x1f7) & 0x80)); //BUSY clear
while(!(inportb(0x1f7) & 0x40)); //DRDY set
for(i = 0; i<256; i++)
{
*data = inportw(0x1f0); // read in 2bytes into buffer
data++;
}
ata_id = &ata_id_data[0];
k_printf("ata model: %s\n", ata_id->model;
There's something wrong with your code.
IIRC if you read from the status flag WHILE an interrupt is called/is going to be called the interrupt might have been died.
To avoid this, use 0x3f6.
also, for future setup, i decided to make sure that it was firing the IRQ's, so i unmask irq's 14 and 15, but my ISR never gets triggered? which i find very odd. i know that my IDT and ISR's are working though because my keyboard driver and PIT works just fine. thanks for any help.
This is weird, maybe because of the mentioned problem ? Please try the first solution.
HTH,
DennisCGc.
Re:ATA driver help
Posted: Fri May 13, 2005 3:37 pm
by Anthony
ok, i read my status from 0x3f6 now. so it shouldn't clear the interrupt. and also, the nEIN bit has been set. but...still no interrupt. and i still can't get any actualy data returned from the Identify Drive command, from either bochs or vmware.
and that is my main concern.
Re:ATA driver help
Posted: Sat May 14, 2005 3:49 am
by DennisCGc
Hi,
Anthony wrote:
ok, i read my status from 0x3f6 now. so it shouldn't clear the interrupt. and also, the nEIN bit has been set. but...still no interrupt. and i still can't get any actualy data returned from the Identify Drive command, from either bochs or vmware.
and that is my main concern.
What is your BOCHS' configuration file then ? You actually do define a harddrive ? And I looked some information up, you want to identify the SECOND drive (Slave) of the primary controller. Maybe you wanted to do this. If so, add this:
Code: Select all
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-slave: type=disk, path="yourhdimage", cylinders=totcylinder, heads=tothead, spt=totsectorpertrack
If you didn't intend to do, I suggest you clear the 3th bit (0000b instead of 1000b) and then add:
Code: Select all
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="yourhdimage", cylinders=totcylinder, heads=tothead, spt=totsectorpertrack
if you didn't have that.
Btw, what happens if you're running this on real hardware ?
HTH,
DennisCGc.