DRIVER(9) NetBSD Kernel Developer's Manual DRIVER(9)
NAMEdriver -- description of a device driver
SYNOPSIS#include <sys/param.h>#include <sys/device.h>#include <sys/errno.h>static intfoo_match(struct device *parent, struct cfdata *match, void *aux);
static voidfoo_attach(struct device *parent, struct device *self, void *aux);
static intfoo_detach(struct device *self, int flags);
static intfoo_activate(struct device *self, enum devact act);
DESCRIPTION
This page briefly describes the basic NetBSD autoconfiguration interface
used by device drivers. For a detailed overview of the autoconfiguration
framework see autoconf(9).
Each device driver must present to the system a standard autoconfigura-
tion interface. This interface is provided by the cfattach structure.
The interface to the driver is constant and is defined statically inside
the driver. For example, the interface to driver ``foo'' is defined
with:
CFATTACH_DECL(foo, /* driver name */
sizeof(struct foo_softc), /* size of instance data */
foo_match, /* match/probe function */
foo_attach, /* attach function */
foo_detach, /* detach function */
foo_activate); /* activate function */
For each device instance controlled by the driver, the autoconfiguration
framework allocates a block of memory to record device-instance-specific
driver variables. The size of this memory block is specified by the sec-
ond argument in the CFATTACH_DECL macro. The memory block is referred to
as the driver's softc structure. The softc structure is only accessed
within the driver, so its definition is local to the driver. Neverthe-
less, the softc structure should adopt the standard NetBSD configuration
and naming conventions. For example, the softc structure for driver
``foo'' is defined with:
struct foo_softc {
struct device sc_dev; /* generic device info */
/* device-specific state */
};
The autoconfiguration framework mandates that the first member of the
softc structure must be the driver-independent struct device. Probably
its most useful aspect to the driver is that it contains the device-
instance name dv_xname.
If a driver has character device interfaces accessed from userland, the
driver must define the cdevsw structure. The structure is constant and
is defined inside the driver. For example, the cdevsw structure for
driver ``foo'' is defined with:
const struct cdevsw foo_cdevsw {
int (*d_open)(dev_t, int, int, struct lwp *);
int (*d_close)(dev_t, int, int, struct lwp *);
int (*d_read)(dev_t, struct uio *, int);
int (*d_write)(dev_t, struct uio *, int);
int (*d_ioctl)(dev_t, u_long, void *, int, struct lwp *);
void (*d_stop)(struct tty *, int);
struct tty *(*d_tty)(dev_t);
int (*d_poll)(dev_t, int, struct lwp *);
paddr_t (*d_mmap)(dev_t, off_t, int);
int (*d_kqfilter)(dev_t, struct knote *);
int d_type;
};
The structure variable must be named foo_cdevsw by appending the letters
``_cdevsw'' to the driver's base name. This convention is mandated by
the autoconfiguration framework.
If the driver ``foo'' has also block device interfaces, the driver must
define the bdevsw structure. The structure is constant and is defined
inside the driver. For example, the bdevsw structure for driver ``foo''
is defined with:
const struct bdevsw foo_bdevsw {
int (*d_open)(dev_t, int, int, struct lwp *);
int (*d_close)(dev_t, int, int, struct lwp *);
void (*d_strategy)(struct buf *);
int (*d_ioctl)(dev_t, u_long, void *, int, struct lwp *);
int (*d_dump)(dev_t, daddr_t, void *, size_t);
int (*d_psize)(dev_t);
int d_type;
};
The structure variable must be named foo_bdevsw by appending the letters
``_bdevsw'' to the driver's base name. This convention is mandated by
the autoconfiguration framework.
During system bootstrap, the autoconfiguration framework searches the
system for devices. For each device driver, its match function is called
(via its cfattach structure) to match the driver with a device instance.
The match function is called with three arguments. This first argument
parent is a pointer to the driver's parent device structure. The second
argument match is a pointer to a data structure describing the autocon-
figuration framework's understanding of the driver. Both the parent and
match arguments are ignored by most drivers. The third argument aux con-
tains a pointer to a structure describing a potential device-instance.
It is passed to the driver from the parent. The match function would
type-cast the aux argument to its appropriate attachment structure and
use its contents to determine whether it supports the device. Depending
on the device hardware, the contents of the attachment structure may con-
tain ``locators'' to locate the device instance so that the driver can
probe it for its identity. If the probe process identifies additional
device properties, it may modify the members of the attachment structure.
For these devices, the NetBSD convention is to call the match routine
foo_probe() instead of foo_match() to make this distinction clear.
Either way, the match function returns a nonzero integer indicating the
confidence of supporting this device and a value of 0 if the driver
doesn't support the device. Generally, only a single driver exists for a
device, so the match function returns 1 for a positive match.
The autoconfiguration framework will call the attach function (via its
cfattach structure) of the driver which returns the highest value from
its match function. The attach function is called with three arguments.
The attach function performs the necessary process to initialise the
device for operation. The first argument parent is a pointer to the
driver's parent device structure. The second argument self is a pointer
to the driver's device structure. It is also a pointer to our softc
structure since the device structure is its first member. The third
argument aux is a pointer to the attachment structure. The parent and
aux arguments are the same as passed to the match function.
The driver's attach function is called before system interrupts are
enabled. If interrupts are required during initialisation, then the
attach function should make use of config_interrupts() (see autoconf(9)).
Some devices can be removed from the system without requiring a system
reboot. The autoconfiguration framework calls the driver's detach func-
tion (via its cfattach structure) during device detachment. If the
device does not support detachment, then the driver does not have to pro-
vide a detach function. The detach function is used to relinquish
resources allocated to the driver which are no longer needed. The first
argument self is a pointer to the driver's device structure. It is the
same structure as passed to the attach function. The second argument
flags contains detachment flags. Valid values are DETACH_FORCE (force
detachment; hardware gone) and DETACH_QUIET (do not print a notice).
The autoconfiguration framework may call the driver's activate function
to notify the driver of a change in the resources that have been allo-
cated to it. For example, an Ethernet driver has to be notified if the
network stack is being added or removed from the kernel. The first argu-
ment to the activate function self is a pointer to the driver's device
structure. It is the same argument as passed to the attach function.
The second argument act describes the action. Valid actions are
DVACT_ACTIVATE (activate the device) and DVACT_DEACTIVATE (deactivate the
device). If the action is not supported the activate function should
return EOPNOTSUPP. The DVACT_DEACTIVATE call will only be made if the
DVACT_ACTIVATE call was successful. The activate function is called in
interrupt context.
Most drivers will want to make use of interrupt facilities. Interrupt
locators provided through the attachment structure should be used to
establish interrupts within the system. Generally, an interrupt inter-
face is provided by the parent. The interface will require a handler and
a driver-specific argument to be specified. This argument is usually a
pointer to the device-instance-specific softc structure. When a hardware
interrupt for the device occurs the handler is called with the argument.
Interrupt handlers should return 0 for ``interrupt not for me'', 1 for
``I took care of it'', or -1 for ``I guess it was mine, but I wasn't
expecting it''.
For a driver to be compiled into the kernel, config(1) must be aware of
its existence. This is done by including an entry in files.<bus> in the
directory containing the driver. For example, the driver ``foo'' attach-
ing to bus ``bar'' with dependency on kernel module ``baz'' has the
entry:
device foo: baz
attach foo at bar
file dev/bar/foo.c foo
An entry can now be added to the machine description file:
foo* at bar?
For device interfaces of a driver to be compiled into the kernel,
config(1) must be aware of its existence. This is done by including an
entry in majors.<arch>. For example, the driver ``foo'' with character
device interfaces, a character major device number ``cmaj'', block device
interfaces, a block device major number ``bmaj'' and dependency on kernel
module ``baz'' has the entry:
device-major foo char cmaj block bmaj baz
For a detailed description of the machine description file and the
``device definition'' language see config(9).
SEE ALSOconfig(1), autoconf(9), config(9), powerhook_establish(9),
shutdownhook_establish(9)
NetBSD 5.0.1 October 14, 2007 NetBSD 5.0.1

You can also request any man page by name and (optionally) by section:

Command:

Section:

Architecture:

Collection:

Use the DEFAULT collection to view manual pages
for third-party software.