Questions about Hard Disk Driver (and drivers in general)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
fireshadow4126
Posts: 15
Joined: Thu Aug 19, 2010 2:22 am
Location: USA

Questions about Hard Disk Driver (and drivers in general)

Post by fireshadow4126 »

Hello,

I've been attempting to add device driver support to my OS, and I've started with the hard disk. I looked at several articles on the wiki and downloaded some documentation, but my driver code doesn't work (currently all I want to do is send an IDENTIFY command and get the disk working.) I've attached the driver code and the relevant header file that gets included from system.h. What happens exactly is that I boot my OS from an iso in VirtualBox (the iso uses GRUB with stage2_eltorito), and my OS boots fine. But when I call hd_install(), it hangs at the while loop forever. I have added a virtual hard-disk in VirtualBox.

What I'm wondering is, is there any setup I have to do on the hard drive for it to be visible to the OS? Perhaps like putting some form of bootsector on it? I don't know, so...

Also, and this relates to drivers in general, it seems that a good kernel detects the hardware and then loads the specific driver as a kernel module. However, where does it find this kernel module? It seems that on Linux and Windows, for instance, the drivers live on the filesystem, but to get a filesystem working, I would need a hard-disk driver working, which leads back to the beginning of my problem.

Thanks in advance!
Attachments
hd.h
Driver header file.
(1.97 KiB) Downloaded 92 times
hd.c
Driver code.
(1.37 KiB) Downloaded 81 times
"Welcome to the desert... of the real." - Morpheus, The Matrix.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Questions about Hard Disk Driver (and drivers in general

Post by AJ »

Hi,
fireshadow4126 wrote:What I'm wondering is, is there any setup I have to do on the hard drive for it to be visible to the OS? Perhaps like putting some form of bootsector on it? I don't know, so...
No - I haven't looked at your code, but you should just be able to read straigt from the drive (after initialising the controller...).
Also, and this relates to drivers in general, it seems that a good kernel detects the hardware and then loads the specific driver as a kernel module. However, where does it find this kernel module? It seems that on Linux and Windows, for instance, the drivers live on the filesystem, but to get a filesystem working, I would need a hard-disk driver working, which leads back to the beginning of my problem.
Some OSes deal with this by having an initial RAM disk containing a basic subset of drivers that is loaded by the OS loader. Alternatively, you could have a basic read-only FS driver which can load other drivers. It is often possible to do this in a tiny abount of code. For example, a 512b FAT12 boot loader can easily load several files in to memory. This is also a good solution if you know what disk you are booting from, for example a CD.

Cheers,
Adam
fireshadow4126
Posts: 15
Joined: Thu Aug 19, 2010 2:22 am
Location: USA

Re: Questions about Hard Disk Driver (and drivers in general

Post by fireshadow4126 »

This is also a good solution if you know what disk you are booting from, for example a CD.
Then the question is, how would the operating system know how to load from the CD? I know that it's simply Survive.iso, but I don't really think it's that easy. I would guess that I would need a CD driver, but isn't that usually part of the hard disk driver?

...This is going to be complicated.
Alternatively, you could have a basic read-only FS driver which can load other drivers.
I think this might be a stupid question, but would this FS driver actually be part of the kernel (not a module), or would it be a module loaded from the boot drive?

Thanks for your reply.
"Welcome to the desert... of the real." - Morpheus, The Matrix.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Questions about Hard Disk Driver (and drivers in general

Post by AJ »

fireshadow4126 wrote:Then the question is, how would the operating system know how to load from the CD? I know that it's simply Survive.iso, but I don't really think it's that easy. I would guess that I would need a CD driver, but isn't that usually part of the hard disk driver?
The method that I used is that my iso9660 boot loader uses int 0x13 extended read (function 0x42) to load the kernel and an initial RAM disk. The only drivers that are statically linked with the kernel is the RAMDisk driver and the RAMDiskFS driver. As long as the initRD contains the "proper" ATA/PI drivers, your kernel can load these from the initial RAMDisk and then load all other drivers from the physical CD rather than the RAM Disk. You have the option of providing a different RAMDisk for each boot medium, or could have a larger RAMDisk which is used regardless of the boot medium and contains all your storage drivers.

If you have an ACPI base driver that does all your device detection, you may also waht that on the RAM disk. I see 2 options:
1. Just have the storage drivers on the RAMDisk and either discard these boot-time drivers once the kernel is up and running, when you start device detection from scratch again.
2. Have an ACPI driver on your RAMDisk which does your device detection, is intelligent enough to load storage drivers first and then proceeds with loading other drivers from elsewhere.
I think this might be a stupid question, but would this FS driver actually be part of the kernel (not a module), or would it be a module loaded from the boot drive?
Entirely up to you. If you want, you can statically link all your FS and storage device drivers with the core kernel. Simplicity at the expense of kernel file size / having to recompile every time you change the drivers / less easy driver/kernel isolation.

HTH,
Adam
fireshadow4126
Posts: 15
Joined: Thu Aug 19, 2010 2:22 am
Location: USA

Re: Questions about Hard Disk Driver (and drivers in general

Post by fireshadow4126 »

The method that I used is that my iso9660 boot loader uses int 0x13 extended read (function 0x42) to load the kernel and an initial RAM disk.
OK, so is this possible with GRUB? If so, how?
"Welcome to the desert... of the real." - Morpheus, The Matrix.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Questions about Hard Disk Driver (and drivers in general

Post by AJ »

Hi,

Take a look at the multiboot(1 or 2) specification, specifically the config files - in addition to loading the kernel, GRUB will load modules for you. Simply load the initrd as a module. For GRUB2 there is a proper initrd option.

Some people take this a stage further - the "kernel" they specify is actually a second stage loader (which may change video mode, switch to 64 bit mode which GRUB legacy cannot do etc...) and the kernel proper can be loaded as a module which is then relocated and run by this second stage loader.

Cheers,
Adam

[edit]see http://www.gnu.org/software/grub/manual ... figuration.[/edit]
fireshadow4126
Posts: 15
Joined: Thu Aug 19, 2010 2:22 am
Location: USA

Re: Questions about Hard Disk Driver (and drivers in general

Post by fireshadow4126 »

OK thanks a lot.

[edit]But this doesn't solve my problem with IDENTIFY in my hard disk driver, *sigh*[/edit]
"Welcome to the desert... of the real." - Morpheus, The Matrix.
Luns
Member
Member
Posts: 56
Joined: Sun May 01, 2011 12:15 am

Re: Questions about Hard Disk Driver (and drivers in general

Post by Luns »

I just had time to take a quick look at your code, but it looks like you only test for the primary drive on the primary bus. You should check for at least the first four possibilities of drives (primary/secondary drive on primary/secondary bus).
fireshadow4126
Posts: 15
Joined: Thu Aug 19, 2010 2:22 am
Location: USA

Re: Questions about Hard Disk Driver (and drivers in general

Post by fireshadow4126 »

I would, but it specifically says in VirtualBox that the virtual hard drive is the master on the Primary bus.
"Welcome to the desert... of the real." - Morpheus, The Matrix.
MihailB
Posts: 17
Joined: Thu Sep 08, 2011 7:32 am
Location: Romania
Contact:

Re: Questions about Hard Disk Driver (and drivers in general

Post by MihailB »

fireshadow4126 wrote:I've been attempting to add device driver support to my OS
....
But when I call hd_install(), it hangs at the while loop forever.

....but to get a filesystem working, I would need a hard-disk driver working, which leads back to the beginning of my problem.
...
Thanks in advance!
You are doing this :

Code: Select all

void send_command(unsigned int number, unsigned int flags)
{
	switch (number)
	{
		case ATA_IDENTIFY:
		{
                                      ....
                                      .... 
			unsigned char status = inportb(ATA_COMMAND(controller));
			if (status == 0)
			{
				puts("Drive does not exist.");
			}
			unsigned char st[32] = { '\0' };
			while ((status = inportb(ATA_COMMAND(controller))) & (1 << ATA_BSY))
			{
				;
			}
			
		}
	}
}
Your problem is this one (where it loops for ever):

Code: Select all

			while ((status = inportb(ATA_COMMAND(controller))) & (1 << ATA_BSY))
			{
				;
			}
pooling forever the status will HANG UP if there is no hard disk installed at that ide slot !
while ((status = inportb(ATA_COMMAND(controller))) & (1 << ATA_BSY)) { ; };
if there's a CD/DVD drive your statement will loop for ever (or for no drive)!

Do this
and before sending CMD:
int i=10000; while ((inportb(ATA_COMMAND(controller))!=0x50)&&(i>0)) { i--; };
^^0x50 (wait until drive not BSY)
(after sending CMD):
i=10000; while ((inportb(ATA_COMMAND(controller))!=0x58)&&(i>0)) { i--; };
^^0x58 (wait until data RDY)


And also (!) you should check status BEFORE you want to send CMD to drive, but again, don't
loop for ever (!)

SO :

Code: Select all

...
...
...
...
...
                                      int i;
			unsigned char selector = (flags & (1 << ATA_SLAVE)) ? 0xB0 : 0xA0;
			unsigned char controller = (flags & (1 << ATA_CONTROLLER)) ? PRIMARY_BASE : SECONDARY_BASE;
                                       i=10000;  
                                      while ((inportb(ATA_COMMAND(controller))!=0x50)&&(i>0)) {  i--; };
			outportb(ATA_DRIVE(controller), selector);
			outportb(ATA_SECTOR_COUNT(controller), 0);
			outportb(ATA_SECTOR_NUM(controller), 0);
			outportb(ATA_CYLINDER_LOW(controller), 0);
			outportb(ATA_CYLINDER_HI(controller), 0);
			outportb(ATA_COMMAND(controller), 0xEC);
			unsigned char status = inportb(ATA_COMMAND(controller));
			if (status == 0)
			{
				puts("Drive does not exist.");
			}
			unsigned char st[32] = { '\0' };
			i=10000;  
                                      while ((inportb(ATA_COMMAND(controller))!=0x58)&&(i>0)) {  i--; };

...
...
...
...
...
send_command(ATA_IDENTIFY, (1 << ATA_CONTROLLER));
asm {
	mov dx,0x1f0 // or 0x170 or what ever ... (you chage this with your consts/var...)
	mov edi,[pointer_to_your_data_structure]
	mov ecx,255 
	cld
	rep insw // finally read :)
}
//(if it returns "trash" it means no HD at that position (try another IDE slot, MASTER/SLAVE) )

here's how I do it :
(if it returns "trash" it means no HD at that position (try another IDE slot, MASTER/SLAVE) )

Code: Select all

Type ide_prop Field=1 'This record is returned BY IDE when IDETIFY drive command is send to 0x1f7/0x177.
	id1 As UShort '0
	cylinders As UShort '1
	id2 As UShort '2
	heads As UShort '3
	id3(1 To 2) As UShort '4
	sect_per_track As UShort '6
	id4(1 To 3) As UShort '7->9
	serial_number As String * ((19-10+1)*2) '10 -> 19
	controller_type As Ushort '20
	controller_buffer_size As Ushort '21 -> realsize = (dword) bufsize*512  
	ecc_transferred As UShort '22
	controller_number As String * ((26-23+1)*2) '23->26	
	model_number As String*((46-27+1)*2) '27->46
	num_sect_per_int As ushort '47
	dword_trasfer_flag As UShort   '48	
End Type
'ide=ide slot number (0/1) ; typ = (master=0)/(slave=1)
Function get_ide_info(ide As Integer,typ As Integer,buf As ide_prop Ptr) As Integer
Dim As Integer i
Dim As UShort ptr dd=callocate(256*2)
dim as ubyte w
Dim As Any Ptr p
If ide = 0 Then
	w = (&h0a+cast(ubyte,typ))*&h10+&h40
	p = dd
 	Asm
 		push ax
 		push dx
 		push ecx
 		mov ecx,10000
 		mov dx,&h1f7
 		_redo_f1:
                 mov dx,&H1f1
                 in al,dx
                 mov dx,&H1f7
                 in al,dx
 		dec ecx
 		jecxz _ok_time_to_go_OUT
 		in al,dx
 		cmp al,&h50   '{wait until controller not busy}
 		jne _redo_f1
 		_ok_time_to_go_OUT: ':))
 		mov al,[w]
 		mov dx,&h1f6
 		Out dx,al
 		mov al,&hec
                mov dx,&h1f7
 		Out dx,al
 		mov ecx,10000
 		_redo_f2:
                 mov dx,&H1f1
                 in al,dx
                 mov dx,&H1f7
                 in al,dx
                dec ecx
 		jecxz _OK_now_realy_is_time_to_END
 		in al,dx
 		cmp al,&h58 ' {wait for data ready} :))
 		jne _redo_f2
		jmp short teora3
 		_OK_now_realy_is_time_to_END:
		pop ecx
		pop dx
		pop ax
		end asm
		function=0
		exit function
		asm
		teora3:
		mov dx,&h1f0
		mov edi,[p]
		mov ecx,255
		cld
                push edi
		rep insw ' finally read :)
                pop edi
		pop ecx
		pop dx
		pop ax
	End asm       
   movsb1(dd,buf,SizeOf(ide_prop)) ':))
   Function = 1
    dealloc2 @dd
ElseIf ide=1 Then
	w = (&h0a+cast(ubyte,typ))*&h10+&h40
	p = dd
 	Asm
 		push ax
 		push dx
 		push ecx
 		mov ecx,10000
 		_redo_f12:
                 mov dx,&H171
                 in al,dx
                 mov dx,&H177
                 in al,dx
                dec ecx
                jecxz _ok_time_to_go_OUT2
                in al,dx
                cmp al,&h50   '{wait until controller not busy}
                jne _redo_f12
                _ok_time_to_go_OUT2: ':))
                mov al,[w]
                mov dx,&h176
                Out dx,al
                mov al,&hec
                mov dx,&h177
                Out dx,al
                mov ecx,10000
                _redo_f22:
                 mov dx,&H171
                 in al,dx
                 mov dx,&H177
                 in al,dx
                dec ecx
 		jecxz _OK_now_realy_is_time_to_END2
 		in al,dx
 		cmp al,&h58 ' {wait for data ready} :))
 		jne _redo_f22
		jmp short teora4
 		_OK_now_realy_is_time_to_END2:
		pop ecx
		pop dx
		pop ax
		end asm
		function=0
		exit function
		asm
		teora4:
		mov dx,&h170
		mov edi,[p]
		mov ecx,255
		cld
                push edi
		rep insw ' finally read :)
                pop edi
		pop ecx
		pop dx
		pop ax
	End asm       
   movsb1(dd,buf,SizeOf(ide_prop)) ':))
   Function = 1
   dealloc2 @dd
endif
End function
best regards ...
happy codeing ...

(don't worry ! I've obtained this after a long an painfull time ...my full project is at :http//filesystemd.sourceforge.net)
Attachments

[The extension bas has been deactivated and can no longer be displayed.]

Post Reply