.\" $NetBSD: driver.9,v 1.29 2017/04/30 12:32:40 pgoyette Exp $ .\" .\" Copyright (c) 2001 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation .\" by Gregory McGarry. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" .Dd April 30, 2017 .Dt DRIVER 9 .Os .Sh NAME .Nm driver .Nd description of a device driver .Sh SYNOPSIS .In sys/param.h .In sys/device.h .In sys/errno.h .Ft static int .Fn foo_match "device_t parent" "cfdata_t match" "void *aux" .Ft static void .Fn foo_attach "device_t parent" "device_t self" "void *aux" .Ft static int .Fn foo_detach "device_t self" "int flags" .Ft static int .Fn foo_activate "device_t self" "enum devact act" .Sh DESCRIPTION This page briefly describes the basic .Nx autoconfiguration interface used by device drivers. For a detailed overview of the autoconfiguration framework see .Xr autoconf 9 . .Pp Each device driver must present to the system a standard autoconfiguration interface. This interface is provided by the .Em cfattach structure. The interface to the driver is constant and is defined statically inside the driver. For example, the interface to driver .Dq foo is defined with: .Pp .Bd -literal CFATTACH_DECL_NEW(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 */ .Ed .Pp 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 second argument in the .Em CFATTACH_DECL macro. The memory block is referred to as the driver's .Em softc structure. The .Em softc structure is only accessed within the driver, so its definition is local to the driver. Nevertheless, the .Em softc structure should adopt the standard .Nx configuration and naming conventions. For example, the .Em softc structure for driver .Dq foo is defined with: .Pp .Bd -literal struct foo_softc { device_t sc_dev; /* generic device info */ /* device-specific state */ }; .Ed .Pp The autoconfiguration framework mandates that the first member of the .Em softc structure must be the driver-independent .Em device_t . Probably its most useful aspect to the driver is that it contains the device-instance name .Em dv_xname . .Pp If a driver has character device interfaces accessed from userland, the driver must define the .Em cdevsw structure. The structure is constant and is defined inside the driver. For example, the .Em cdevsw structure for driver .Dq foo is defined with: .Pp .Bd -literal 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_flag; }; .Ed .Pp The structure variable must be named foo_cdevsw by appending the letters .Dq _cdevsw to the driver's base name. This convention is mandated by the autoconfiguration framework. .Pp If the driver .Dq foo has also block device interfaces, the driver must define the .Em bdevsw structure. The structure is constant and is defined inside the driver. For example, the .Em bdevsw structure for driver .Dq foo is defined with: .Pp .Bd -literal 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_flag; }; .Ed .Pp The structure variable must be named foo_bdevsw by appending the letters .Dq _bdevsw to the driver's base name. This convention is mandated by the autoconfiguration framework. .Pp During system bootstrap, the autoconfiguration framework searches the system for devices. For each device driver, its match function is called (via its .Em cfattach structure) to match the driver with a device instance. The match function is called with three arguments. This first argument .Fa parent is a pointer to the driver's parent device structure. The second argument .Fa match is a pointer to a data structure describing the autoconfiguration framework's understanding of the driver. Both the .Fa parent and .Fa match arguments are ignored by most drivers. The third argument .Fa aux contains 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 .Fa 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 contain .Dq 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 .Nx convention is to call the match routine .Fn foo_probe instead of .Fn 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. .Pp The autoconfiguration framework will call the attach function (via its .Em 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 .Fa parent is a pointer to the driver's parent device structure. The second argument .Fa self is a pointer to the driver's device structure. It is also a pointer to our .Em softc structure since the device structure is its first member. The third argument .Fa aux is a pointer to the attachment structure. The .Fa parent and .Fa aux arguments are the same as passed to the match function. .Pp 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 .Fn config_interrupts (see .Xr autoconf 9 ) . .Pp Some devices can be removed from the system without requiring a system reboot. The autoconfiguration framework calls the driver's detach function (via its .Em cfattach structure) during device detachment. If the device does not support detachment, then the driver does not have to provide a detach function. The detach function is used to relinquish resources allocated to the driver which are no longer needed. The first argument .Fa self is a pointer to the driver's device structure. It is the same structure as passed to the attach function. The second argument .Fa flags contains detachment flags. Valid values are .Dv DETACH_FORCE (force detachment; hardware gone) and .Dv DETACH_QUIET (do not print a notice). .Pp The autoconfiguration framework may call the driver's activate function to notify the driver of a change in the resources that have been allocated 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 argument to the activate function .Fa self is a pointer to the driver's device structure. It is the same argument as passed to the attach function. The second argument .Fa act describes the action. Valid actions are .Dv DVACT_ACTIVATE (activate the device) and .Dv DVACT_DEACTIVATE (deactivate the device). If the action is not supported the activate function should return .Er EOPNOTSUPP . The .Dv DVACT_DEACTIVATE call will only be made if the .Dv DVACT_ACTIVATE call was successful. The activate function is called in interrupt context. .Pp 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 interface 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 .Dq interrupt not for me , 1 for .Dq I took care of it , or -1 for .Do I guess it was mine, but I wasn't expecting it .Dc . .Pp For a driver to be compiled into the kernel, .Xr config 1 must be aware of its existence. This is done by including an entry in files.\*[Lt]bus\*[Gt] in the directory containing the driver. For example, the driver .Dq foo attaching to bus .Dq bar with dependency on kernel module .Dq baz has the entry: .Bd -literal device foo: baz attach foo at bar file dev/bar/foo.c foo .Ed .Pp An entry can now be added to the machine description file: .Bd -literal foo* at bar? .Ed .Pp For device interfaces of a driver to be compiled into the kernel, .Xr config 1 must be aware of its existence. This is done by including an entry in majors.\*[Lt]arch\*[Gt]. For example, the driver .Dq foo with character device interfaces, a character major device number .Dq cmaj , block device interfaces, a block device major number .Dq bmaj and dependency on kernel module .Dq baz has the entry: .Bd -literal device-major foo char cmaj block bmaj baz .Ed .Pp For a detailed description of the machine description file and the .Dq device definition language see .Xr config 9 . .Sh SEE ALSO .Xr config 1 , .Xr autoconf 9 , .Xr config 9 , .Xr devsw 9 , .Xr pmf 9