Expand description
Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
This documentation describes how to implement a bus specific driver API and how to align it with the design of (bus specific) devices.
Note: Readers are expected to know the content of the documentation of Device
and
DeviceContext
.
§Driver Trait
The main driver interface is defined by a bus specific driver trait. For instance:
pub trait Driver: Send {
/// The type holding information about each device ID supported by the driver.
type IdInfo: 'static;
/// The table of OF device ids supported by the driver.
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
/// The table of ACPI device ids supported by the driver.
const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
/// Driver probe.
fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>;
/// Driver unbind (optional).
fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {
let _ = (dev, this);
}
}
For specific examples see auxiliary::Driver
, pci::Driver
and platform::Driver
.
The probe()
callback should return a Result<Pin<KBox<Self>>>
, i.e. the driver’s private
data. The bus abstraction should store the pointer in the corresponding bus device. The generic
Device
infrastructure provides common helpers for this purpose on its
Device<CoreInternal>
implementation.
All driver callbacks should provide a reference to the driver’s private data. Once the driver
is unbound from the device, the bus abstraction should take back the ownership of the driver’s
private data from the corresponding Device
and drop
it.
All driver callbacks should provide a Device<Core>
reference (see also device::Core
).
§Adapter
The adapter implementation of a bus represents the abstraction layer between the C bus callbacks and the Rust bus callbacks. It therefore has to be generic over an implementation of the driver trait.
pub struct Adapter<T: Driver>;
There’s a common Adapter
trait that can be implemented to inherit common driver
infrastructure, such as finding the ID info from an of::IdTable
or acpi::IdTable
.
§Driver Registration
In order to register C driver types (such as struct platform_driver
) the adapter
should implement the RegistrationOps
trait.
This trait implementation can be used to create the actual registration with the common
Registration
type.
Typically, bus abstractions want to provide a bus specific module_bus_driver!
macro, which
creates a kernel module with exactly one Registration
for the bus specific adapter.
The generic driver infrastructure provides a helper for this with the module_driver
macro.
§Device IDs
Besides the common device ID types, such as of::DeviceId
and acpi::DeviceId
, most buses
may need to implement their own device ID types.
For this purpose the generic infrastructure in device_id
should be used.
Structs§
- Registration
- A
Registration
is a generic type that represents the registration of some driver type (e.g.bindings::pci_driver
). Therefore aRegistration
must be initialized with a type that implements theRegistrationOps
trait, such that the genericT::register
andT::unregister
calls result in the subsystem specific registration calls.
Traits§
- Adapter
- The bus independent adapter to match a drivers and a devices.
- Registration
Ops - The
RegistrationOps
trait serves as generic interface for subsystems (e.g., PCI, Platform, Amba, etc.) to provide the corresponding subsystem specific implementation to register / unregister a driver of the particular type (RegType
).