The Driver Model Core, Part I

The 2.5 kernel implements a unified device driver model that will make driver development for 2.6 easier.

In the 2.5 Linux kernel development
series, a unified device driver model framework was created by Pat
Mochel. This framework consists of a number of common structures
and functions all device driver subsystems have been converted to
use. It also consists of some generic structures that are starting
to be used outside of the driver code by other parts of the kernel.
This article discusses parts of the driver model and provides an
example of how to convert a specific device driver subsystem to the
driver model.

Buses, Devices and Classes

The driver framework breaks all things down into buses,
devices and classes. Using these primitives, it controls how
drivers are matched up with physical and virtual devices, and it
shows the user how all of these things are interconnected.

A bus can be described as something with devices connected to
it. Examples of buses are PCI, USB, i2c, PCMCIA and SCSI. Usually
only one bus driver controls the activity on a bus, and it provides
a type of bridge from the bus it is on to the bus it
controls.

An example of a bridge is a USB controller that lives on the
PCI bus. It talks to the PCI bus as a PCI device and looks to the
kernel as a PCI driver. But it controls all access to that specific
USB bus, talking to the different USB devices plugged in to
it.

Buses are represented in the kernel with the struct bus_type
definition, found in include/linux/device.h. All buses in the
system are shown to the user in subdirectories of the sysfs
directory /sys/bus/.

Devices are physical or virtual devices that reside on a bus.
They are represented by the struct device definition and are
created by the bus when the bus sees they are present in the
system. Usually only one driver controls a specific device at one
time. They can be seen in the /sys/devices directory as a giant
tree of all devices in the system or in the
/sys/bus/BUS_TYPE/devices/ directory for a
specific type of device.

Devices also have drivers assigned to them that control how
to talk to the device across a specific bus. Some drivers know how
to talk to multiple buses, such as the Tulip network driver, which
can talk to PCI and ISA Tulip devices. All drivers are represented
by the struct device_driver definition. They can be seen in sysfs
at /sys/bus/BUS_TYPE/drivers/. Drivers
register with a specific bus and export a list of different types
of devices they can support. The bus matches the devices and
drivers based on this list of exported devices. The list also is
exported to user space so the /sbin/hotplug tools can be used to
match drivers to devices that do not have drivers already loaded.
See my article, “Hot Plug”, in the April 2002 issue of
Linux Journal for more information on this
interface and how it works [also available at
www.linuxjournal.com/article/5604].

Classes here do not take the general object-oriented
definition but, rather, are things that provide a function to the
user. They are not bus- or device-specific things but functionally
look to the user as the same type of device. Examples of classes
are audio devices; pointing devices, such as mice and touchpads;
keyboards; joysticks; IDE disks; and tty devices. The kernel always
has had these kinds of devices, and they traditionally have been
grouped together by major/minor number range, so the user can
access them easily. Classes are represented in the kernel with the
struct device_class definition, and they can be seen as
subdirectories of the sysfs directory /sys/class/.

All of the above descriptions sound great on paper, but how
does the driver model actually affect the kernel code? To show
this, let us walk through how the i2c driver subsystem was modified
to support this driver model.

The i2c code has lived outside of the main kernel tree for a
long time, and it was offered as a patch for the 2.0, 2.2 and 2.4
kernels. It also was the subject of “Using the i2c Bus”, by Simon
G. Vogl, one of the main authors of the code
[LJ, March 1997,
www.linuxjournal.com/article/1342].
In the 2.4 development cycle, a number of the i2c core files and a
few i2c bus drivers were accepted into the main kernel. In the 2.5
development cycle, a few more drivers were added; hopefully, all of
them eventually will migrate into the main tree. For a good
description of the i2c code, what devices it supports and how to
use it, see the main development site at
secure.netroedge.com/~lm78/index.html.

When loaded, the i2c bus drivers, which talk to the i2c
controller chips, export a number of files in the /proc/bus
directory. When an i2c device driver is loaded and bound to an i2c
device, it exports files and directories in the
/proc/sys/dev/sensors directory. By moving the representation of
the devices and buses to the kernel driver core, all of these
separate files can be shown in their proper places in /sys.