NAME | SYNOPSIS | FEATURES | DESCRIPTION | EXTENDED DESCRIPTION | Allowed Calling Contexts | ATTRIBUTES | SEE ALSO
#include <dki/dki.h>void svDeviceRegister(DevRegId dev_id);
typedef struct { char* dev_class; void* dev_ops; void* dev_id; DevNode dev_node; } DevRegEntry;
DKI
Provides access to microkernel services implementing the device registry .
The device registry microkernel module implements a data base of driver instances servicing devices currently supported by the system. The device registry data base is populated by drivers which perform self-registration (using svDeviceRegister ) at device initialization time. The device registry data base is accessed by driver clients in order to obtain a pointer to the driver instance servicing a given (logical) device. The device registry API is described below in detail.
Note that only the svDeviceLookup , svDeviceRelease and svDeviceEntry microkernel calls should be used by driver clients. The rest of the API is dedicated to device drivers.
svDeviceAlloc allocates a device registry entry for a given device driver instance. Note that the entry is allocated in an invalid state. This means that the entry is not included in the registry (it is not visible to clients via svDeviceLookup ).
The entry becomes valid (visible to clients) when a subsequent svDeviceRegister is invoked. On the other hand, the driver is allowed to call svDeviceEvent on this type of entry. Shut down events signaled on an invalid entry are memorized by the device registry and they are processed when the entry becomes valid (that is, when svDeviceRegister is called).
The entry argument points to the DevRegEntry structure which designates the device driver instance. The DevRegEntry structure is described below:
Points to a string specifying the device class name.
Points to a structure of driver service routines.
Points to a handle which is usually passed back to the driver (as first argument) each time a driver service routine is invoked.
Specifies the device node in the tree which is serviced by the driver. Note that a driver client must switch to the DKI thread context when accessing the device tree structure (see section "Device Node Properties").
The version argument specifies the driver interface version implemented by the device driver instance.
The dev_class field and version argument specify APIs implemented by the driver. This type of API is provided to driver clients as a structure of indirect functions implementing the API service routines. For instance, the "uart" device API is specified by the UartDevOps structure, the "timer" device API is specified by the TimerDevOps structure. A pointer to this type of structure is obtained by a device driver client from the dev_ops field of the device registry entry.
The shared argument specifies whether the device driver instance may be shared between multiple clients. In other words, it indicates whether the registered instance may be looked up multiple times.
The handler argument specifies the driver handler which is invoked by the device registry module as an acknowledgement to a shut-down event (see svDeviceEvent ). handler is called when the last reference to the device registry entry goes away and a shut-down event has been previously signalled on the entry. entry is passed back to the driver as the argument of handler .
In case of success, a non zero DevRegId is returned, otherwise NULL is returned.
Device registry assigns a logical unit number to the physical device. The logical unit number is unique within dev_class . The device registry handles a logical unit counter per class. All counters are initialized to zero. Each time a new device entry's is allocated, the current counter value is assigned to the entry logical unit number and the counter is incremented. Thus, the logical device order within a class corresponds to the allocation order.
The logical unit number is mainly used by device driver clients to iterate through a given device class looking for a certain device. Using a valid logical unit number, a client is able to access the corresponding device registry entry, in particular, the dev_node field which points to the device node. The physical device corresponding to a given logical unit number may then be detected by the device node properties and the node position within the device tree.
The device driver may allocate (and then register) multiple entries in order to declare different classes (APIs) for the same physical device. For instance, a driver may implement orthogonal sets of operations like power management which are additional to the main device functionality. Another example is a device driver servicing a multi-function device. This type of driver would register multiple entries: one entry per device function. From the client's point of view, this type of device would be visible as multiple (mono-function) independent devices.
svDeviceRegister adds a given device registry entry to the registry. The entry must be previously allocated by svDeviceAlloc . The entry becomes valid (and therefore visible for clients) only if there is no shut-down event signalled on the entry. Otherwise, the entry remains invalid and the device registry module invokes a handler previously specified via svDeviceAlloc . A pointer to the DevRegEntry structure (previously specified via svDeviceAlloc ) is passed back to the driver as the argument of handler . The handler routine is called in the DKI thread context.
When handler is called the entry is no longer registered. Thus, it is useless to invoke svDeviceUnregister once handler has been called. On the other hand, in order to free memory resources, the driver should release the device registry entry invoking svDeviceFree once the entry is no longer used by the driver. Typically, the entry is no longer used by the driver when the connection to the parent bus/nexus driver is closed, and the parent driver is unable to invoke a call-back handler signalling a bus/nexus event.
svDeviceUnregister removes the device entry from the device registry (if the entry is valid). The device entry being removed is specified by the dev_id argument. svDeviceUnregister returns the following results when a valid entry is specified:
The device entry has been successfully removed from the registry.
The device entry has not been removed from the registry because it is locked by a driver client. In other words, the svDeviceLookup/Release pairs are not balanced.
svDeviceUnregister returns K_EBUSY when an invalid entry is specified. The driver must remove all related device entries from the registry prior to being unloaded from the system. Typically, svDeviceUnregister is issued by the device driver (for each device driver instance) when the driver code is requested to be unloaded via drv_unload . The driver unload fails when the driver code is still being used by the system.
svDeviceEvent notifies the device registry module that a shutdown event has occurred (for example, that a hot-pluggable device has been removed). The shutdown event basically means that the driver instance should no longer be used by driver clients and the device entry must be removed from the registry (that is, the driver instance will disappear). The shutdown event is immediately propagated to all driver clients in order to stop the device usage and to release the device entry as soon as possible. The device is specified by the dev_id argument.
svDeviceEvent propagates the shutdown event invoking the event_handler routines specified by the driver clients in svDeviceLookup . The event and arg arguments are opaque for the device registry. They are passed (as arguments) to the client event handlers. event specifies the reason for the shut-down as follows:
Normal device shut down
Hot-plug (surprise) device removal
arg is event specific.
All driver clients are requested to release the device entry (as soon as possible) invoking the svDeviceRelease routine. Note that, prior to the shutdown event propagation, svDeviceEvent removes the device entry from the registry in order to prevent the entry from being found (and locked) by new driver clients. Once all driver client handlers are invoked, svDeviceEvent returns to the driver. Note that the real device shutdown has to be deferred until the handler routine invocation.
Once the device entry is released by the last driver client, the device registry module invokes handler previously specified via svDeviceAlloc . A pointer to the DevRegEntry structure (previously specified via svDeviceAlloc ) is passed back to the driver as the argument of handler . The handler routine is called in the DKI thread context.
Typically, svDeviceEvent is used by a device driver servicing a hot-pluggable device. svDeviceEvent is invoked by the device driver when the driver is notified (by its parent driver) that the device has been removed from the bus.
In the case of hot-plug removal, the device driver must still be operational until the device entry is released (ignoring all requests to the driver, for example). The driver is allowed to call svDeviceEvent on an invalid (unregistered) entry. In this type of case, handler will be invoked only when a registration attempt is made, that is, svDeviceRegister will be invoked. In addition, the registration will fail and the entry will remain invalid.
svDeviceFree releases a given device registry entry previously allocated by svDeviceAlloc . The device entry being released is specified by the dev_id argument. The entry being released must be invalid (unregistered). Thus, if the entry was registered by svDeviceRegister , the driver is allowed to release it if either the entry is successfully unregistered by svDeviceUnregister or handler (previously specified by svDeviceAlloc ) is invoked.
svDeviceLookup searches the device entry in the registry matching the specified device class and logical unit.
Specifies the device class.
Specifies the minimum device driver interface version required.
Specifies the logical device unit in the class.
Specifies the event handler which is called when a device event is signalled.
Specifies the first argument of cli_handler .
Is an output argument identifying the client token on the matching device entry. This cli_id is passed back as an argument to svDeviceEntry to get the associated device entry, or to svDeviceRelease to release the device driver instance.
svDeviceLookup returns the following results:
The device entry matching the dev_class and dev_unit pair was found in the registry.
The device entry matching the dev_class and dev_unit pair was not found in the registry. Or, the device is being used by another client and device sharing is not allowed.
There is no device entry in the registry matching dev_class .
There is no device entry in the registry matching dev_unit in the dev_class . Or, there is a device entry in the dev_class with a logical unit greater than dev_unit . In other words, dev_unit falls into a hole in the dev_class unit ranges. The device entry matching the dev_class and dev_unit pair found in the registry is implementing an older version of the interface than the one required.
There is no device entry in the registry matching dev_unit in the dev_class . Moreover dev_unit is greater than all existing logical units in the dev_class .
In case of success, the corresponding device entry is locked in the registry until a subsequent svDeviceRelease . Note that the device registry lock may or may not be exclusive, depending on the value of the shared argument specified in svDeviceAlloc . In other words, the device may be shared between multiple driver clients, if shared was TRUE at registration time. The device driver instance must not disappear while its device entry is locked in the registry.
In the case of a catastrophic device shutdown (for example, hot-plug removal) the device entry lock owners are notified (through the cli_handler routine invocation) that the device entry must be released as soon as possible.
The svDeviceEntry routine returns the device entry associated with a given client identifier. The cli_id argument specifies the client identifier previously returned by svDeviceLookup .
The svDeviceRelease routine releases the lock on the given device entry. The device entry is specified by the cli_id argument. Obviously, a device driver client should no longer access the device driver instance and the device node once the device entry has been released.
The following table specifies the contexts in which a caller is allowed to invoke each service:
Services | Base level | DKI thread | Interrupt | Blocking |
svDeviceAlloc | + | + | - | + |
svDeviceFree | + | + | - | + |
svDeviceRegister | + | + | - | + |
svDeviceUnregister | + | + | - | + |
svDeviceEvent | + | + | + | - |
svDeviceLookup | + | + | - | + |
svDeviceRelease | + | + | - | + |
svDeviceEntry | + | + | - | - |
See attributes(5) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
---|---|
Interface Stability | Evolving |
NAME | SYNOPSIS | FEATURES | DESCRIPTION | EXTENDED DESCRIPTION | Allowed Calling Contexts | ATTRIBUTES | SEE ALSO