NAME | SYNOPSIS | API RESTRICTIONS | FEATURES | DESCRIPTION | EXTENDED DESCRIPTION | Allowed Calling Contexts | ATTRIBUTES | SEE ALSO
#include <dki/dki.h>void svDeviceRegister(DevRegId dev_id);
The function or functions documented here may not be used safely in all application contexts with all APIs provided in the ChorusOS 5.0 product.
See API(5FEA) for details.
DKI
Provides access to microkernel services implementing the device registry .
The device registry microkernel module implements a database of driver instances servicing devices supported by the system. The device registry database is populated by drivers which perform self-registration (using svDeviceRegister() ) at device initialization time. The device registry database is accessed by driver clients to obtain a pointer to the driver instance servicing a given (logical) device. The device registry API is described below in detail.
Only the svDeviceLookup() , svDeviceRelease() , svDeviceNewNotify() , svDeviceNewCancel() , 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.
The entry is allocated in an invalid state. This means that the entry is not included in the registry and therefore, is not visible to clients through 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 structure is as follows:
typedef struct { char* dev_class; void* dev_ops; void* dev_id; DevNode dev_node; } DevRegEntry;
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 that is serviced by the driver.
A driver client must switch to the DKI thread context when accessing the device tree structure.
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.
The 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 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.
To declare different classes (APIs) for the same physical device, the device driver may allocate (and then register) multiple entries. For instance, a driver may implement orthogonal sets of operations, like power management which are additional to the main device function. Another example is a device driver servicing a multi-function device. This type of driver would register multiple entries, that is, 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 through svDeviceAlloc() . A pointer to the DevRegEntry structure (previously specified through 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, 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 using 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 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 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 to 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.
Prior to the shutdown event propagation, svDeviceEvent() removes the device entry from the registry to prevent the entry from being found (and locked) by new driver clients. After all driver client handlers are invoked, svDeviceEvent() returns to the driver.
The real device shutdown has to be deferred until the handler routine invocation.
After the device entry is released by the last driver client, the device registry module invokes handler previously specified using svDeviceAlloc() . A pointer to the DevRegEntry structure (previously specified through svDeviceAlloc() ) is passed back to the driver as the argument of handler . The handler routine is called in the DKI thread context.
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 . And, there is a device entry in the dev_class with a logical unit greater than dev_unit , or 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() .
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 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. After the device entry has been released, a device driver client should no longer access the device driver instance or the device node.
The svDeviceNewNotify() routine connects a given handler to the device registry. The handler is invoked by the device registry module each time a new device is registered. The handler argument specifies the handler being connected. The cookie argument is passed back to the handler when it is invoked. The new_id argument is an output argument identifying the connected handler. This new_id should be passed back as an argument to a subsequent svDeviceNewCancel() to disconnect the handler.
The handler is invoked in the DKI thread context.
The svDeviceNewCancel() routine disconnects a handler previously connected by svDeviceNewNotify() . The new_id argument specifies the handler being disconnected.
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() | + | + | - | - |
svDeviceNewNotify() | + | + | - | + |
svDeviceNewCancel() | + | + | - | + |
See attributes(5) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
---|---|
Interface Stability | Evolving |
NAME | SYNOPSIS | API RESTRICTIONS | FEATURES | DESCRIPTION | EXTENDED DESCRIPTION | Allowed Calling Contexts | ATTRIBUTES | SEE ALSO