Writing Device Drivers

Loadable Driver Interface

Device drivers must be dynamically loadable and should be unloadable to help conserve memory resources. Drivers that can be unloaded are also easier to test and debug.

Each device driver has a section of code that defines a loadable interface. This code section defines a static pointer for the soft state routines, the structures described in "Data Structures", and the routines involved in loading the module.


Example 5-1 Loadable Interface Section

static void *statep;				/* for soft state routines */
static struct cb_ops xx_cb_ops;					/* forward reference */
static struct dev_ops xx_ops = {
 	DEVO_REV,
 	0,
 	xxgetinfo,
 	nulldev,
 	xxprobe,
 	xxattach,
 	xxdetach,
 	xxreset,
 	nodev,
 	&xx_cb_ops,
 	NULL,
		xxpower
};

static struct modldrv modldrv = {
 	&mod_driverops,
 	"xx driver v1.0",
	 &xx_ops
};

static struct modlinkage modlinkage = {
	   MODREV_1,
 	&modldrv,
 	NULL
};

int
_init(void)
{
 	int error;
 	ddi_soft_state_init(&statep, sizeof (struct xxstate),
			estimated number of instances);
	further per-module initialization if necessary
		error = mod_install(&modlinkage);
		if (error != 0) {
			undo any per-module initialization done earlier
			ddi_soft_state_fini(&statep);
 	}
 	return (error);
}

int
_fini(void)
{
 	int error;
 	error = mod_remove(&modlinkage);
 	if (error == 0) {
			release per-module resources if any were allocated
			ddi_soft_state_fini(&statep);
 	}
 	return (error);
}

int
_info(struct modinfo *modinfop)
{
 	return (mod_info(&modlinkage, modinfop));
}

The driver should perform any one-time resource allocation or data initialization during driver loading in _init(9E). For example, it should initialize any mutexes global to the driver in this routine. The driver should not, however, use _init(9E) to allocate or initialize anything that has to do with a particular instance of the device. Per-instance initialization must be done in attach(9E). For example, if a driver for a printer can handle more than one printer at the same time, it should allocate resources specific to each printer instance in attach(9E).

Similarly, in _fini(9E), the driver should release only those resources allocated by _init(9E).


Note -

Once _init(9E) has called mod_install(9F), the driver should not change any of the data structures hanging off the modlinkage(9S) structure, as the system may make copies of them or change them.