Questions about Hard Disk Driver (and drivers in general)
-
- Posts: 15
- Joined: Thu Aug 19, 2010 2:22 am
- Location: USA
Questions about Hard Disk Driver (and drivers in general)
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!
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 93 times
-
- hd.c
- Driver code.
- (1.37 KiB) Downloaded 81 times
"Welcome to the desert... of the real." - Morpheus, The Matrix.
Re: Questions about Hard Disk Driver (and drivers in general
Hi,
Cheers,
Adam
No - I haven't looked at your code, but you should just be able to read straigt from the drive (after initialising the controller...).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...
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.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.
Cheers,
Adam
-
- Posts: 15
- Joined: Thu Aug 19, 2010 2:22 am
- Location: USA
Re: Questions about Hard Disk Driver (and drivers in general
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 also a good solution if you know what disk you are booting from, for example a CD.
...This is going to be complicated.
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?Alternatively, you could have a basic read-only FS driver which can load other drivers.
Thanks for your reply.
"Welcome to the desert... of the real." - Morpheus, The Matrix.
Re: Questions about Hard Disk Driver (and drivers in general
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.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?
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.
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.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?
HTH,
Adam
-
- Posts: 15
- Joined: Thu Aug 19, 2010 2:22 am
- Location: USA
Re: Questions about Hard Disk Driver (and drivers in general
OK, so is this possible with GRUB? If so, how?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.
"Welcome to the desert... of the real." - Morpheus, The Matrix.
Re: Questions about Hard Disk Driver (and drivers in general
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]
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]
-
- Posts: 15
- Joined: Thu Aug 19, 2010 2:22 am
- Location: USA
Re: Questions about Hard Disk Driver (and drivers in general
OK thanks a lot.
[edit]But this doesn't solve my problem with IDENTIFY in my hard disk driver, *sigh*[/edit]
[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.
Re: Questions about Hard Disk Driver (and drivers in general
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).
-
- Posts: 15
- Joined: Thu Aug 19, 2010 2:22 am
- Location: USA
Re: Questions about Hard Disk Driver (and drivers in general
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.
Re: Questions about Hard Disk Driver (and drivers in general
You are doing this :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!
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))
{
;
}
}
}
}
Code: Select all
while ((status = inportb(ATA_COMMAND(controller))) & (1 << ATA_BSY))
{
;
}
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) )
(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
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.]