Subject: Re: Time to fix a 25 year old misdesign
To: None <>
From: Thorbjorn Jemander <>
List: tech-kern
Date: 10/16/2000 06:16:45
On Sunday, October 15 2000, 20:17:21 +0200 Lennart Augustsson wrote about Re: 
Time to fix a 25 year old misdesign:

>There is a certain elegance in the current design, but it also stops you
>from doing things that you'd like to do.
>I still think a design with a symmetry between "generate a driver reference"
>and "drop a driver reference" would be more elegant.
>Symmetry is beauty. :)

I'm neither a driver nor a kernel expert, but other systems have the
symmetry you propose (or not propose - given the amount of work).

Take for instance BeOS. Here's a part of their 'Drivers.h':

typedef status_t (*device_open_hook) (const char *name, uint32 flags, void **
typedef status_t (*device_close_hook) (void *cookie);

<znip: removed the declarations of the other hooks>


typedef struct {
	device_open_hook		open;		/* called to open the device */
	device_close_hook		close;		/* called to close the device */
	device_free_hook		    free;		/* called to free the cookie */
	device_control_hook		control;	    /* called to control the device *
	device_read_hook		    read;		/* reads from the device */
	device_write_hook		write;		/* writes to the device */
	device_select_hook		select;		/* start select */
	device_deselect_hook	    deselect;	/* stop select */
	device_readv_hook		readv;		/* scatter-gather read from the 
device */
	device_writev_hook		writev;		/* scatter-gather write to the device 
} device_hooks;

extern _EXPORT status_t		init_hardware(void);
extern _EXPORT const char	**publish_devices();
extern _EXPORT device_hooks	*find_device(const char *name);
extern _EXPORT status_t		init_driver(void);
extern _EXPORT void			uninit_driver(void);	

extern _EXPORT int32	api_version;

Here init_hardware() is called once at the first open of the device,
init_driver() for each time an open() call occurrs on any of its
published entry-points and if previously all were closed. uninit_driver
is called when all entry-points are closed. open() is called for a 
specified entry-point and multiple open entry-points are permitted
per device (requiring proper locking, of course) and close() is called
whenever the entry-point is closed. Not until all all entry-points are
closed, uninit_driver is called. If some are subsequently opened, 
init_driver is called again. The cookie is allocated at the first
open() call of an entry-point and is later used as a reference to that
entrypoint in subsequent read, write and control calls. I  don't remember
when free() is called, but I it anyway is supposed to free the cookie.
(the cookie is often a pointer to a struct identitying/storing the state
of the driver.) publish_devices returns a set of paths (not only names)
tor each entry-point to a device e.g. { "K575/DAC", "K575/ADC", "K575/DI",
..., 0}. These will be published in the file system as a dir-structure
beneath the position of the driver. In this case as /dev/daq/K575/...
When the device is accessed the first time, the kernel will get the
hooks for the entry-point by using find_device - it's supposed to return
a set of hooks for that device.

The lines

extern _EXPORT int32	api_version;

might also provide a solution to the problem. When a driver is loaded,
the kernel could check for api_version and treat the device as supporting the 
or new device api, if one now would redesign it. 

I'm not saying this is the way to be, just an example on how other
people do the device api.

I'm also very aware of the huge amount of drivers and the amount of
work required if the driver API would change.

I willingly admit my limited knowledge of the internal workings
of the NetBSD kernel and driver model. I just thought this could
be somewhat of interest.

/Thorbjýrn Jemander

Best regards,
Thorbjörn Jemander             Office: +46 13 28 1371
Surface and Semicond. Physics, Lab: +46 13 28 1274
Department of Physics (IFM)    Fax: +46 13 13 7568
Linköpings Universitet         Email:
582 81 Linköping, Sweden       Web: