1. Introduction

In the 2.4 and earlier Linux kernels, there was no unified database of what devices were present in the system, and how they were connected with each other. The implications of this are:

To overcome these problems, in 2.5 and later kernels a framework has been provided to maintain a device model. This article describes this device model framework. The intention of this article is to provide a bird's eye view of the working of the device model framework. The specific details of each sub-component can be obtained from various other books/articles and of course the kernel source code.

The five software components that play a major role in building and maintaining the device model are:

2. Device Model Core

The device model core defines a set of structures and functions. The structures form the building blocks of the device model and the functions update and maintain the device model.

Some of the important structures defined by the device model core are given below.

The struct bus_type is used to represent busses like PCI, USB, I2C, etc. The struct device is used to represent devices like an Intel AC97 audio controller, an Intel PRO/100 ethernet controller, a PS/2 mouse etc. The struct device_driver is used to represent kernel drivers that can handle specific devices. The struct class is used to represent a class of devices like sound, input, graphics, etc. no matter how they are connected to the system.

The device model core, among other things, defines functions to register and unregister instances of the above structures. These functions are listed below.

The files that implement the device model core are include/linux/device.h, drivers/base/*.c.

3. Generic Bus Drivers

For each bus supported by the kernel there is a generic bus driver. The generic bus driver allocates a struct bus_type and registers it with the kernel's list of bus types. The registration is done using bus_register(). (bus_type_register() would have been a more appropriate name!).

The important fields of the bus_type structure are shown below.

bus_type
|-- name (string)
|-- !klist_devices (klist)
|-- !klist_drivers (klist)
|-- match (fp)
|-- suspend (fp)
`-- resume (fp)

The fields marked with a ! are internal to the device model core and should not be touched by the generic bus driver directly.

When a match is found, the device is associated with the device driver. The process of associating a device with a device driver is called binding.

Given below is a sample of bus_type instantiation for the PHY management bus, taken from drivers/net/phy/mdio_bus.c.

struct bus_type mdio_bus_type = {
        .name           = "mdio_bus",
        .match          = mdio_bus_match,
        .suspend        = mdio_bus_suspend,
        .resume         = mdio_bus_resume,
};

Apart from defining a bus_type, the generic bus driver defines a bus specific driver structure and a bus specific device structure. These structures extend the generic struct device_driver and struct device provided by the device model core, by adding bus specific members.

The generic bus driver provides helper functions to register and unregister device drivers that can handle devices on that bus. These helper functions wrap the generic functions provided by the device model core.

4. Bus Controller Drivers

For a specific bus type there could be many different controllers provided by different vendors. Each of these controllers needs a corresponding bus controller driver. The role of a bus controller driver in maintenance of the device model, is similar to that of any other device driver in that, it registers itself with driver_register(). But apart from registering itself, it also detects devices on the bus it is controlling and registers the devices on the bus using device_register().

The bus controller driver is responsible for instantiating and registering instances of struct device with the device model core. Some of the important members of struct device are given below.

device
|-- bus_id (string)
|-- bus (bus_type)
|-- parent (device)
`-- !driver (device_driver)

The fields marked with a ! are internal to the device model core and should not be touched by the bus controller driver directly.

As a sample bus controller driver, the bus controller driver for the PHY management bus on the MPC85xx, is available from drivers/net/gianfar_mii.c

5. Device Drivers

Every device driver registers itself with the bus_type using driver_register(). After which the device model core tries to bind it with a device. When a device is detected (registered) that can be handled by a particular driver, the probe member of the driver is called to instantiate the driver for that particular device.

Each device driver is responsible for instantiating and registering an instance of struct device_driver with the device model core. The important members of struct device_driver is given below.

device_driver
|-- bus (bus_type)
|-- probe (fp)
|-- remove (fp)
|-- suspend (fp)
`-- resume (fp)

As samples of device drivers, see the PHY driver located in drivers/net/phy/.

6. Class Drivers

Most users of a system are not bothered about how devices are connected in a system, but what type of devices are connected in the system. A class driver instantiates a struct class for the class of devices it represents and registers it with the device model core using class_register(). Each device driver is responsible for adding its device to the appropriate class.

The important members of struct class is given below.

class
|-- name (string)
`-- !devices (list)

The fields marked with a ! mark are internal to the device model core and should not be touched by the class driver directly.

7. Conclusion

With these data structures in place, a device tree of how the devices are connected in the system are available, and what types of devices are present in the system is also available. This overcomes the limitations of the 2.4 kernel, and paves way for