Page 1 of 1

Problems about device drivers handling

Posted: Wed Apr 11, 2007 9:17 am
by Jeko
I have some problems about device drivers handling. I use the structure of unix and linux device drivers (functions are open, close, read, write, ioctl). But with this method how can I handle the drivers that wants more than only one parameter?

For example, video drivers must have the function for drawing a line:

Code: Select all

int DrawLine(int x1, int y1, int x2, int y2, int color);
that needs at least 5 parameters. With ioctl I can pass only one parameter. How can I do?
I've the same problem for other drivers, such as PCI driver.

Posted: Wed Apr 11, 2007 9:21 am
by ~
What about passing them the same number of parameters, and let each driver to utilize only those that it knows it needs?

Or, since each driver is different, why not simply have each API call pass the correct number of parameters? Isn't it done like that anyway?

Posted: Wed Apr 11, 2007 9:30 am
by Jeko
~ wrote:What about passing them the same number of parameters, and let each driver to utilize only those that it knows it needs?

Or, since each driver is different, why not simply have each API call pass the correct number of parameters? Isn't it done like that anyway?
I don't understand. I'm using unix interface for device drivers with only open, write, read, close, ioctl. What are you saying?

Posted: Wed Apr 11, 2007 9:34 am
by frank
You could pass a pointer to a struct as that one parameter.

Posted: Wed Apr 11, 2007 9:42 am
by Jeko
frank wrote:You could pass a pointer to a struct as that one parameter.
Is this a good method?
I thinked I can pass the struct with write.

Posted: Wed Apr 11, 2007 9:47 am
by frank
MarkOS wrote:
frank wrote:You could pass a pointer to a struct as that one parameter.
Is this a good method?
I thinked I can pass the struct with write.
For most of the device drivers that only require one parameter you could just pass it as normal. For device drivers that require more than one parameter you could put all of the information in a structure and pass a pointer to the structure, casting it to whatever the type of that one parameter is. All of your existing device drivers would still work and only the device drivers that thought that they were getting a pointer to a struct would treat it as such.

Re: Problems about device drivers handling

Posted: Wed Apr 11, 2007 10:58 am
by mystran
MarkOS wrote: that needs at least 5 parameters. With ioctl I can pass only one parameter. How can I do?
Easiest thing is to pass a single parameter, which is the combination of the 5 parameters:

Code: Select all

struct drawline_paremeters {
   int x1,y1,x2,y2,color;
};

 ...
   struct drawline_paramaeters dp = { 1, 1, 10, 10, red};
   ioctl(graphics_fd, __ioctl_graphics_drawline, &dp);
In other words, pass a pointer to a struct containing the parameters.

That said:

Code: Select all

NAME
       ioctl - control device

SYNOPSIS
       #include <sys/ioctl.h>

       int ioctl(int d, int request, ...);

DESCRIPTION
       The ioctl function manipulates the underlying device parameters of special
       files.  In particular, many operating characteristics of character special
       files  (e.g.  terminals) may be controlled with ioctl requests.  The argu-
       ment d must be an open file descriptor.

       The second argument is a device-dependent request code.  The  third  argu-
       ment is an untyped pointer to memory.  It's traditionally char *argp (from
       the days before void * was valid C), and will be so named for this discus-
       sion.

       An ioctl request has encoded in it whether the argument is an in parameter
       or out parameter, and the size of the argument argp in bytes.  Macros  and
       defines  used  in  specifying  an  ioctl  request  are located in the file
       <sys/ioctl.h>.

So you can just have it take variable number of arguments kinda like printf, if you want. Passing a struct is potentially a bit cleaner though.

Re: Problems about device drivers handling

Posted: Wed Apr 11, 2007 12:38 pm
by Candy
mystran wrote:So you can just have it take variable number of arguments kinda like printf, if you want. Passing a struct is potentially a bit cleaner though.
What's the point of "clean" in the presence of ioctl?

Re: Problems about device drivers handling

Posted: Wed Apr 11, 2007 12:54 pm
by mystran
Candy wrote:
mystran wrote:So you can just have it take variable number of arguments kinda like printf, if you want. Passing a struct is potentially a bit cleaner though.
What's the point of "clean" in the presence of ioctl?
....

Indeed, that's pretty good summary: ioctl is a kludge to begin with.

Posted: Wed Apr 11, 2007 1:22 pm
by Kevin McGuire
that needs at least 5 parameters. With ioctl I can pass only one parameter. How can I do?
I've the same problem for other drivers, such as PCI driver.
Why would you want to force many devices that have completely different functionality to use a interface that would not be efficient for them to use? You might just want to widen the conceptual scope and break it into logical 'functionality blocks'.
I have some problems about device drivers handling. I use the structure of unix and linux device drivers (functions are open, close, read, write, ioctl). But with this method how can I handle the drivers that wants more than only one parameter?
The Linux kernel does not subject all it's drivers to using one interface with five methods such as: open, close, read, write, ioctl.

Here is a interface that is specific to the PCI subsystem.

Code: Select all

static struct pci_driver xl_3c359_driver = {
	.name		= "3c359",
	.id_table	= xl_pci_tbl,
	.probe		= xl_probe,
	.remove		= __devexit_p(xl_remove_one),
};
There are many other interfaces in the Linux kernel. I call them interfaces, but they may very well be called something else but I still think they operate in the same manner.

In my own opinion I do not feel a driver should even worry about being opened or closed. It should do nothing more than get that device into the appropriate states and export the functionality of that device..and nothing else. If you want more then break it away from the driver, and place it in front of the driver and really drivers if you have multiple ones. It helps remove the bulk and make things smaller and more compact which can fit into cache easier. This could also be known as removing redundancy. I always like keeping redundancy in mind since it is a important factor in all aspects of life.

Posted: Wed Apr 11, 2007 3:28 pm
by mystran
Actually, depending on the device, it might or might not want to worry about opening/closing...

Say, an audio driver might want to know about every open() and close() so it can allocate/deallocate buffers. This might not make any sense for SoundBlaster ofcourse since you're forced to mix in software when the card only provide a single output. But with a more advanced card with hardware mixing, you might just as well take advantage of that.

But I agree with the point that the interface a program uses on a file descriptor need not be the same interface you actually talk to the devices. It makes more sense for a block device to provide blocks, and then some higher level code to figure out how to deal with read/write/lseek.

ioctl() then is a hack to talk to device drivers directly from userspace, without all higher layers on top of the device driver needing to care about some special case stuff that only applies to this device and your grandmother's dog, so that you don't need to make a million and one special case system calls.

Personally, I'd actually separate graphics drivers into two parts: a small piece of kernel code that implements a totally driver specific ioctl()-interface and mmap(), and then the actual graphics driver which can run as a normal process, and provides some standard interface for you GUI to use. This is (more or less) how X11 works with modern graphics cards. Programs can then communicate with the GUI just like they'd communicate with any other server: sending messages through pipes/sockets/whatever. This is a good design. The reason X11 is slow crap has to do with the braindead protocol.

Posted: Thu Apr 12, 2007 9:02 am
by hakware
For ioctls, you could use varargs (I'm assuming you're doing this in c). Though varargs might involve a bit of extra coding on the library function side (like it does in d), it'd probably be worth it in the long run ;-)

Posted: Fri Apr 13, 2007 2:36 am
by os64dev
for a gui i would do the struct thingy and use as a format the opengl structures. If at one point you'll be able to do opengl then you can transfer the structure directly to the hardware card. i think ;-)