Device Driver Interface

The device driver interface consists of processing functions specified when registering a device. These functions are called by device management and run as a quasi-task portion. They must be reentrant. The mutually exclusive calling of these processing functions is not guaranteed. If, for example, there are simultaneous requests from multiple devices for the same device, different tasks might call the same processing function at the same time. The device driver must apply mutual exclusion control in such cases as required.

IO requests to a device driver are made by means of the following request packet mapped to a request ID.


typedef	struct t_devreq {
	struct	t_devreq *next;	/* I: Link to request packet (NULL: termination)	*/
	VP	exinf;	/* X: Extended information	 */
	ID	devid;	/* I: Target device ID	*/
	INT	cmd:4;	/* I: Request command	*/
	BOOL	abort:1;	/* I: TRUE if abort request	*/
	W	start; 	/* I: Starting data number	*/
	W	size;	/* I: Request size	*/
	VP	buf;	/* I: IO buffer address	*/
	W	asize;	/* O: Size of result	*/
	ER	error;	/* O: Error result	*/
/* Implementation-dependent information may be added beyond this point.	*/
} T_DEVREQ;

I indicates an input parameter and O an output parameter. @I@nput parameters must not be changed by the device driver. Parameters other than input parameters (I) are initially cleared to 0 by device management. After that, device management does not modify them. next is used to link the request packet. @I@n addition to being used for keeping track of request packets in device management, it is also used by the completion wait function (waitfn) and abort function (abortfn).

exinf can be used freely by the device driver to store any other information. Device management does not pay attention to its contents.

The device ID of the device to which the request is issued is specified in devid.

The request command is specified in cmd as follows.

cmd := (TDC_READ || TDC_WRITE)


	#define	TDC_READ	1	/* read request */
	#define	TDC_WRITE	2	/* write request */

If abort processing is to be carried out, abort is set to TRUE right before calling the abort function (@abort@fn). abort is a flag indicating whether abort processing was requested and does not indicate that processing was @abort@ed. In some cases, abort is set to TRUE even when the abort function (@abort@fn) is not called. Abort processing is performed when a request with abort set to TRUE is actually passed to the device driver.

The start and size parameters for the tk_rea_dev and tk_wri_dev calls are set to the values specified here.

Similarly, the buf parameter for tk_rea_dev or tk_wri_dev calls are set to the value specified here.

In asize, the device driver sets the value returned in asize by tk_wai_dev.

In error, the device driver sets the error code returned by tk_wai_dev in its return code. E_OK indicates a normal result.

[Difference with T-Kernel]

Specifications concerning virtual memory and user space do not exist, so nolock and tskspc do not exist among T_DEVREQ members. Also, the reserved member rsv does not exist so that the different bit widths of the INT type on different targets can be absorbed.

[Difference with T-Kernel 1.00.00]

The type of start, size, and asize is W instead of INT.

[Porting Guideline]

The specifications concerning virtual memory do not exist in µT-Kernel, so all memory is treated as actual memory. Thus, when a device driver created for µT-Kernel is used in the systems with T-Kernel’s virtual memory, the application should make the memory resident.

Similarly, the specification concerning user space does not exist in µT-Kernel. So when device drivers created for µT-Kernel are ported to the T-Kernel, they should be implemented so that the buffer area prepared by the application can be allocated in shared space.

  • Open Function: ER openfn( ID devid, UINT omode, VP exinf )

devid Device ID of the device to open

omode Open mode (same as tk_opn_dev)

exinf Extended information set at device registration

return code Error

The open function openfn is called when tk_opn_dev is invoked.

The function openfn performs processing to enable the use of a device. Details of the processing are device-dependent; if no processing is needed, it does nothing. The device driver does not need to remember whether a device is open or not, nor is it necessary to treat as error the calling of another processing function only because the device was not opened (openfn had not been called). If another processing function is called for a device that is not open, the necessary processing may be performed as long as there is no problem in device driver operation.

When openfn is used to perform operations such as device initialization, in principle, no processing should be performed that causes a WAIT state. The processing and return from openfn must be as prompt as possible. In the case of a device such as a serial port for which it is necessary to set the communication mode, for example, the device can be initialized when the communication mode is set by tk_wri_dev. In such cases, there is no need for openfn to initialize the device.

When the same device is opened multiple times, normally this function is called only the first time. If, however, the driver attribute TDA_OPENREQ is specified in device registration, this function is called each time the device is opened.

Since processing related to the mode of opening and the opening of the device multiple times is handled by device management, processing related to them is not required in the openfn function. Similarly, omode is simply passed as reference information; no processing related to omode is required.

  • Close Function: ER closefn( ID devid, UINT option, VP exinf )

devid Device ID of the device to close

option Close option (same as tk_cls_dev)

exinf Extended information set at device registration

return code Error

The close function closefn is called when tk_cls_dev is invoked.

The closefn function performs processing to end use of a device. Details of the processing are device-dependent; if no processing is needed, it does nothing.

If the device is capable of ejecting media and TD_EJECT is set in option, media ejection is performed.

When closefn is used to perform device shutdown processing or media ejection, in principle, no processing should be performed that causes a WAIT state. The processing and return from closefn must be as prompt as possible. If media ejection takes time, control may be returned from closefn without waiting for the ejection to complete.

When the same device is opened multiple times, normally this function is called only the last time it is closed. If, however, the driver attribute TDA_OPENREQ is specified in device registration, this function is called each time the device is closed. In this case TD_EJECT is specified in option only the last time.

Since processing related to the mode of opening and the opening of the device multiple times is handled by device management, processing related to them is not required in the closefn function.

  • Processing Start Function: ER execfn( T_DEVREQ *devreq, TMO tmout, VP exinf )

devreq Request packet

tmout Request acceptance timeout (ms)

exinf Extended information set at device registration

return code Error

The execfn function is called when tk_rea_dev or tk_wri_dev is invoked and starts the processing requested in devreq. This function only starts the requested processing, returning to its caller without waiting for the processing to complete. The time required to start processing depends on the device driver; this function does not necessarily complete immediately.

When new processing cannot be accepted, this function goes to WAIT state for request acceptance. If the new request cannot be accepted within the time specified in tmout, the function times out.

The attribute TMO_POL or TMO_FEVR can be specified in tmout. If the function times out, E_TMOUT is passed in the execfn return code. The timeout applies only to request acceptance and not to the processing after acceptance.

When error is passed in the execfn return code, the request is considered not to have been accepted and the request packet is discarded.

If processing is aborted before the request is accepted (before the requested processing starts), E_ABORT is passed in the execfn return code and the request packet is discarded. If processing is aborted after the processing has been accepted, E_OK is returned for this function. The request packet is not discarded until waitfn is executed and processing completes.

When processing is aborted, the important thing is to return from execfn as quickly as possible. If processing will end soon anyway without aborting, it is not necessary to abort.

  • Completion Wait Function: INT waitfn( T_DEVREQ *devreq, INT nreq, TMO tmout, VP exinf )

devreq Request packet list

nreq Request packet count

tmout Timeout (ms)

exinf Extended information set at device registration

return code Completed request packet number or error

The waitfn function is called when tk_wai_dev is invoked.

devreq is a list of request packets in a chain linked by devreqnext. This function waits for completion of any of the nreq request packets starting from devreq. The final next is not necessarily NULL, so the count passed in nreq must always be followed. The number of the completed request packets (which one after devreq) is passed in the return code. The first one is numbered 0 and the last one is numbered nreq-1. Here completion means any of normal completion, abnormal (error) termination, or abort.

The time to wait until completion is set in tmout. TMO_POL or TMO_FEVR can be specified as the tmout attribute. If the wait times out, the requested processing continues. The waitfn return code in case of timeout is E_TMOUT. The error parameter of the request packet does not change. Note that if return from waitfn occurs while the requested processing continues, error must be returned in the waitfn return code but the processing must be completed even when error is passed in the return code, and a value other than error must not be returned if processing is ongoing. As long as error is not passed in the waitfn return code, the request is considered to be pending and no request packet is discarded. When the number of a request packet whose processing was completed is passed in the waitfn return code, the processing of that request is considered to be completed and that request packet is discarded.

IO error and other device-related errors are stored in the error parameter of the request packet. Error is passed in the waitfn return code when completion waiting did not take place properly. The waitfn return code is set in the tk_wai_dev return code, whereas the request packet error value is returned in ioer.

Abort processing differs depending on whether the wait is for completion of a single request (nreq = 1) or multiple requests (nreq > 1). When completion of a single request is being waited for, the request currently being processed is aborted. When waiting for completion of multiple requests, only the wait is aborted (wait release), not the requested processing itself. When a wait for multiple requests is aborted (wait release), E_ABORT is passed in the waitfn return code.

During a wait for request completion, an abort request may be set in the abort parameter of a request packet. In such a case, if it is a single request, the request abort processing must be performed. If the wait is for multiple requests, it is also preferable that abort processing be executed, but it is also possible to ignore the abort flag.

When abort occurs, the important thing is to return from waitfn as quickly as possible. If processing will end soon anyway without aborting, it is not necessary to abort.

As a rule, E_ABORT is returned in the request packet error parameter when processing is aborted; but a different error code may be returned as appropriate based on the device properties. Returning E_OK on the basis that the processing right up to the abort is valid is also allowed. If processing completes normally to the end, E_OK is returned even if there was an abort request.

  • Abort Function: ER abortfn( ID tskid, T_DEVREQ *@devreq@, INT nreq, VP exinf )

tskid Task ID of the task executing execfn or waitfn

devreq Request packet list

nreq Request packet count

exinf Extended information set at device registration

return code Error

The function abortfn causes execfn or waitfn to return promptly when the specified request is being executed. Normally this means the request being processed is aborted. If, however, the processing can be completed soon without aborting, it may not have to be aborted. The important thing is to return as quickly as possible from execfn or waitfn.

tskid indicates the task executing the request specified in devreq. In other words, it is the task executing execfn or waitfn. devreq and nreq are the same as the parameters that were passed to execfn or waitfn. In the case of execfn, nreq is always 1.

@@abort@fn@ is called by a different task from the one executing execfn or waitfn. Since both tasks run concurrently, mutual exclusion control must be performed as necessary. It is possible that the @@abort@fn@ function will be called immediately before calling execfn or waitfn, or during return from these functions. Measures must be taken to ensure proper operation in such cases. Before @@abort@fn@ is called, the abort flag in the request packet whose processing is to be @abort@ed is set to TRUE, enabling execfn or waitfn to know whether there is going to be an abort request.

When waitfn is executing for multiple requests (nreq > 1), this is treated as a special case differing as follows from other cases.

— Only the completion wait is aborted (wait release), not the requested processing.

— The abort flag is not set in the request packet (remains as abort = FALSE).

Aborting a request when execfn and waitfn are not executing is done not by calling @@abort@fn@ but by setting the abort flag in the request packet. If execfn is called when the abort flag is set, the request is not accepted. If waitfn is called, abort processing is the same as that when @@abort@fn@ is called.

If a request for which processing was started by execfn is aborted before waitfn was called to wait for its completion, the completion of the aborted processing is notified when waitfn is called. Even though processing was aborted, the request itself is not discarded until its completion has been confirmed by waitfn.

abortfn only starts abort processing returning promptly without waiting for the abort to complete.

abortfn is called in the following cases.

— When a device is being closed by tk_cls_dev or by subsystem cleanup processing, and a device descriptor was processing a request, abortfn is used to abort the request being processed by that device descriptor.

  • Event Handling Function: INT eventfn( INT evttyp, VP evtinf, VP exinf )

evttyp Driver request event type

evtinf Information for each event type

exinf Extended information set at device registration

return code Return code defined for each event type or error

The following driver request event types are defined. Those with positive values are called by tk_evt_dev, and those with negative values are called inside device management.


	#define	TDV_SUSPEND	(-1)	/* suspend	*/
	#define	TDV_RESUME	(-2)	/* resume	*/
	#define	TDV_CARDEVT	1	/* PC Card event (see Card Manager	*/
	#define	TDV_USBEVT	2	/* USB event (see USB Manager)	*/

The processing performed by an event function is defined for each event type. Suspend and resume processing are discussed later below.

When a device event is called by tk_evt_dev, the eventfn return code is set as the tk_evt_dev return code.

Requests to event functions must be accepted even if another request is processing and must be processed as quickly as possible.

Comments

Click here to Post a Comment