Page 1 of 1

Drivers (and message passing)

Posted: Sun Feb 03, 2008 12:26 pm
by lukem95
I'v got to the point where i have a multitasking, application loading OS.

i know want to write some drivers, and load them as user programs. my problem however is how to call functions from the drivers. Getting the data back to the kernel is easy enough, as i can just create a syscall to do so, but how would i do it the other way around?

i'm sure there is a standard way/ways to do this, but i cant seem to think of anything that will work short of a shared memory location, and a spinning loop checking for a bit to be set in the driver, which soudns like a waste of resources.

It may be the only way to go however. Does anybody have any tips or ideas?

lukem95

Posted: Sun Feb 03, 2008 12:39 pm
by piranha
Modules are one solution, although if one goes bad, then the whole kernel can lock up.

You could just run the drivers in Ring0.

My kernel uses modules, and I will make a fail-safe loader system that times out or something.
-JL

Posted: Sun Feb 03, 2008 12:40 pm
by Telgin
Um, I think the general method for calling functions in a driver is just to "export" the function addresses from the driver then call them from within the kernel at the address exported. Since you have application loading done though, I'd somewhat assume that you know how to do things like look up the program's entry point and call it.

If that's not what you meant then, did you mean how do you keep the driver running as a program and allow the kernel to call specific functions within the driver to allow it to do stuff?

Posted: Sun Feb 03, 2008 3:50 pm
by lukem95

Code: Select all

If that's not what you meant then, did you mean how do you keep the driver running as a program and allow the kernel to call specific functions within the driver to allow it to do stuff?

yeah i mean that... i guess i could have a seperate file for every function, but thats not very resource saving.

Posted: Mon Feb 04, 2008 1:38 am
by kscguru
Can you just reverse the problem? Instead of thinking about calling from the kernel into the driver, think about returning to the driver from some previous syscall (e.g. some syscall made at driver load).

Driver loads, has a thread ... that thread does initialization, then makes a magic syscall that blocks in the kernel. Any time another thread wants to call into the driver, it swaps with the driver thread (so the other thread blocks, and the driver thread returns). Driver thread does work, then makes the magic syscall again, which results in another swap (other thread unblocks, driver thread blocks). Put a little parameter-passing in the swap routine, and you have a function call mechanism.

This is roughly how Solaris Doors works, by the way; Solaris is slightly more elaborate in that it creates thread pools on-the-fly so multithreading performance is better. Solaris uses it as an IPC mechanism, but nothing stops you from using it for drivers.

Posted: Mon Feb 04, 2008 2:12 am
by pcmattman
Perhaps this?

All drivers go into the kernel address space in their own respective locations, then they are dynamically linked so that you can run code in them even without knowing their initial location, and then call some init function which sets the driver up and all of the relevant functions with your driver interface.

Posted: Mon Feb 04, 2008 4:12 am
by mathematician
Drivers could go into a linked list with the header of each driver containg pointers to its internal routines. That apples to resident drivers, and then installable drivers could then be tagged onto the list. If it wanted to to the kernel could go down the list just once, buiding a table of pointers. If the driver needs to attract the kernel's part way through processing a request it could use a software interrupt with an identifier loaded into one of the registers, and another interrupt to signal completion (so that the process blocked whilst waiting for the driver can be unblocked).

Posted: Mon Feb 04, 2008 9:20 am
by bewing
A driver in userspace is basically a shared library. The main difference is that its list of exported symbols must have standardized names. The driver has to register itself with the device manager as being the "method" associated with a particular device. The device manager loads the driver, accesses its symbol table for the standard symbols, (calls the driver's init function), and stores those entrypoints in its table. When an app makes a request aimed at a device, the device manager either connects the app directly to the device driver, or acts as a middleman on all calls.

So the main question is: how are you planning on implementing dynamic libraries?

Posted: Mon Feb 04, 2008 5:29 pm
by AndrewAPrice
How about IPC?

e.g.

Code: Select all

DeviceRequest request;
bool running = true;

while(running)
{
   ReceiveDeviceRequest(&request);
   switch(request.Type)
   {
   case DR_OPEN:
      break;
   case DR_CLOSE:
      break;
   case DR_READ:
      break;
   case DR_WRITE:
      break;
   case DR_SEEK:
      break;
   case DR_IOCTL:
      break;
   case DR_KILL:
      running = false;
      break;
   }
}
The kernel stores a list of DeviceRequest's as they are sent, and ReceiveDriverRequest receives the next request on the list. And there you go - a basic driver template :D

Posted: Tue Feb 05, 2008 1:56 pm
by lukem95
Thanks for your replies, i will consider this some more and post my POA :)