ChorusOS 4.0 Device Driver Framework Guide

Driver Initialization

The microkernel initialization goes through the following steps:

  1. device independent microkernel initialization

  2. built-in device drivers initialization

  3. device dependent microkernel initialization

At the first step, the microkernel performs initialization of device-independent modules like executive, memory management and so on.

At the second step, the microkernel installs and launches the built-in device driver actor(s) (drivers which are embedded in the ChorusOS operating system archive). Note that each driver actor's main() function is invoked sequentially by the microkernel initialization thread. The driver's main() function should perform a self-registration of the driver component within the system, by using the DKI interface.

When registering, the driver exports its properties to the system:

Once the driver component is self-registered, future management of the driver is controlled by its parent bus/nexus driver, using the properties registered.

The four possible entry points that a driver component may register are:

Finally, once built-in driver components have been started, the microkernel performs initialization of device dependent modules (like the "TICK" module which relies on a TIMER class device).


Note -

Interrupts are disabled at CPU level during the first, second and third initialization steps. Once the built-in drivers are initialized, interrupts are enabled at CPU level.


Once all of the driver's main() functions are invoked, the microkernel initiates the device initialization process. This can be seen as the microkernel implementing a local bus driver (bound to the device tree root node) for a DKI/FDKI bus class.

The initialization process starts from driver components servicing bus or device controllers directly connected to the CPU local bus; the driver registry is searched to find out the appropriate drivers and to call their registered entry points. Typically, the probe registered function is called for all driver components requiring a DKI/FDKI parent bus class. After probing, the bind function is called for all driver components requiring a DKI/FDKI parent bus class. Finally, after binding, the initializeregistered function is called for all driver components requiring a DKI/FDKI parent bus class, that are bound to a child of the device tree root node (nodes representing a bus or a device controller directly connected to the CPU local bus).


Note -

The drv_probe, drv_bind and drv_init routines are all optional


The drv_probe routine detects device(s) residing on the bus and creates corresponding device nodes in the device tree. The drv_bind routine allows drivers to perform a driver-to-device binding. The driver examines the properties attached to the device node in order to determine the type of device and to check whether the device may be serviced by the driver. If the check is positive, the driver attaches a driver property to the device node. The name of the driver node is "driver" and it has a string type value, specifying its name. The initialization process is propagated by the drv_init function of the bus/nexus drivers started by the microkernel.

In addition, when a driver instance is activated by a parent bus/nexus driver (through its registered drv_init() function), it establishes a connection to its parent bus driver (typically through an open service of the bus API) specifying a call-back event handler and a load handler. The parent bus/nexus driver uses the call-back event handler mechanism to propagate the bus events to the connected child driver instances. These events are typically bus-class specific, but are usually used to shut down child driver instances. The load handler is used (together with the unload entry point) to manage dynamic loading/unloading of the driver components.