I'm relatively new to OS Development. I started working in my kernel a few months ago and i'd say i did a pretty good job until now. (except for the really messy and poorly documented code )
Here is the source code on Github if you would like to take a look at it: https://github.com/Garnek0/GarnOS
Anyways, my current device manager (i'm going to call it the Device Abstraction Layer or DAL from now on as that is what its called in my kernel) is really unreliable and not future-proof at all. Instead of having each driver registered and stored in a list, the drivers need to be "manually" loaded as modules by the kernel inside device identification routines (if you look inside the mess that pcidev.c is, you'll see what i mean). What i want to do is take the linux approach and register drivers, store them in a list and test them for each device that doesnt have a driver using a list of ids pointed to by a metadata struct inside the driver's executable. My problem is that i have absolutely no idea where to even start. I have my DAL closely tied to other components such as the module loader and trying to morph it into what i explained above is going to be extremely hard. Rewriting the DAL is completely out of the question... doing that will create such a mess that i'd probably just end up git checkouting back to where i started. I tried looking at linux to see how it's implemented there but linux is so complicated that i couldn't even find the routines for the drivers. I'm honestly completely at a loss here. Any help is appreciated.
Thanks!
Making a reliable driver system
-
- Member
- Posts: 5560
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Making a reliable driver system
Yeah, those giant switch statements don't belong in there. Call everything "unknown PCI device" and let the drivers figure out the rest, or at least use a table lookup instead of a switch statement. Looks like you might also have a bug with single-function devices getting enumerated multiple times. (Unrelated, your pci_config_read_word function makes no sense. Why does it read a dword and then discard half? Just return the whole dword!)Garnek0 wrote:(if you look inside the mess that pcidev.c is, you'll see what i mean)
I believe that's called the sunk cost fallacy.Garnek0 wrote:Rewriting the DAL is completely out of the question...
Linux uses depmod to build a big table (modules.alias) that maps device IDs to module names. Each module binary contains a list of supported device IDs in a table, and depmod extracts that table using special symbols.Garnek0 wrote:I tried looking at linux to see how it's implemented there but linux is so complicated that i couldn't even find the routines for the drivers.
Re: Making a reliable driver system
I think driver registration is something you only would implement at a fairly advanced level.
In my design, I have a config file that will contain the drivers to load, and then the tool will build a binary that is booted. The kernel then can find which drivers to load from the binary. Another approach is to link them with the kernel.
Loadable drivers would be stored in the filesystem, and you cannot implement this until you have a stable filesystem.
In my design, I have a config file that will contain the drivers to load, and then the tool will build a binary that is booted. The kernel then can find which drivers to load from the binary. Another approach is to link them with the kernel.
Loadable drivers would be stored in the filesystem, and you cannot implement this until you have a stable filesystem.
Re: Making a reliable driver system
Well, yeah, but that's not the magic sauce. That would be in the init function. Every module has an init function. If the module is built into the kernel, the init function is called at some point during startup. Linux uses a list of them built by the linker to do that. The drivers get registered after the memory manager but before device discovery. That way, all drivers are already available when devices are discovered.Octocontrabass wrote:Linux uses depmod to build a big table (modules.alias) that maps device IDs to module names. Each module binary contains a list of supported device IDs in a table, and depmod extracts that table using special symbols.
Yes, there are loadable modules. But those only get into the mix after the builtin ones have failed to handle a device. In that case, Linux calls request_module(), and that will somehow cause a module to be loaded. Don't ask me how; that is really beyond me.
But the important thing still remains. You have each driver register itself as that class of driver, then device enumerators can look through tables to determine what device to handle with what driver. The important thing here is that you need a good system for identifying types of drivers. Bear in mind that every device has two sides: The side where it is found on the bus, and the side where it is useful for the user. It is probably not sensible to have a list of "PCI drivers" beyond a common list of PCI identifiers, and something like a common "probe" function that gets called by the enumerator. But the graphics card driver needs to somehow expose a framebuffer, the network driver a network interface, and the USB driver needs to go do its own thing. So that is something to think about.
Carpe diem!
Re: Making a reliable driver system
I did a lot of OS installs way back when hardware autodetection was in its infancy, and I think it's a luxury feature. It's very nice when you have a lot of installs to do on varied hardware, but it saves little when you're only installing on one machine. Are you testing your OS on many different machines at this stage in its development? Interested people trying out your OS will only expect it to work where you say it works. If you say it only works on Qemu with certain options, that's what they'll use. (Unless they're crazy like me! )
I recommend forgetting about autodetection for now, and focus on cleaning up your code instead. Otherwise, you're going to end up with many more situations like this:
I recommend forgetting about autodetection for now, and focus on cleaning up your code instead. Otherwise, you're going to end up with many more situations like this:
I don't think this is sunk cost fallacy, (sorry @Octocontrabass,) but rather the fact that you know you don't have the skills needed to write clean code. (Am I right?) Focus on designing cleaner subsystems. The cleaner they are, the fewer impossible messes you'll get into. Note, though, that I write "cleaner", not "clean" -- don't try too hard. It's possible to make a design so pure, it creates more problems than it solves. Pure functional languages can have that problem.Garnek0 wrote:Rewriting the DAL is completely out of the question... doing that will create such a mess that i'd probably just end up git checkouting back to where i started.
Linux is the last place I'd look because it's so complex. It's insanely overoptimized and I gather that's not the only problem. You'd probably have an easier time reading decompiled Windows source -- don't do that! OpenBSD source is known for being easier to read. Plan 9 & 9front are easier still.Garnek0 wrote:I tried looking at linux to see how it's implemented there but linux is so complicated that i couldn't even find the routines for the drivers.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie