Page 1 of 1

Simple PIO Driver

Posted: Sat Sep 17, 2011 6:18 pm
by mark3094
I have just started to write a PIO driver (haven't done one before). I am using VMWare server, with 4 small IDE virtual hard disks.

I am starting by trying to run IDENTIFY on a drive to see what information I get back, but there seem to be some funny results.

This is what I have so far:

Code: Select all

	/*  Check if drive is busy  */
	for ( ; (inb (0x1F7) & 0x80) != 0; ) {
		printf ("Busy\n");
	}
	printf ("Not Busy\n");


	/*  Disable interrupts  */
	__asm cli;


	/*  Check if drive ready  */
	for ( ; (inb (0x1F7) & 0x40) == 0; ) {
		printf ("Not Ready\n");
	}
	printf ("Ready\n");


	/*  Identify command - Transferrs data into the hard drive's cache  */
	outb (0x1F6, 0x0);
	outb (0x1F7, 0xEC);
	for ( ; (inb (0x1F7) & 0x8) == 0; ) {
		printf ("Waiting\n");
	}
	printf ("Identify complete...\n");

	
	/*  Read data  */
	printf ("Word 0 - %u\n", inw(0x1F0));
	printf ("Word 1 - %u (cylinders)\n", inw(0x1F0));
	printf ("Word 2 - %u (unused)\n", inw(0x1F0));
	printf ("Word 3 - %u (heads)\n", inw(0x1F0));
	printf ("Word 4 - %u (unused)\n", inw(0x1F0));
	printf ("Word 5 - %u (unused)\n", inw(0x1F0));
	printf ("Word 6 - %u (sectors per track)\n", inw(0x1F0));
This is telling me that the disk has 4294967295 cylinders, 15 heads, and 63 sectors, which doesn't seem right at all.

My inw function looks like this (extern char inw (uword port);):

Code: Select all

_inw:
	PUSH	EDX
	PUSH	EBP
	MOV		EBP, ESP

	XOR		EAX, EAX
	MOV		DX, [EBP + 12]					;  Port number
	IN		AX, DX

	POP		EBP
	POP		EDX
RET

Any ideas where I have gone wrong on this?

Re: Simple PIO Driver

Posted: Sat Sep 17, 2011 7:52 pm
by mark3094
It looks like word 54 is 'number of current cylinders', which returns '67'.

What's the difference between word 54 and word 1?

Re: Simple PIO Driver

Posted: Sat Sep 17, 2011 8:48 pm
by gerryg400
The ATA specs change over time and some features (like CHS addressing) are dropped from time to time. Modern drives use LBA and some (most ? all ?) don't support CHS mode. The drive size can be read from words 60 and 61. If LBA is supported then the words you are reading may be obsolete.

Re: Simple PIO Driver

Posted: Sun Sep 18, 2011 1:06 am
by mark3094
I see

Which version of ATA should I be using? I thought I had to start with ATA-1, and find out what the drive was capable of, then implement features as required...
Should I just start with the most recent version?

Re: Simple PIO Driver

Posted: Sun Sep 18, 2011 1:49 am
by mark3094
If anyone comes across this thread, take note that my declaration of inw is wrong:
mark3094 wrote:My inw function looks like this (extern char inw (uword port);

It should be:

Code: Select all

extern short int inw (uword port);
Where a short int is 16-bit long.
Hope my original post doesn't throw anyone off track...

Re: Simple PIO Driver

Posted: Sun Sep 18, 2011 5:55 am
by gerryg400
As a simple test I created a 1 GB IDE drive in VMWare. I used an identify command and got the following which seems correct.

Code: Select all

Physical drive 0 VMware Virtual IDE Hard Drive           
cyls=2080 head=16 sec=63
I tried a bigger 100GB drive and got

Code: Select all

Physical drive 1 VMware Virtual IDE Hard Drive           
cyls=16383 head=15 sec=63
This seems wrong. I suggest that you ignore the CHS values unless LBA is not supported by your drive.

Re: Simple PIO Driver

Posted: Sun Sep 18, 2011 6:14 am
by gerryg400
ata8 section 4.2 wrote:In standards ATA/ATAPI-5 and earlier, a CHS translation was defined. This translation is obsolete but if implemented it shall be implemented as defined in ATA/ATAPI-5.
and
ata5 section 6.2 wrote: All devices shall support LBA translation.
− If the device’s capacity is greater than or equal to one sector and less than or equal to 16,514,064 sectors, then the device shall support CHS translation.
− If the device’s capacity is greater than 16,514,064 sectors, the device may support CHS translation.
− If a device supports CHS translation, then, following a power-on or hardware reset, the CHS translation enabled by the device shall be the default translation.
− If a device supports CHS translation, a device may allow a host to use the INITIALIZE DEVICE PARAMETERS command to select other CHS translations.
− If a device supports CHS translation, IDENTIFY DEVICE words 1,3, and 6 shall describe the default translation, and words 53-58 shall describe the current translation.
Actually ata5 has good information for implementing a driver that works for both modern and old drives.
ata5 section 6.2.1 also wrote:If the content of words (61:60) is greater than or equal to 16,514,064 then the content of word 1 shall be equal to 16,383.
which means VMWare's drive is correct.

Re: Simple PIO Driver

Posted: Sun Sep 18, 2011 3:15 pm
by mark3094
Thankyou again. I see where I went wrong. I was reading 60:61 to get the sectors (which was returning 0:256), not 61:60, which returns 256:0, or 16,777,216 (8GB - the size of my VMWare disk :D )

Suddenly a hard disk driver doesn't seem as hard as it once did.

I will use ATA-5 for now, and 'upgrade' to the most recent one when I implement DMA.

Once again, thanks for you assistance

Re: Simple PIO Driver

Posted: Mon Sep 19, 2011 3:04 pm
by mark3094
My identify command is mostly working now, however, I'm having problems selecting drives on the secondary controller.

Code: Select all

/*  Identify command - Transferrs data into the hard drive's cache  */
   outb (0x1F6, 0xA0);
   outb (0x1F7, 0xEC);
   for ( ; (inb (0x1F7) & 0x8) == 0; ) {
      printf ("Waiting\n");
   }
   printf ("Identify complete...\n");
The first outb selects the primary master. If I change the command I send to 0xB0, the primary slave is selected, and the information reported on it is correct too.

The problem is that if I use commands such as...

Code: Select all

outb (0x176, 0xA0)
outb (0x176, 0xB0)
...The primary master information is always returned. I can't see what I have wrong here. Can anyone help?

Re: Simple PIO Driver

Posted: Mon Sep 19, 2011 3:52 pm
by mark3094
Sorry, simple not-thinking-straight error.

I was selecting the secondary controller, but still sending identify commands to the primary controller.