Device Management Functions

Device management functions manage device drivers running on T-Kernel.

A device driver is a program that is implemented independent from T-Kernel itself to control a hardware device or perform I/O processing with the hardware device. Since the difference of specifications among individual devices is absorbed by the device driver when an application or middleware operates a device or performs I/O processing with the device via the device driver, the application or middleware can enhance its hardware independency and compatibility.

Device management functions include a function to define a device driver, or to register the device driver to T-Kernel, and a function to use the registered device driver from an application or middleware.

While this registration of device drivers is mostly performed in the initialization at system startup, it can also be performed dynamically during the normal operation of the system. A device driver is registered in the device registration information (ddev) that is one of parameters for the extended SVC, tk_def_dev(), by specifying the set of functions (driver processing functions) of a program that actually implements device driver. These functions include the open function (openfn) that is called when a device is opened, the execute function (execfn) that is called when read or write processing starts, wait-for-completion function (waitfn) that waits for completion of read or write processing, etc. The actual operation of a device or I/O processing with the devices are performed in these driver processing functions.

As these driver processing functions are executed at protection level 0 as quasi-task portion, they can also access hardware directly. I/O processing with a device may be performed directly in these driver processing functions or may be performed in another task that runs based on the request from one of these driver processing functions. The specification of parameters, etc. when these driver processing functions are called is specified as a device driver interface. The device driver interface is an interface between a device driver and the T-Kernel device management functions.

When a device driver program is implemented, it is recommended to separate three layers of interface, logical, and physical layers carefully in order to enhance their maintainability and portability. The interface layer is responsible for implementing an interface between the T-Kernel device management functions and a device driver. The logical layer is responsible for performing a common processing according to the type of device. The physical layer is responsible for performing an operation dependent on the actual hardware or control chip. The interface specification, however, among the interface layer, logical layer, and physical layer is not specified in the T-Kernel, so that the actual layer separation can be implemented appropriately in each device driver. Programs that process the interface layer may be provided as libraries since there are many common processings that are independent of individual devices in the physical layer.

Extended SVCs are provided such as open (tk_opn_dev()), close (tk_cls_dev()), read (tk_rea_dev()), write (tk_wri_dev()), etc. to use the registered device driver from an application or middleware. The specification of these extended SVCs is called an application interface. For example, when an application executes tk_opn_dev() to open a device, the T-Kernel calls the open function (openfn) for the corresponding device driver to request the device open processing.

The positioning and configuration of T-Kernel device management functions are shown in Figure 1.

Figure 1. Device Management Functions

NoteAdditional Notes
 

The device drivers have common features with the subsystems as being implemented independent from T-Kernel itself and also being a system program to add or extend functions for T-Kernel. Additionally, both are also same in that they are both executed by loading the program into the system space, operate at protection level 0, and can access a hardware. While API for calling a device driver is limited to using open/close and read/write type, API for calling a subsystem can be defined without any restriction. The subsystems have functions to manage resources but the device drivers have no functions to do so.

Though T-Kernel device drivers managed by device management functions are assumed to be drivers for physical devices or hardware, they are not necessarily required to handle real physical devices or hardware. Also, system program for operating a device could be implemented as a subsystem rather than a device driver if it is not compatible with open/close or read/write type APIs.

Common Notes Related to Device Drivers

Basic Concepts

In addition to a physical device that represents a device as a physical hardware, there is a logical device that represents a perceived unit of a device from the viewpoint of software.

Although both devices match for most devices, when partitions were created on a hard disk or any other storage type device (SD card, USB storage, etc.), entire device represents a physical device and each partition represents a logical device.

The physical devices of same type are identified by "unit" while logical devices in one physical device are identified by "subunit." For example, the information that distinguishes the first hard disk from the second is called "unit," and the information that distinguishes the first partition from the second within that first hard disk is called "subunit."

The data definitions used in device management functions are explained in the subsequent subsections.

Device Name (UB* type)

A device name is a string of up to eight characters that is given to each device. It consists of the following elements:

#define L_DEVNM         8       /* Device name length */

Type

Name indicating the device type

Characters a to z and A to Z can be used.

Unit

One letter indicating a physical device

Each unit is assigned a letter from a to z in order starting from a.

Subunit

One to three digits indicating a logical device

Each subunit is assigned a number from 0 to 254 in order starting from 0.

Device names take the format of type + unit + subunit. Some devices may not have a unit or subunit, in which case the corresponding field is omitted.

The subunit is usually used to distinguish partitions in a hard disk. In other devices also, it can be used to create multiple logical devices in one physical device.

A name consisting of type + unit is called a physical device name. A name consisting of type + unit + subunit is called a logical device name. If there is no subunit, the physical device name and logical device name are identical. The term "device name" by itself means the logical device name.

Example 1. Example of Device Name

Device nameTarget device
hdaHard disk (entire disk)
hda0Hard disk (1st partition)
fdaFloppy disk
rsaSerial port
kbpdKeyboard/pointing device

Device ID (ID type)

By registering a device (device driver) with T-Kernel/SM, a device ID (> 0) is assigned to the device (physical device name). Device IDs are assigned to each physical device. The device ID of a logical device consists of the device ID assigned to the physical device to which is appended the subunit number + 1 (1 to 255).

devid: The device ID assigned at device registration

devid           Physical device
devid + n+1     The nth subunit (logical device)

Example 2. Example of Device ID

Device nameDevice IDSummary description
hdadevidHard disk (entire disk)
hda0devid + 11st partition of hard disk
hda1devid + 22nd partition of hard disk

Device Attribute (ATR type)

Device attributes are defined in order to represent a feature for each device and classify a device for each type. Device attributes should be specified when registering a device driver.

The specification method of device attributes is as follows:

IIII IIII IIII IIII PRxx xxxx KKKK KKKK

The high 16 bits are device-dependent attributes defined for each device. The low 16 bits are standard attributes defined as follows.

#define TD_PROTECT      0x8000  /* P: Write protected */
#define TD_REMOVABLE    0x4000  /* R: removable media */

#define TD_DEVKIND      0x00ff  /* K: device/media kind */
#define TD_DEVTYPE      0x00f0  /*    device type */

                                /* device type */
#define TDK_UNDEF       0x0000  /* undefined/unknown */
#define TDK_DISK        0x0010  /* disk device */

As to the above shown device type, whether it is the disk type (TDK_DISK) or not affects the processing procedure at the time of suspend. For more details, see the description of tk_sus_dev and the Section called Special Properties of Disk Devices.

Within the realm of T-Kernel, the device type other than disk type is not defined. Defining the device type other than disk type does not affect the behavior of T-Kernel. Other devices are assigned to undefined type (TDK_UNDEF).

For the disk device, the disk kinds are additionally defined. The typical disk kinds are as follows: For disk types other than these, see the specification related to device drivers or the Section called Disk Kind for Device Attributes in the Chapter called Appendix in the Section called Specification Related to Device Drivers to be Used as Reference in the Chapter called Appendix.

 /* disk kind */
#define TDK_DISK_UNDEF  0x0010  /* miscellaneous disk */
#define TDK_DISK_HD     0x0015  /* hard disk */
#define TDK_DISK_CDROM  0x0016  /* CD-ROM */

The definition of disk kinds does not affect the T-Kernel behavior. These definitions are used only when they are required in a device driver or an application. For example, when an application must change its processing according to the kind of devices or media, the disk kind information is used. Devices or media that do not need such distinctions do not have to be assigned a device type.

Device Descriptor (ID type)

A device descriptor is an identifier used to access a device.

The device descriptor is assigned a positive value (> 0) by the T-Kernel/SM when a device is opened.

The device descriptor belongs to the same resource group as that of the task that opened the device. Operations using a device descriptor can be performed only by tasks belonging to the same resource group as the device descriptor. Error code (E_OACV) is returned for requests from tasks belonging to a different resource group.

Request ID (ID type)

When an I/O request is made to a device, a request ID (> 0) is assigned identifying the request. This ID can be used to wait for I/O completion.

Data Number (W type, D type)

Data input/output from/to device is specified by a data number. Data is roughly classified into device-specific data and attribute data.

Device-specific data: Data number ≧ 0

As device-specific data, the data numbers are defined separately for each device.

Example 3. Example of Device-specific Data

deviceData number
DiskData number = physical block number
Serial portData number = 0 only

Attribute data: Data number < 0

Attribute data specifies driver or device state acquisition and setting modes, and special functions, etc.

Data numbers common to devices are defined, but device-dependent attribute data can also be defined. For more details, see the Section called Attribute Data.

Attribute Data

Attribute data are classified broadly into the following three types of data.

Common attributes

Attributes defined in common for all devices (device drivers).

Device kind attributes

Attributes defined in common for devices (device drivers) of the same kind.

Device-specific attributes

Attributes defined individually for each device (device driver).

For the device kind attributes and device-specific attributes, see the specifications related to device driver. Only the common attributes are defined here.

Common attributes are assigned attribute data numbers in the range from -1 to -99. While common attribute data numbers are the same for all devices, not all devices necessarily support all the common attributes. If an unsupported data number is specified, error code E_PAR is returned.

The definition of common attributes is as follows:

#define TDN_EVENT       (-1)    /* RW: event notification message buffer ID */
#define TDN_DISKINFO    (-2)    /* R: disk information */
#define TDN_DISPSPEC    (-3)    /* R: display device specification */
#define TDN_PCMCIAINFO  (-4)    /* R: PC card information */
#define TDN_DISKINFO_D  (-5)    /* R: disk information (64-bit device) */

RW: read (tk_rea_dev)/write (tk_wri_dev) enabled
R-: read (tk_rea_dev) only

TDN_EVENT

Event notification message buffer ID

Data typeID

The ID of the message buffer used for device event notification.

As a device is registered by tk_def_dev when a device driver is started and the system default event notification message buffer ID (evtmbfid) is returned as this API return parameter, the value is held in the device driver and is used as the initial value of this attribute data.

If 0 is set, device events are not notified. For device event notification, see the Section called Device Event Notification.

TDN_DISKINFO

32-bit device and disk information

Data typeDiskInfo

typedef enum {
        DiskFmt_STD     = 0,            /* standard (HD, etc.) */
        DiskFmt_2HD     = 2,            /* 2HD 1.44MB */
        DiskFmt_CDROM   = 4             /* CD-ROM 640MB */
} DiskFormat;
typedef struct {
        DiskFormat format;              /* format */
        UW      protect:1;              /* protected status */
        UW      removable:1;            /* removable */
        UW      rsv:30;                 /* reserved (always 0) */
        W       blocksize;              /* block size in bytes */
        W       blockcount;             /* total block count */
} DiskInfo;

For definition of DiskFormat other than the above description, see the specification related to device drivers or the Section called Device Attribute Data in the Chapter called Appendix in the Section called Specification Related to Device Drivers to be Used as Reference in the Chapter called Appendix.

TDN_DISPSPEC

Display Device Specification

Data typeDEV_SPEC

For the definition of DEV_SPEC, see the specification related to device drivers or the Section called Device Attribute Data in the Chapter called Appendix in the Section called Specification Related to Device Drivers to be Used as Reference in the Chapter called Appendix.

TDN_DISKINFO_D

64-bit device and disk information

Data typeDiskInfo_D

typedef struct diskinfo_d {
        DiskFormat format;      /* format */
        BOOL    protect:1;      /* protected status */
        BOOL    removable:1;    /* removable */
        UW      rsv:30;         /* reserved (0) */
        W       blocksize;      /* block size in bytes */
        D       blockcont_d;    /* total number of blocks in 64-bit */
} DiskInfo_D;

Difference between DiskInfo_D and DiskInfo is only the part of their names being blockcont or blockcont_d, and the data type.

T-Kernel/SM does not convert a data between DiskInfo and DiskInfo_D. Both TDN_DISKINFO and TDN_DISKINFO_D just pass the request to device driver without any modification.

A disk driver must support TDN_DISKINFO and/or TDN_DISKINFO_D. It is recommended that TDN_DISKINFO is supported wherever possible for compatibility with T-Kernel 1.0.

Even if the total number of blocks of entire disk exceeds W, the number of blocks of individual partition may fit within W. In that case, the preferable implementation is such that a partitions fitting within W correspond to TDN_DISKINFO and partitions not fitting within W are determined to be an error (E_PAR) by TDN_DISKINFO. It is also preferable that TDN_DISKINFO_D is supported even if the number of blocks fit within W.

There is no direct dependency between the support for TDN_DISKINFO_D and the device driver attribute TDA_DEV_D. A device driver does not always have TDA_DEV_D attribute even if TDN_DISKINFO_D is supported. Also, TDN_DISKINFO_D is not always supported even if the device driver has TDA_DEV_D attribute.

As the definition of common attributes described above is a part of the specification of device driver rather than T-Kernel, it does not directly affect the T-Kernel behavior. Each device driver does not need to implement all the functions defined in the common attributes. However, as the definition of common attributes is applicable to all the device drivers, the specification of each device driver must be specified in a way that does not conflict with this definitions.

NoteDifference from T-Kernel 1.0
 

Attribute data for TDN_DISKINFO_D is added to support 64-bit devices.

Device Input/Output Operations

The application interface is used to make use of the registered device drivers from an application or middleware. The functions below are provided as application interface functions, called as extended SVC. These functions cannot be called from a task-independent portion or while dispatch or interrupts are disabled (E_CTX).

ID  tk_opn_dev( CONST UB *devnm, UINT omode )
ER  tk_cls_dev( ID dd, UINT option )
ID  tk_rea_dev( ID dd, W start, void *buf, W size, TMO tmout )
ID  tk_rea_dev_du( ID dd, D start_d, void *buf, W size, TMO_U tmout_u )
ER  tk_srea_dev( ID dd, W start, void *buf, W size, W *asize )
ER  tk_srea_dev_d( ID dd, D start_d, void *buf, W size, W *asize )
ID  tk_wri_dev( ID dd, W start, CONST void *buf, W size, TMO tmout )
ID  tk_wri_dev_du( ID dd, D start_d, CONST void *buf, W size, TMO_U tmout_u )
ER  tk_swri_dev( ID dd, W start, CONST void *buf, W size, W *asize )
ER  tk_swri_dev_d( ID dd, D start_d, CONST void *buf, W size, W *asize )
ID  tk_wai_dev( ID dd, ID reqid, W *asize, ER *ioer, TMO tmout )
ID  tk_wai_dev_u( ID dd, ID reqid, W *asize, ER *ioer, TMO_U tmout_u )
INT tk_sus_dev( UINT mode )
ID  tk_get_dev( ID devid, UB *devnm )
ID  tk_ref_dev( CONST UB *devnm, T_RDEV *rdev )
ID  tk_oref_dev( ID dd, T_RDEV *rdev )
INT tk_lst_dev( T_LDEV *ldev, INT start, INT ndev )
INT tk_evt_dev( ID devid, INT evttyp, void *evtinf )

tk_opn_dev - Open Device

C Language Interface

#include <tk/tkernel.h>

ID dd = tk_opn_dev (CONST UB *devnm , UINT omode );

Parameter

CONST UB* devnm Device NameDevice name
UINT omode Open ModeOpen mode

Return Parameter

ID dd Device DescriptorDevice descriptor
orError CodeError code

Error Code

E_BUSY Device BUSY (exclusive open)
E_NOEXS Device does not exist
E_LIMIT Open count exceeds the limit
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Opens the device specified in devnm in the mode specified in omode, and prepares for device access. The device descriptor is passed in the return code.

omode := (TD_READ || TD_WRITE || TD_UPDATE) | [TD_EXCL || TD_WEXCL || TD_REXCL]
         | [TD_NOLOCK]
#define TD_READ         0x0001          /* read only */
#define TD_WRITE        0x0002          /* write only */
#define TD_UPDATE       0x0003          /* read/write */
#define TD_EXCL         0x0100          /* exclusive */
#define TD_WEXCL        0x0200          /* exclusive write */
#define TD_REXCL        0x0400          /* exclusive read */
#define TD_NOLOCK       0x1000          /* unnecessary to be locked (resident) */

TD_READ

read only

TD_WRITE

Write only

TD_UPDATE

Read/write

Sets the access mode.

When TD_READ is set, tk_wri_dev() cannot be used.

When TD_WRITE is set, tk_rea_dev() cannot be used.

TD_EXCL

Exclusive

TD_WEXCL

Exclusive write

TD_REXCL

Exclusive read

Sets the exclusive mode.

When TD_EXCL is set, all concurrent opening is prohibited.

When TD_WEXCL is set, concurrent opening in write mode (TD_WRITE or TD_UPDATE) is prohibited.

When TD_REXCL is set, concurrent opening in read mode (TD_READ or TD_UPDATE) is prohibited.

Table 1. Whether Concurrent Open of Same Device is Allowed or NOT

Present Open ModeConcurrent Open Mode
No exclusive modeTD_WEXCLTD_REXCLTD_EXCL
RUWRUWRUWRUW
No exclusive modeRYESYESYESYESYESYESNONONONONONO
UYESYESYESNONONONONONONONONO
WYESYESYESNONONOYESYESYESNONONO
TD_WEXCLRYESNONOYESNONONONONONONONO
UYESNONONONONONONONONONONO
WYESNONONONONOYESNONONONONO
TD_REXCLRNONOYESNONOYESNONONONONONO
UNONOYESNONONONONONONONONO
WNONOYESNONONONONOYESNONONO
TD_EXCLRNONONONONONONONONONONONO
UNONONONONONONONONONONONO
WNONONONONONONONONONONONO
R = TD_READ
W = TD_WRITE
U = TD_UPDATE
YES = Yes, can be opened
NO = No, cannot be opened (E_BUSY)
TD_NOLOCK

unnecessary to be locked (resident)

Indicates that a memory space (buf) specified in I/O operations (tk_rea_dev and tk_wri_dev) has already been locked (made resident) on the calling side and does not have to be locked by the device driver. In this case the device driver does not (must not) lock the area. This is used e.g. to perform disk access for page-in/page-out in a virtual memory system. Generally it does not need to be specified.

The device descriptor belongs to the resource group of the task that opened the device.

When a physical device is opened, the logical devices belonging to it are all treated as having been opened in the same mode, and are processed as exclusive open.

tk_cls_dev - Close Device

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_cls_dev (ID dd , UINT option );

Parameter

ID dd Device DescriptorDevice descriptor
UINT option Close OptionClose option

Return Parameter

ER ercd Error CodeError code

Error Code

E_ID dd is invalid or not open
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Closes device descriptor dd. If a request is being processed, the processing is aborted and the device is closed.

option := [TD_EJECT]
#define TD_EJECT        0x0001          /* Eject media */

TD_EJECT

Eject media

If the same device has not been opened by another task, the media is ejected. In the case of devices that cannot eject their media, the request is ignored.

The subsystem cleanup processing (tk_cln_ssy) closes all the device descriptors belonging to the resource group.

tk_rea_dev - Start Read Device

C Language Interface

#include <tk/tkernel.h>

ID reqid = tk_rea_dev (ID dd , W start , void *buf , W size , TMO tmout );

Parameter

ID dd Device DescriptorDevice descriptor
W start Start LocationRead start location (≧ 0: Device-specific data, < 0: Attribute data)
void* buf BufferBuffer location for putting the read data
W size Read SizeRead size
TMO tmout TimeoutRequest acceptance timeout (ms)

Return Parameter

ID reqid Request IDRequest ID
orError CodeError code

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (read not permitted)
E_LIMIT Number of requests exceeds the limit
E_TMOUT Busy processing other requests
E_ABORT Processing aborted
Other Error code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Initiates reading device-specific data or attribute data from the specified device. This function initiates reading only, returning to its caller without waiting for the read operation to finish. The space specified in buf must be retained until the read operation completes. Read completion is waited for by tk_wai_dev(). The time required for initiating read operation differs among device drivers; return of control is not necessarily immediate.

In the case of device-specific data, the start and size units are defined for each device. With attribute data, start is an attribute data number and size is in bytes. The attribute data of the data number specified in start is read. Normally size must be at least as large as the size of the attribute data to be read. Reading of multiple attribute data in one operation is not possible. When size = 0 is specified, actual reading does not take place but the current size of data that can be read is checked.

Whether or not a new request can be accepted while a read or write operation is in progress depends on the device driver. If a new request cannot be accepted, the request is queued. The timeout for request waiting is set in tmout. The TMO_POL or TMO_FEVR attribute can be specified in tmout. Note that the timeout applies to the request acceptance. Once a request has been accepted, this function does not time out.

This extended SVC can be used for a device driver that has the TDA_DEV_D or TDA_TMO_U attribute. In that case, the parameters are converted appropriately by T-Kernel/SM. For example, when a device driver has the TDA_TMO_U attribute, the timeout interval (milliseconds) specified in tmout of this extended SVC is converted to the time in microseconds, and then passed to the device driver with the TDA_TMO_U attribute.

Difference from T-Kernel 1.0

The data type of start and size was changed from INT to W. This is because it is more easier to understand to fix the number of bits at a known value for the parameters closely related to the functions (time management and device management) that now have the 64-bit specifications in T-Kernel 2.0. The reason why the type of MSEC and TMO was changed from INT to W, and the type of RELTIM was changed from UINT to UW is also similar, in addition to the relationship with μT-Kernel.

tk_rea_dev_du - Read Device (in 64-bit microseconds)

C Language Interface

#include <tk/tkernel.h>

ID reqid = tk_rea_dev_du (ID dd , D start_d , void *buf , W size , TMO_U tmout_u );

Parameter

ID dd Device DescriptorDevice descriptor
D start_d Start LocationRead start location (64 bit, ≧ 0: Device-specific data, < 0: Attribute data)
void* buf BufferBuffer location for putting the read data
W size Read SizeRead size
TMO_U tmout_u TimeoutRequest acceptance timeout (in microseconds)

Return Parameter

ID reqid Request IDRequest ID
orError CodeError code

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (read not permitted)
E_LIMIT Number of requests exceeds the limit
E_TMOUT Busy processing other requests
E_ABORT Processing aborted
Other Error code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This extended SVC takes the parameters start_d (64 bits) and tmout_u (64-bit microseconds), instead of the parameters start and tmout of tk_rea_dev.

Its specification is the same as that of tk_rea_dev, except that the parameters are changed to start_d and tmout_u. For more details, see the description of tk_rea_dev.

Additional Notes

If the corresponding device driver does not have the TDA_DEV_D attribute, the error code E_PAR is returned when specifying a value that is out of the range of W for the start position start_d.

If the corresponding device driver does not have the TDA_TMO_U attribute (does not supports microseconds), it cannot handle the timeout in microseconds. In that case, the timeout (in microseconds) specified by this extended SVC in tmout_u is rounded to the time in milliseconds and passed to the device driver.

Thus, the appropriate conversion of parameters is executed by T-Kernel/SM. The application does not have to know whether the device driver has the TDA_DEV_D attribute or not, or whether the device driver supports 64 bits or not.

Difference from T-Kernel 1.0

This extended SVC was added in T-Kernel 2.0.

tk_rea_dev_du and tk_wri_dev_du include the both meanings of the suffixes, '_u' and '_d', because their start positions are 64 bits and timeouts are 64-bit microseconds.

tk_srea_dev - Synchronous Read

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_srea_dev (ID dd , W start , void *buf , W size , W *asize );

Parameter

ID dd Device DescriptorDevice descriptor
W start Start LocationRead start location (≧ 0: Device-specific data, < 0: Attribute data)
void* buf BufferBuffer location for putting the read data
W size Read SizeRead size
W* asize Actual SizePointer to the area to return the read size

Return Parameter

ER ercd Error CodeError code
W asize Actual SizeActually read size

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (read not permitted)
E_LIMIT Number of requests exceeds the limit
E_ABORT Processing aborted
Other Error code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Synchronous read. This is equivalent to the following.

ER tk_srea_dev( ID dd, W start, void *buf, W size, W *asize )
{
        ER      er, ioer;

        er = tk_rea_dev(dd, start, buf, size, TMO_FEVR);
        if ( er > 0 ) {
                er = tk_wai_dev(dd, er, asize, &ioer, TMO_FEVR);
                if ( er > 0 ) er = ioer;
        }

        return er;
}

This extended SVC can be used for a device driver that has the TDA_DEV_D attribute. In that case, the parameters are converted appropriately by T-Kernel/SM.

Difference from T-Kernel 1.0

The data type of start and size is changed from INT to W, and the data type of asize is changed from INT* to W*.

tk_srea_dev_d - Synchronous Read (64 bit)

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_srea_dev_d (ID dd , D start_d , void *buf , W size , W *asize );

Parameter

ID dd Device DescriptorDevice descriptor
D start_d Start LocationRead start location (64 bit, ≧ 0: Device-specific data, < 0: Attribute data)
void* buf BufferBuffer location for putting the read data
W size Read SizeRead size
W* asize Actual SizePointer to the area to return the read size

Return Parameter

ER ercd Error CodeError code
W asize Actual SizeActually read size

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (read not permitted)
E_LIMIT Number of requests exceeds the limit
E_ABORT Processing aborted
Other Error code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This extended SVC takes the 64-bit parameter start_d, instead of the parameter start of tk_srea_dev.

Its specification is the same as that of tk_srea_dev, except that the parameter is changed to start_d. For more details, see the description of tk_srea_dev.

Additional Notes

If the corresponding device driver does not have the TDA_DEV_D attribute, the error code E_PAR is returned when specifying a value that is out of the range of W for the start position start_d.

Thus, the appropriate conversion of parameters is executed by T-Kernel/SM. The application does not have to know whether the device driver has the TDA_DEV_D attribute, or whether the device driver supports 64 bits.

Difference from T-Kernel 1.0

This extended SVC was added in T-Kernel 2.0.

tk_wri_dev - Start Write Device

C Language Interface

#include <tk/tkernel.h>

ID reqid = tk_wri_dev (ID dd , W start , CONST void *buf , W size , TMO tmout );

Parameter

ID dd Device DescriptorDevice descriptor
W start Start Locationwrite start location (≧ 0: Device-specific data, < 0: Attribute data)
CONST void* buf BufferBuffer holding data to be written
W size Write SizeSize of data to be written
TMO tmout TimeoutRequest acceptance timeout (ms)

Return Parameter

ID reqid Request IDRequest ID
orError CodeError code

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (write not permitted)
E_RONLY Read-only device
E_LIMIT Number of requests exceeds the limit
E_TMOUT Busy processing other requests
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Initiates writing device-specific data or attribute data to a device. This function initiates writing only, returning to its caller without waiting for the write operation to finish. The space specified in buf must be retained until the write operation completes. Write completion is waited for by tk_wai_dev(). The time required for initiating write operation differs among device drivers; return of control is not necessarily immediate.

In the case of device-specific data, the start and size units are defined for each device. With attribute data, start is an attribute data number and size is in bytes. The attribute data of the data number specified in start is written. Normally size must be at least as large as the size of the attribute data to be written. Multiple attribute data cannot be written in one operation. When size = 0 is specified, actual writing does not take place but the current size of data that can be written is checked.

Whether or not a new request can be accepted while a read or write operation is in progress depends on the device driver. If a new request cannot be accepted, the request is queued. The timeout for request waiting is set in tmout. The TMO_POL or TMO_FEVR attribute can be specified in tmout. Note that the timeout applies to the request acceptance. Once a request has been accepted, this function does not time out.

This extended SVC can be used for a device driver that has the TDA_DEV_D or TDA_TMO_U attribute. In that case, the parameters are converted appropriately by T-Kernel/SM. For example, when a device driver has the TDA_TMO_U attribute, the timeout interval (milliseconds) specified in tmout of this extended SVC is converted to the time in microseconds, and then passed to the device driver with the TDA_TMO_U attribute.

Difference from T-Kernel 1.0

The data type of start and size was changed from INT to W.

tk_wri_dev_du - Write Device (in 64-bit microseconds)

C Language Interface

#include <tk/tkernel.h>

ID reqid = tk_wri_dev_du (ID dd , D start_d , CONST void *buf , W size , TMO_U tmout_u );

Parameter

ID dd Device DescriptorDevice descriptor
D start_d Start LocationWrite start location (64 bit, ≧ 0: Device-specific data, < 0: Attribute data)
CONST void* buf BufferBuffer holding data to be written
W size Write SizeSize of data to be written
TMO_U tmout_u TimeoutRequest acceptance timeout (in microseconds)

Return Parameter

ID reqid Request IDRequest ID
orError CodeError code

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (write not permitted)
E_RONLY Read-only device
E_LIMIT Number of requests exceeds the limit
E_TMOUT Busy processing other requests
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This extended SVC takes the parameters start_d (64 bits) and tmout_u (64-bit microseconds), instead of the parameters start and tmout of tk_wri_dev.

Its specification is the same as that of tk_wri_dev, except that the parameters are changed to start_d and tmout_u. For more details, see the description of tk_wri_dev.

Additional Notes

If the corresponding device driver does not have the TDA_DEV_D attribute, the error code E_PAR is returned when specifying a value that is out of the range of W for the start position start_d.

If the corresponding device driver does not have the TDA_TMO_U attribute (does not supports microseconds), it cannot handle the timeout in microseconds. In that case, the timeout (in microseconds) specified by this extended SVC in tmout_u is rounded to the time in milliseconds and passed to the device driver.

Thus, the appropriate conversion of parameters is executed by T-Kernel/SM. The application does not have to know whether the device driver has the TDA_DEV_D attribute or not, or whether the device driver supports 64 bits or not.

Difference from T-Kernel 1.0

This extended SVC was added in T-Kernel 2.0.

tk_rea_dev_du and tk_wri_dev_du include the both meanings of the suffixes '_u' and '_d', because their start positions are 64 bits and timeouts are 64-bit microseconds.

tk_swri_dev - Synchronous Write

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_swri_dev (ID dd , W start , CONST void *buf , W size , W *asize );

Parameter

ID dd Device DescriptorDevice descriptor
W start Start LocationWrite start location (≧ 0: Device-specific data, < 0: Attribute data)
CONST void* buf BufferBuffer holding data to be written
W size Write SizeSize of data to be written
W* asize Actual SizePointer to the area to return the written size

Return Parameter

ER ercd Error CodeError code
W asize Actual SizeActually written size

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (write not permitted)
E_RONLY Read-only device
E_LIMIT Number of requests exceeds the limit
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Synchronous write. This is equivalent to the following.

ER tk_swri_dev( ID dd, W start, void *buf, W size, W *asize )
{
        ER      er, ioer;

        er = tk_wri_dev(dd, start, buf, size, TMO_FEVR);
        if ( er > 0 ) {
                er = tk_wai_dev(dd, er, asize, &ioer, TMO_FEVR);
                if ( er > 0 ) er = ioer;
        }

        return er;
}

This extended SVC can be used for a device driver that has the TDA_DEV_D attribute. In that case, the parameters are converted appropriately by T-Kernel/SM.

Difference from T-Kernel 1.0

The data type of start and size is changed from INT to W, and the data type of asize is changed from INT* to W*.

tk_swri_dev_d - Synchronous Write (64 bit)

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_swri_dev_d (ID dd , D start_d , CONST void *buf , W size , W *asize );

Parameter

ID dd Device DescriptorDevice descriptor
D start_d Start LocationWrite start location (64 bit, ≧ 0: Device-specific data, < 0: Attribute data)
CONST void* buf BufferBuffer holding data to be written
W size Write SizeSize of data to be written
W* asize Actual SizePointer to the area to return the written size

Return Parameter

ER ercd Error CodeError code
W asize Actual SizeActually written size

Error Code

E_ID dd is invalid or not open
E_OACV Open mode is invalid (write not permitted)
E_RONLY Read-only device
E_LIMIT Number of requests exceeds the limit
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This extended SVC takes the 64-bit parameter start_d, instead of the parameter start of tk_swri_dev.

Its specification is the same as that of tk_swri_dev, except that the parameter is changed to start_d. For more details, see the description of tk_swri_dev.

Additional Notes

If the corresponding device driver does not have the TDA_DEV_D attribute, the error code E_PAR is returned when specifying a value that is out of the range of W for the start position start_d.

Thus, the appropriate conversion of parameters is executed by T-Kernel/SM. The application does not have to know whether the device driver has the TDA_DEV_D attribute or not, or whether the device driver supports 64 bits or not.

Difference from T-Kernel 1.0

This extended SVC was added in T-Kernel 2.0.

tk_wai_dev - Wait for Request Completion for Device

C Language Interface

#include <tk/tkernel.h>

ID creqid = tk_wai_dev (ID dd , ID reqid , W *asize , ER *ioer , TMO tmout );

Parameter

ID dd Device DescriptorDevice descriptor
ID reqid Request IDRequest ID
W* asize Actually Read/Written SizePointer to the area to return the read/written size
ER* ioer I/O ErrorPointer to the area to return I/O error
TMO tmout TimeoutTimeout (ms)

Return Parameter

ID creqid Completed Request IDCompleted request ID
orError CodeError code
W asize Actually Read/Written SizeActually read/written size
ER ioer I/O ErrorI/O error

Error Code

E_ID dd is invalid or not opened, or reqid is invalid or not a request for dd
E_OBJ Another task is already waiting for request reqid
E_NOEXS No requests are being processed (only when reqid = 0)
E_TMOUT Timeout (processing continues)
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Waits for completion of request reqid for device dd. If reqid = 0 is set, this function waits for completion of any pending request to dd. This function waits for completion only of requests currently processing when the function is called. A request issued after tk_wai_dev() was called is not waited for.

When multiple requests are being processed concurrently, the order of their completion is not necessarily the same as the order of request but is dependent on the device driver. Processing is, however, guaranteed to be performed in a sequence such that the result is consistent with the order of requesting. When processing a read operation from a disk, for example, the sequence might be changed as follows.

Block number request sequence

1 4 3 2 5

Block number processing sequence

1 2 3 4 5

Disk access can be made more efficient by changing the sequence as above with the aim of reducing seek time and spin wait time.

The timeout for waiting for completion is set in tmout. The TMO_POL or TMO_FEVR attribute can be specified for tmout. If a timeout error is returned (E_TMOUT), tk_wai_dev() must be called again to wait for completion since the request processing is still ongoing. When reqid > 0 and tmout = TMO_FEVR are both set, the processing must be completed without timing out.

If the device driver returns a processing result error (such as I/O error) for the requested processing, the error code is stored in ioer instead of the return code. Specifically, the error code, which is stored in error of the request packet T_DEVREQ by the wait-for-completion function (waitfn) called for processing tk_wai_dev, is returned to ioer as the processing result error.

On the other hand, the return code is used for errors when the wait request itself was not handled properly. When error is passed in the return code, ioer has no meaning. Note also that if an error is passed in the return code, tk_wai_dev() must be called again to wait for completion since the processing is still ongoing. For more details, see the Section called waitfn - Wait-for-completion function.

If a task exception is raised during completion waiting by tk_wai_dev(), the request in reqid is aborted and processing is completed. The result of aborting the requested processing is dependent on the device driver. When reqid = 0 was set, however, requests are not aborted but are treated as timeout. In this case E_ABORT rather than E_TMOUT is returned.

It is not possible for multiple tasks to wait for completion of the same request ID at the same time. If there is a task waiting for request completion with reqid = 0 set, another task cannot wait for completion for the same dd. Similarly, if there is a task waiting for request completion with reqid > 0 set, another task cannot wait for completion specifying reqid = 0.

This extended SVC can be used for a device driver that has the TDA_TMO_U attribute. In that case, the parameters are converted appropriately by T-Kernel/SM. For example, when a device driver has the TDA_TMO_U attribute, the timeout interval (milliseconds) specified in tmout of this extended SVC is converted to the time in microseconds, and then passed to the device driver with the TDA_TMO_U attribute.

Difference from T-Kernel 1.0

The data type of asize was changed from INT* to W*.

tk_wai_dev_u - Wait Device (in microseconds)

C Language Interface

#include <tk/tkernel.h>

ID creqid = tk_wai_dev_u (ID dd , ID reqid , W *asize , ER *ioer , TMO_U tmout_u );

Parameter

ID dd Device DescriptorDevice descriptor
ID reqid Request IDRequest ID
W* asize Actually Read/Written SizePointer to the area to return the read/written size
ER* ioer I/O ErrorPointer to the area to return I/O error
TMO_U tmout_u TimeoutTimeout (in microseconds)

Return Parameter

ID creqid Completed Request IDCompleted request ID
orError CodeError code
W asize Actually Read/Written SizeActually read/written size
ER ioer I/O ErrorI/O error

Error Code

E_ID dd is invalid or not opened, or reqid is invalid or not a request for dd
E_OBJ Another task is already waiting for request reqid
E_NOEXS No requests are being processed (only when reqid = 0)
E_TMOUT Timeout (processing continues)
E_ABORT Processing aborted
OtherError code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

This extended SVC takes the parameter tmout_u (64-bit microseconds), instead of the parameter tmout of tk_wai_dev.

Its specification is the same as that of tk_wai_dev, except that the parameter changed to tmout_u. For more details, see the description of tk_wai_dev.

Additional Notes

If the corresponding device driver does not have the TDA_TMO_U attribute (does not supports microseconds), it cannot handle the timeout in microseconds. In that case, the timeout (in microseconds) specified by this extended SVC in tmout_u is rounded to the time in milliseconds and passed to the device driver.

Thus, the appropriate conversion of parameters is executed by T-Kernel/SM. The application does not have to know whether the device driver has the TDA_TMO_U attribute or not, or whether the device driver supports microseconds or not.

Difference from T-Kernel 1.0

This extended SVC was added in T-Kernel 2.0.

Note that an extended SVC of device management function tk_wai_dev_u is appended with the suffix '_u', not '_d'.

tk_sus_dev - Suspends Device

C Language Interface

#include <tk/tkernel.h>

INT dissus = tk_sus_dev (UINT mode );

Parameter

UINT mode ModeMode

Return Parameter

INT dissus Suspend Disable Request CountSuspend disable request count
orError CodeError code

Error Code

E_BUSY Suspend already disabled
E_QOVR Suspend disable request count limit exceeded

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Performs the processing specified in mode, then passes the resulting suspend disable request count in the return code.

mode := ( (TD_SUSPEND | [TD_FORCE]) || TD_DISSUS || TD_ENASUS || TD_CHECK)
#define TD_SUSPEND      0x0001      /* suspend */
#define TD_DISSUS       0x0002      /* disable suspension */
#define TD_ENASUS       0x0003      /* enable suspension */
#define TD_CHECK        0x0004      /* get suspend disable request count */
#define TD_FORCE        0x8000      /* forced suspend specification */

TD_SUSPEND

Suspend

If suspending is enabled, suspends processing.

If suspending is disabled, returns E_BUSY.

TD_SUSPEND|TD_FORCE

Forcibly suspend

Suspends even in suspend disabled state.

TD_DISSUS

Disable suspension

Disables suspension.

TD_ENASUS

Enable suspension

Enables suspension.

If the enable request count is above the disable count for the resource group, no operation is performed.

TD_CHECK

Get suspend disable count

Gets only the number of times suspend disable has been requested.

Suspension is performed in the following steps.

  1. Processing prior to start of suspension in each subsystem

    tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0)

  2. Suspension processing in non-disk devices

  3. Suspension processing in disk devices

  4. Processing after completion of suspension in each subsystem

    tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0)

  5. Suspended state

    tk_set_pow(TPW_DOSUSPEND)

Resumption from SUSPEND state is performed in the following steps.

  1. Return from SUSPEND state

    Return from tk_set_pow(TPW_DOSUSPEND)

  2. Processing prior to start of resumption in each subsystem

    tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0)

  3. Resumption processing in disk devices

  4. Resumption processing in non-disk devices

  5. Processing after completion of resumption in each subsystem

    tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0)

In the above processing, whether the device is a disk device or not is determined by checking whether the device attribute is the disk type (TDK_DISK) or not.

The number of suspend disable requests is counted. Suspension is enabled only if the same number of suspend enable requests is made. At system boot, the suspend disable count is 0 and suspension is enabled. There is only one suspend disable request count kept per system, but the system keeps track of the resource group making the request. It is not possible to clear suspend disable requests made in another resource group. When the cleanup function runs in a resource group, all the suspend requests made in that group are cleared and the suspend disable request count is reduced accordingly. The maximum suspend disable request count is implementation-dependent, but must be at least 255. When the upper limit is exceeded, E_QOVR is returned.

tk_get_dev - Get Device Name

C Language Interface

#include <tk/tkernel.h>

ID pdevid = tk_get_dev (ID devid , UB *devnm );

Parameter

ID devid Device IDDevice ID
UB* devnm Device NamePointer to the device name storage location

Return Parameter

ID pdevid Device ID of Physical DeviceDevice ID of the physical device
orError CodeError code
UB devnm Device NameDevice name

Error Code

E_NOEXS The device specified in devid does not exist

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Gets the device name of the device specified in devid and puts the result in devnm.

devid is the device ID of either a physical device or a logical device.

If devid is a physical device, the physical device name is put in devnm.

If devid is a logical device, the logical device name is put in devnm.

devnm requires a space of L_DEVNM + 1 bytes or larger.

The device ID of the physical device to which device devid belongs is passed in the return code.

tk_ref_dev - Get Device Information

C Language Interface

#include <tk/tkernel.h>

ID devid = tk_ref_dev (CONST UB *devnm , T_RDEV *rdev );

Parameter

CONST UB* devnm Device NameDevice name
T_RDEV* rdev Packet to Return Device InformationPointer to the area to return the device information

Return Parameter

ID devid Device IDDevice ID
orError CodeError code

rdev Detail:

ATR devatr Device AttributeDevice attributes
INT blksz Block Size of Device-specific DataBlock size of device-specific data (-1: unknown)
INT nsub Subunit CountNumber of subunits
INT subno Subunit Number0: Physical device, 1 to nsub: Subunit number+1
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_NOEXS The device specified in devnm does not exist

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Gets device information about the device specified in devnm, and puts the result in rdev. If rdev = NULL is set, the device information is not stored.

nsub indicates the number of physical device subunits belonging to the device specified in devnm.

The device ID of the device specified in devnm is passed in the return code.

tk_oref_dev - Get Device Information

C Language Interface

#include <tk/tkernel.h>

ID devid = tk_oref_dev (ID dd , T_RDEV *rdev );

Parameter

ID dd Device DescriptorDevice descriptor
T_RDEV* rdev Packet to Return Device InformationPointer to the area to return the device information

Return Parameter

ID devid Device IDDevice ID
orError CodeError code

rdev Detail:

ATR devatr Device AttributeDevice attributes
INT blksz Block Size of Device-specific DataBlock size of device-specific data (-1: unknown)
INT nsub Subunit CountNumber of subunits
INT subno Subunit Number0: Physical device, 1 to nsub: Subunit number+1
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_ID dd is invalid or not open

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Gets device information about the device specified in dd, and puts the result in rdev. If rdev = NULL is set, the device information is not stored.

nsub indicates the number of physical device subunits belonging to the device specified in dd.

The device ID of the device specified in dd is passed in the return code.

tk_lst_dev - Get Registered Device Information

C Language Interface

#include <tk/tkernel.h>

INT remcnt = tk_lst_dev (T_LDEV *ldev , INT start , INT ndev );

Parameter

T_LDEV* ldev List of DevicesLocation of registered device information (array)
INT start Starting NumberStarting number
INT ndev Number of DevicesNumber to acquire

Return Parameter

INT remcnt Remaining Device CountNumber of remaining registrations
orError CodeError code

ldev Detail:

ATR devatr Device AttributeDevice attributes
INT blksz Block Size of Device-specific DataBlock size of device-specific data (-1: unknown)
INT nsub Subunit CountNumber of subunits
UB devnm[L_DEVNM] Physical Device NamePhysical device name
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_NOEXS start exceeds the registered number

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Gets information about registered devices. Registered devices are managed per physical device. The registered device information is therefore also obtained per physical device.

When the number of registered devices is N, number are assigned serially to devices from 0 to N - 1. Starting from the number specified in start in accordance with this scheme, the number of registrations specified in ndev is acquired and put in ldev. The space specified in ldev must be large enough to hold ndev registration information. The number of remaining registrations after start (N-start) is passed in the return code.

If the number of registrations from start is fewer than ndev, all remaining registrations are stored. A value passed in return code less than or equal to ndev means all remaining registrations were obtained. Note that this numbering changes as devices are registered and deleted. For this reason, accurate information may not be always obtained if the acquisition is carried out over multiple operations.

tk_evt_dev - Send Driver Request Event to Device

C Language Interface

#include <tk/tkernel.h>

INT retcode = tk_evt_dev (ID devid , INT evttyp , void *evtinf );

Parameter

ID devid Device IDEvent destination device ID
INT evttyp Event TypeDriver request event type
void* evtinf Event InformationInformation for each event type

Return Parameter

INT retcode Return Code from eventfn Return code passed by eventfn
orError CodeError code

Error Code

E_NOEXS The device specified in devid does not exist
E_PAR Internal device manager events (evttyp < 0) cannot be specified
Other Error code returned by device driver

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Sends a driver request event to the device (device driver) specified in devid.

The functioning of driver request events and the contents of evtinf are defined for each event type. For details on driver request event, see the Section called eventfn - Event function.

Registration of Device Driver

Registration Method of Device Driver

Device driver registration is performed for each physical device.

tk_def_dev - Register Device

C Language Interface

#include <tk/tkernel.h>

ID devid = tk_def_dev (CONST UB *devnm , CONST T_DDEV *ddev , T_IDEV *idev );

Parameter

CONST UB* devnm Physical Device NamePhysical device name
CONST T_DDEV* ddev Define DeviceDevice registration information
T_IDEV* idev Initial Device InformationDevice initial information

Return Parameter

ID devid Device IDDevice ID
orError CodeError code

idev Detail:

ID evtmbfid Event Notification Message Buffer IDEvent notification message buffer ID
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_LIMIT Number of registrations exceeds the system limit
E_NOEXS The device specified in devnm does not exist (when ddev = NULL)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Registers a device (device driver) with the device name set in devnm, and passes the device ID of the registered device in the return code. If a device with device name devnm is already registered, the registration is updated with new information, in which case the device ID does not change.

ddev specifies the device registration information. When ddev = NULL is specified, device devnm registration is deleted.

ddev is a structure in the following format:

typedef struct t_ddev {
        void    *exinf;   /* extended information */
        ATR     drvatr;   /* driver attributes */
        ATR     devatr;   /* device attributes */
        INT     nsub;     /* number of subunits */
        INT     blksz;    /* block size of device-specific data (-1: unknown) */
        FP      openfn;   /* open function */
        FP      closefn;  /* close function */
        FP      execfn;   /* execute function */
        FP      waitfn;   /* wait-for-completion function */
        FP      abortfn;  /* abort function */
        FP      eventfn;  /* event function */
        /* Implementation-dependent information may be added beyond this point.*/
} T_DDEV;

exinf is used to store any desired information. The value is passed to the processing functions. Device management pays no attention to the contents.

drvatr sets device driver attribute information. The lower bits indicate system attributes, and the high bits are used for implementation-dependent attributes. The implementation-dependent attribute portion is used, for example, to define validity flags when implementation-dependent data is added to T_DDEV.

drvatr := [TDA_OPENREQ] | [TDA_TMO_U] | [TDA_DEV_D]
#define TDA_OPENREQ     0x0001  /* open/close each time */
#define TDA_TMO_U       0x0002  /* timeout in microseconds is used */
#define TDA_DEV_D       0x0004  /* 64 bit device */

drvatr can be specified by combining the following driver attributes.

TDA_OPENREQ

When a device is opened multiple times, normally openfn is called only the first time it is opened and closefn the last time it is closed. If TDA_OPENREQ is specified, then openfn/closefn will be called for all open/close operations even in case of multiple openings.

TDA_TMO_U

Indicates that timeout in microseconds is used.

In this case, the timeout tmout of driver processing functions is specified in the TMO_U format (microseconds).

TDA_DEV_D

Indicates that a 64-bit device is used. In this case, the type of the request packet devreq of driver processing functions is T_DEVREQ_D.

If TDA_TMO_U or TDA_DEV_D is specified, type of some parameters of driver processing functions is changed. If a combination of multiple driver attributes that change the type of parameters is specified in a driver processing function, the type of all specified parameters of that function is changed.

Device attributes are specified in devatr. The details of device attribute setting are as noted above.

The number of subunits is set in nsub. If there are no subunits, 0 is specified.

blksz sets the block size of device-specific data in bytes. In the case of a disk device, this is the physical block size. It is set to 1 byte for a serial port, etc. For a device with no device-specific data, it is set to 0. For an unformatted disk or other device whose block size is unknown, -1 is set. If blksz ≦ 0, device-specific data cannot be accessed. When device-specific data is accessed by tk_rea_dev or tk_wri_dev, size * blksz must be the size of the area being accessed, that is, the size of buf.

openfn, closefn, execfn, waitfn, abortfn, and eventfn set the entry address of driver processing functions. For more details on driver processing functions, see the Section called Device Driver Interface.

The device initialization information is returned in idev. This includes information set by default when the device driver is started, and can be used as necessary. When idev = NULL is set, device initialization information is not stored.

evtmbfid specifies the system default message buffer ID for event notification. If there is no system default event notification message buffer, 0 is set.

Notification like the following is made to each subsystem when a device is registered or deleted. devid is the device ID of the registered or deleted physical device.

Device registration or update:

tk_evt_ssy(0, TSEVT_DEVICE_REGIST, 0, devid)

Device deletion:

tk_evt_ssy(0, TSEVT_DEVICE_DELETE, 0, devid)

Difference from T-Kernel 1.0

TDA_TMO_U and TDA_DEV_D are added as attributes of drvatr to support 64-bit devices.

tk_ref_idv - Reference Device Initialization Information

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_ref_idv (T_IDEV *idev );

Parameter

T_IDEV* idev Packet to Return Initial Device InformationPointer to the area to return the device initialization information

Return Parameter

ER ercd Error CodeError code

idev Detail:

ID evtmbfid Event Notification Message Buffer IDEvent notification message buffer ID
(Other implementation-dependent parameters may be added beyond this point.)

Error Code

E_MACV Memory access privilege error

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Description

Gets device initialization information. The contents are the same as the information obtained by tk_def_dev().

Additional Notes

The error code E_MACV is common to many system calls, and usually not included in the error code list of each system call. However, for this extended SVC, E_MACV is included in this error code list because it is the only typical error.

Device Driver Interface

The device driver interface consists of processing functions (driver processing functions) specified when registering a device.

Open function

ER openfn(ID devid, UINT omode, void *exinf);

Close function

ER closefn(ID devid, UINT option, void *exinf);

Execute function

ER execfn(T_DEVREQ *devreq, TMO tmout, void *exinf);

Wait-for-completion function

INT waitfn(T_DEVREQ *devreq, INT nreq, TMO tmout, void *exinf);

Abort function

ER abortfn(ID tskid, T_DEVREQ *devreq, INT nreq, void *exinf);

Event function

INT eventfn(INT evttyp, void *evtinf, void *exinf);

If TDA_TMO_U is specified for a driver attribute, the timeout specification tmout for the following driver processing functions is set to TMO_U type (in microseconds).

Execute function

ER execfn(T_DEVREQ *devreq, TMO_U tmout_u, void *exinf);

Wait-for-completion function

INT waitfn(T_DEVREQ *devreq, INT nreq, TMO_U tmout_u, void *exinf);

If TDA_DEV_D is specified for a driver attribute, the type of request packet devreq for the following driver processing functions is set to T_DEVREQ_D.

Execute function

ER execfn(T_DEVREQ_D *devreq_d, TMO tmout, void *exinf);

Wait-for-completion function

INT waitfn(T_DEVREQ_D *devreq_d, INT nreq, TMO tmout, void *exinf);

Abort function

ER abortfn(ID tskid, T_DEVREQ_D *devreq_d, INT nreq, void *exinf);

If TDA_TMO_U and TDA_DEV_D are specified set a driver attribute, a driver processing function is set to the one that has parameters with all the specified types of changes were applied.

Execute function

ER execfn(T_DEVREQ_D *devreq_d, TMO_U tmout_u, void *exinf);

Wait-for-completion function

INT waitfn(T_DEVREQ_D *devreq_d, INT nreq, TMO_U tmout_u, void *exinf);

Driver processing functions are called by device management and run as a quasi-task portion. These driver processing functions must be reentrant. Calling of these driver processing functions in a mutually exclusive manner is not guaranteed. If, for example, there are simultaneous requests from multiple devices for the same device, different tasks might call the same driver processing function at the same time. The device driver must perform mutual exclusion control in such cases as necessary.

I/O requests to a device driver are made by means of the following request packet associated with a request ID.

/*
 * Device request packet: For 32-bit
 * In:  Input parameter to driver processing function (set in T-Kernel/SM device management)
 * Out: Output parameter from driver processing function (set in driver processing function)
 */
typedef struct t_devreq {
        struct t_devreq *next;    /* In: Link to request packet (NULL: termination) */
        void    *exinf;           /* X: Extended information */
        ID      devid;            /* In: Target device ID */
        INT     cmd:4;            /* In: Request command */
        BOOL    abort:1;          /* In: TRUE if abort request */
        BOOL    nolock:1;         /* In: TRUE if lock (making resident) not needed */
        INT     rsv:26;           /* In: Reserved (always 0) */
        T_TSKSPC tskspc;          /* In: Task space of requesting task */
        W       start;            /* In: Starting data number */
        W       size;             /* In: Request size */
        void    *buf;             /* In: IO buffer address */
        W       asize;            /* Out: Size of result */
        ER      error;            /* Out: Error result */
        /* Implementation-dependent information may be added beyond this point.*/
} T_DEVREQ;
/*
 * Device request packet: For 64-bit
 * In:  Input parameter to driver processing function (set in T-Kernel/SM device management)
 * Out: Output parameter from driver processing function (set in driver processing function)
 */
typedef struct t_devreq_d {
        struct t_devreq_d *next;  /* In: Link to request packet (NULL: termination) */
        void    *exinf;           /* X: Extended information */
        ID      devid;            /* In: Target device ID */
        INT     cmd:4;            /* In: Request command */
        BOOL    abort:1;          /* In: TRUE if abort request */
        BOOL    nolock:1;         /* In: TRUE if lock (making resident) not needed */
        INT     rsv:26;           /* In: Reserved (always 0) */
        T_TSKSPC tskspc;          /* In: Task space of requesting task */
        D       start_d;          /* In: Starting data number, 64-bit */
        W       size;             /* In: Request size */
        void    *buf;             /* In: IO buffer address */
        W       asize;            /* Out: Size of result */
        ER      error;            /* Out: Error result */
        /* Implementation-dependent information may be added beyond this point.*/
} T_DEVREQ_D;

In: Input parameter to the driver processing function is set in T-Kernel/SM device management. Should not be changed on the device driver side. Parameters other than input parameters (In) are initially cleared to 0 by the device management. After that, device management does not modify them.Out: Output parameter returned from the driver processing function is set in the driver processing function.

next is used to link the request packet. In addition to usage for keeping track of request packets in device management, it is used also by the completion wait function (waitfn) and abort function (abortfn).

exinf can be used freely by the device driver. Device management does not pay attention to the 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 (abortfn). abort is a flag indicating whether abort processing was requested, and does not indicate that processing was aborted. In some cases abort is set to TRUE even when the abort function (abortfn) is not called. Abort processing is performed when a request with abort set to TRUE is actually passed to the device driver.

nolock indicates that the memory space specified in buf has already been locked (made resident) and does not need to be locked by the device driver. In this case the device driver must not lock the memory space. (nolock is specified when there is a possibility of incorrect operation if the device driver performs a lock. Accordingly, when nolock = TRUE, the device driver must not lock the space.)

tskspc is set as the task space for a task (API issuing task) that issued API for device I/O operation. Since the processing function is executed in a context of a quasi-task portion in which the API issuing task is a requesting task, tskspc is same as the task space for the processing function. If, however, the actual I/O processing (read/write in the space specified in buf) is performed by a separate task in the device driver, it is necessary to switch the task space of the task performing the actual I/O processing to the task space of the task issuing API.

start, start_d, and size are just set as start, start_d, and size specified in tk_rea_dev(),

tk_rea_dev_du(), tk_wri_dev(), and tk_wri_dev_du().

buf is just set as buf specified in tk_rea_dev(), tk_rea_dev_du(), tk_wri_dev(), and tk_wri_dev_du(). The memory space specified in buf may be nonresident in some cases or task space in others. Care must therefore be taken regarding the following points.

  • Nonresident memory cannot be accessed from a task-independent portion or while dispatching or interrupts are disabled.

  • Task space memory cannot be accessed from another task.

For these reasons, switching of task space or making memory space resident must be performed as necessary. Special attention is needed when access is made by an interrupt handler. Generally it is best not to access buf directly from an interrupt handler. Before accessing the buf memory space, the validity of buf must be checked using an address space check function(ChkSpace... are described above).

The device driver sets in asize the value returned in asize by tk_wai_dev().

The device driver sets in error the error code passed by tk_wai_dev() in its return code. E_OK indicates a normal result.

Difference between T_DEVREQ and T_DEVREQ_D is only the part of their names being start or start_d, and the data type.

The type of device request packet (T_DEVREQ or T_DEVREQ_D) is selected based on the driver attribute (TDA_DEV_D) at device registration. For this reason, T_DEVREQ and T_DEVRE do not co-exist in the request packet for one driver.

NoteDifference from T-Kernel 1.0
 

The data type of start, size, and asize for T_DEVREQ was changed from INT to W. Device request packet for T_DEVREQ_D is added to support 64-bit devices.

openfn - Open function

C Language Interface

ER ercd = openfn (ID devid , UINT omode , void *exinf );

Parameter

ID devid Device IDDevice ID of the device to open
UINT omode Open ModeOpen mode (same as tk_opn_dev)
void* exinf Extended InformationExtended information set at device registration

Return Parameter

ER ercd Error CodeError code

Error Code

Other Error code returned by the device driver

Description

The open function openfn is called when tk_opn_dev() is invoked.

The function openfn performs processing to enable 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 simply 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 can be performed so long as there is no problem in device driver operation.

When openfn is used to perform device initialization or the like, in principle no processing should be performed that causes a wait. 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. There is no need for openfn to initialize the device.

When the same device is opened multiple times, normally this function is called only for 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.

The openfn function does not need to perform any processing with regard to multiple opening or open mode, which are handled by device management. Likewise, omode is simply passed as reference information; no processing relating to omode is required.

openfn runs as a quasi-task portion of the task that issued tk_opn_dev. That is, it is executed in the context of the quasi-task portion whose requesting task is the task that issued tk_opn_dev.

closefn - Close function

C Language Interface

ER ercd = closefn (ID devid , UINT option , void *exinf );

Parameter

ID devid Device IDDevice ID of the device to close
UINT option Close OptionClose option (same as tk_cls_dev)
void* exinf Extended InformationExtended information set at device registration

Return Parameter

ER ercd Error CodeError code

Error Code

Other Error code returned by the device driver

Description

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. The processing and return from closefn must be as prompt as possible. If media ejection takes time, it is permissible to return 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 for the last time.

The closefn function does not need to perform any processing with regard to multiple opening or open mode, which are handled by device management.

closefn runs as a quasi-task portion of the task that issued tk_cls_dev. When the device is closed by cleanup processing, this function is executed in the context of the cleanup function, that is, it runs as a quasi-task portion of the task that issued tk_cln_ssy.

execfn - Execute function

C Language Interface

/* Execute function (32-bit request packet, millisecond timeout) */

ER ercd = execfn (T_DEVREQ *devreq , TMO tmout , void *exinf );

/* execute function (64-bit request packet, millisecond timeout) */

ER ercd = execfn (T_DEVREQ_D *devreq_d , TMO tmout , void *exinf );

/* execute function (32-bit request packet, microsecond timeout) */

ER ercd = execfn (T_DEVREQ *devreq , TMO_U tmout_u , void *exinf );

/* execute function (64-bit request packet, microsecond timeout) */

ER ercd = execfn (T_DEVREQ_D *devreq_d , TMO_U tmout_u , void *exinf );

Parameter

T_DEVREQ* devreq Device Request PacketRequest packet (32-bit)
T_DEVREQ_D* devreq_d Device Request PacketRequest packet (64-bit)
TMO tmout TimeoutRequest acceptance timeout (ms)
TMO_U tmout_u TimeoutRequest acceptance timeout (in microseconds)
void* exinf Extended InformationExtended information set at device registration

Return Parameter

ER ercd Error CodeError code

Error Code

Other Error code returned by the device driver

Description

The execute function execfn is called when tk_rea_dev() or tk_wri_dev() is invoked.

Initiates the processing requested in devreq. This function initiates the requested processing only, returning to its caller without waiting for the processing to complete. The time required to initiate processing depends on the device driver; this function does not necessarily complete immediately.

When new processing cannot be accepted, this function goes to WAITING state for request acceptance. If the new request cannot be accepted within the time specified in tmout, the function times out. The TMO_POL or TMO_FEVR attribute can be specified in tmout. If the function times out, E_TMOUT is passed in the execfn return code. The request packet error parameter does not change. Timeout applies to the request acceptance, 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. In this case, the request packet is discarded. If the abort occurs 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 abort occurs, 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.

execfn runs as a quasi-task portion of the task that issued tk_rea_dev, tk_wri_dev, tk_srea_dev, or tk_swri_dev.

In a device driver for which TDA_DEV_D is specified as an attribute at the time of registering the device, the execute function (64-bit request packet, millisecond timeout) execfn is called when tk_rea_dev() or tk_wri_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout execfn, except that the parameter request packet is a 64-bit T_DEVREQ_D* devreq_d.

In a device driver for which TDA_TMO_U is specified as an attribute at the time of registering the device, the execute function (32-bit request packet, microsecond timeout) execfn is called when tk_rea_dev() or tk_wri_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout execfn, except that the parameter timeout specification is a microsecond TMO_U tmout_u.

In a device driver for which both TDA_DEV_D and TDA_TMO_U are specified as an attribute at the time of registering the device, the execute function (64-bit request packet, microsecond timeout) execfn is called when tk_rea_dev() or tk_wri_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout execfn, except that the parameter request packet is a 64-bit T_DEVREQ_D* devreq_d and the parameter timeout specification is a microsecond TMO_U tmout_u.

Difference from T-Kernel 1.0

The execute function (64-bit request packet, millisecond timeout), execute function (32-bit request packet, microsecond timeout), and execute function (64-bit request packet, microsecond timeout) were added in T-Kernel 2.0.

waitfn - Wait-for-completion function

C Language Interface

/* wait-for-completion function (32-bit request packet, millisecond timeout) */

INT creqno = waitfn (T_DEVREQ *devreq , INT nreq , TMO tmout , void *exinf );

/* wait-for-completion function (64-bit request packet, millisecond timeout) */

INT creqno = waitfn (T_DEVREQ_D *devreq_d , INT nreq , TMO tmout , void *exinf );

/* wait-for-completion function (32-bit request packet, microsecond timeout) */

INT creqno = waitfn (T_DEVREQ *devreq , INT nreq , TMO_U tmout_u , void *exinf );

/* wait-for-completion function (64-bit request packet, microsecond timeout) */

INT creqno = waitfn (T_DEVREQ_D *devreq_d , INT nreq , TMO_U tmout_u , void *exinf );

Parameter

T_DEVREQ* devreq Device Request PacketRequest packet list (32-bit)
T_DEVREQ_D* devreq_d Device Request PacketRequest packet list (64-bit)
INT nreq Number of RequestRequest packet count
TMO tmout TimeoutTimeout (ms)
TMO_U tmout_u TimeoutTimeout (in microseconds)
void* exinf Extended InformationExtended information set at device registration

Return Parameter

INT creqno Completed Request Packet NumberCompleted request packet number
orError CodeError code

Error Code

Other Error code returned by the device driver

Description

The wait-for-completion function waitfn is called when tk_wai_dev() is invoked.

devreq is a list of request packets in a chain linked by devreq->next. This function waits for completion of any of the nreq request packets starting from devreq. The final next is not necessarily NULL, so the nreq must always be followed. The number of the completed request packet (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 timeout for waiting for completion is set in tmout. The TMO_POL or TMO_FEVR attribute can be specified for tmout. If the wait times out, the requested processing continues. The waitfn return code in case of timeout is E_TMOUT. The request packet error parameter 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 not be completed 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 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.

I/O error and other device-related errors are stored in the request packet error parameter. 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.

The abort processing when the abort function abortfn was executed during completion waiting by waitfn differs depending on whether to wait for completion of a single request (waitfn, nreq = 1) or multiple requests (waitfn, nreq > 1). When waiting for completion of a single request, the request currently processing is aborted. On the other hand, when waiting for completion of multiple requests, as a special handling, only the completion waiting by waitfn is released and the processing for the request itself is not aborted. It means that, even if the abort function abortfn is executed, the request packets' abort remains FALSE and the processing for the requests continues. E_ABORT is passed in the return code from the released waitfn.

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 than E_ABORT may be returned as appropriate based on the device properties. It is also permissible to return E_OK on the basis that the processing right up to the abort is valid. If processing completes normally to the end, E_OK is returned even if there was an abort request.

waitfn runs as a quasi-task portion of the task that issued tk_wai_dev, tk_srea_dev, or tk_swri_dev.

In a device driver for which TDA_DEV_D is specified as an attribute at the time of registering the device, the wait-for-completion function (64-bit request packet, millisecond timeout) waitfn is called when tk_wai_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout waitfn, except that the parameter request packet is a 64-bit T_DEVREQ_D* devreq_d.

In a device driver for which TDA_TMO_U is specified as an attribute at the time of registering the device, the wait-for-completion function (32-bit request packet, microsecond timeout) waitfn is called when tk_wai_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout waitfn, except that the parameter timeout specification is a microsecond TMO_U tmout_u.

In a device driver for which TDA_DEV_D and TDA_TMO_U are specified as an attribute at the time of registering the device, the wait-for-completion function (64-bit request packet, microsecond timeout) waitfn is called when tk_wai_dev() is invoked. In this case, the function specification is the same as that of 32-bit request packet, millisecond timeout waitfn, except that the parameter request packet is a 64-bit T_DEVREQ_D* devreq_d and the parameter timeout specification is a microsecond TMO_U tmout_u.

Difference from T-Kernel 1.0

The wait-for-completion function (64-bit request packet, millisecond timeout), wait-for-completion function (32-bit request packet, microsecond timeout), and wait-for-completion function (64-bit request packet, microsecond timeout) were added in T-Kernel 2.0.

abortfn - Abort function

C Language Interface

/* abort function (32-bit request packet) */

ER ercd = abortfn (ID tskid , T_DEVREQ *devreq , INT nreq , void *exinf );

/* abort function (64-bit request packet) */

ER ercd = abortfn (ID tskid , T_DEVREQ_D *devreq_d , INT nreq , void *exinf );

Parameter

ID tskid Task ID Task ID of the task executing execfn or waitfn
T_DEVREQ* devreq Device Request PacketRequest packet list (32-bit)
T_DEVREQ_D* devreq_d Device Request PacketRequest packet list (64-bit)
INT nreq Number of Request PacketsRequest packet count
void* exinf Extended InformationExtended information set at device registration

Return Parameter

ER ercd Error CodeError code

Error Code

Other Error code returned by the device driver

Description

The abort function abortfn is called when you want to promptly return from the currently running execute function execfn or wait-for-completion function waitfn. 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.

abortfn is called in the following cases.

  • When a break function is executing after a task exception and the task that raised the exception requests abort processing, abortfn is used to abort the request being processed by that task.

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

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.

abortfn 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 abortfn 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 abortfn is called, the abort flag in the request packet whose processing is to be aborted is set to TRUE, enabling execfn or waitfn to know whether there is going to be an abort request. Note also that abortfn can use tk_dis_wai() for any object.

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 (waited is released), 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 abortfn but by setting the request packet abort flag. 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 if abortfn 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 later. Even though processing was aborted, the request itself is not discarded until its completion has been checked by waitfn.

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

The abortfn that is executed on a task exception runs as a quasi-task portion of the task issuing tk_ras_tex that raised the task exception. The abortfn that is executed on a device close runs as a quasi-task portion of the task that issued tk_cls_dev. When the device is closed by cleanup processing, this function is executed in the context of the cleanup function, that is, it runs as a quasi-task portion of the task that issued tk_cln_ssy.

In a device driver for which TDA_DEV_D is specified as an attribute at the time of registering the device, the abort function (64-bit request packet) abortfn is called when you want to promptly return from the currently running execute function execfn or wait-for-completion function waitfn. In this case, the function specification is the same as that of 32-bit request packet abortfn, except that the parameter request packet is a 64-bit T_DEVREQ_D* devreq_d.

Difference from T-Kernel 1.0

The abort function (64-bit request packet) was added in T-Kernel 2.0.

eventfn - Event function

C Language Interface

INT retcode = eventfn (INT evttyp , void *evtinf , void *exinf );

Parameter

INT evttyp Event TypeDriver request event type
void* evtinf Event InformationInformation for each event type
void* exinf Extended InformationExtended information set at device registration

Return Parameter

INT retcode Return CodeReturn code defined for each event type
orError CodeError code

Error Code

Other Error code returned by the device driver

Description

When a state change occurs in the device or system which is caused by a factor other than normal device I/O processing by an application interface, requiring some processing by the device driver, a driver request event is raised and then the event function eventfn is called.

The driver request event is raised when suspending or resuming a device for power control (see tk_sus_dev) or when connecting a removable device such as USB or PC card.

For example, when the system is suspended by tk_sus_dev, the driver request event for the suspend (TDV_SUSPEND) is raised in the T-Kernel (during the tk_sus_dev processing) and the event function for each device is called with evttyp = TDV_SUSPEND. The event function called for each device performs necessary operations for suspend such as saving the state.

The following driver request events are defined.

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

The driver request events with a negative value are called internally from the device management in the T-Kernel/SM, for suspend or resume processing.

On the other hand, the driver request events with a positive value (TDV_CARDEVT and TDV_USBEVT) are reference specifications which are not directly related to the T-Kernel operation, and raised by calling tk_evt_dev(). These driver request events are used as needed to implement a bus driver for USB, PC card, or other device.

The processing performed by the event function is defined for each event type. For suspend and resume processings, see the Section called Device Suspend/Resume Processing.

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

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

The eventfn runs as a quasi-task portion of the task that issued tk_evt_dev or tk_sus_dev that caused the event.

Additional Notes

The following behaviors are assumed for PC card event or USB event.

Note that they describe implementation examples of device drivers that handle a device such as PC card or USB and are not part of the T-Kernel specification.

When a USB device is connected, a class driver should dynamically be mapped to the USB device to perform an actual I/O processing.

For example, when a storage such as USB memory is connected, a device driver for the mass storage class handles the I/O for the device, or when a USB camera is connected, a device driver for the video class handles the I/O for the device. Which device driver should be used cannot be determined until the USB device is connected.

In this case, the driver request event for the USB connection and the event function for each device driver are used in order to map a class driver to the USB device. Specifically, when the USB bus driver (USB manager) monitoring the USB ports detects a newly connected USB device, it sends the driver request event for the USB connection (TDV_USBEVT) to each device driver which will be candidate of the class driver and then calls the event function for each device.

The event function for each device returns whether or not it can support the newly connected USB device in response to this TDV_USBEVT. The USB bus driver receives the return codes and determines the mapping to the actual class driver.

The similar steps are used also for connecting PC card.

Device Event Notification

A device driver sends events that occur on each device to the specific message buffer (event notification message buffer) as device event notification messages. The event notification message buffer ID is referenced or set as an attribute data of TDN_EVENT for each device.

The system default event notification message buffer is used immediately after device registration. As a device is registered by tk_def_dev when a device driver is started, the system default event notification message buffer ID value is returned as this API's return parameter, the value is held in the device driver and is used as the initial value of this attribute data, TDN_EVENT.

The system default event notification message buffer is created at system startup. Its size and maximum message length are defined by TDEvtMbfSz in the system configuration information.

The message formats used in device event notification are as follows: The content and size of the event notification message vary depending on the event type.

◇Basic format of device event notification
typedef struct t_devevt {
        TDEvtTyp        evttyp;         /* event type */
        /* Information specific to each event type is appended here. */
} T_DEVEVT;

◇Format of device event notification with device ID
typedef struct t_devevt_id {
        TDEvtTyp        evttyp;         /* event type */
        ID              devid;          /* Device ID */
        /* Information specific to each event type is appended here. */
} T_DEVEVT_ID;

◇Format of device event notification with extended information
typedef struct t_devevt_ex {
        TDEvtTyp        evttyp;         /* event type */
        ID              devid;          /* Device ID */
        UB              exdat[16];      /* Extended information */
        /* Information specific to each event type is appended here. */
} T_DEVEVT_EX;

The event type of a device event notification is classified as follows:

  1. Basic event notification (event type: 0x0001 to 0x002F)

    Basic event notification from a device

  2. System event notification (event type: 0x0030 to 0x007F)

    Event notification related to entire system such as power supply control

  3. Event notification with extended information (event type: 0x0080 to 0x00FF)

    Event notification from a device with extended information

  4. User-defined event notification (event type: 0x0100 to 0xFFFF)

    Notification of event that users can arbitrarily define

Typical event types are as follows: For more details on each event and other event types, see the specification related to device drivers or the Section called Event Type of the Device Event Notification in the Chapter called Appendix in the Section called Specification Related to Device Drivers to be Used as Reference in the Chapter called Appendix.

typedef enum tdevttyp {
        TDE_unknown     = 0,            /* undefined */
        TDE_MOUNT       = 0x01,         /* media insert */
        TDE_EJECT       = 0x02,         /* Eject media */
        TDE_POWEROFF    = 0x31,         /* power switch off */
        TDE_POWERLOW    = 0x32,         /* low power alarm */
        TDE_POWERFAIL   = 0x33,         /* abnormal power */
        TDE_POWERSUS    = 0x34          /* auto suspend */
} TDEvtTyp;

Measures must be taken so that if event notification cannot be sent because the message buffer is full, the lack of notification will not adversely affect operation on the receiving end. One option is to hold the notification until space becomes available in the message buffer, but in that case other device driver processing should not, as a rule, be allowed to fall behind as a result. Processing on the receiving end should be designed to avoid message buffer overflow as much as possible.

NoteDifference from T-Kernel 1.0
 

The description has been re-organized for message formats and event types used in the device event notification.

Device Suspend/Resume Processing

Device drivers perform suspend and resume operations in response to the issuing of suspend/resume (TDV_SUSPEND/TDV_RESUME) events to the event handling function (eventfn). Suspend and resume events are issued only to physical devices.

TDV_SUSPEND

Suspend

evttyp = TDV_SUSPEND
evtinf = NULL (none)

Suspend processing takes place as follows.

  1. If there is a request being processed at the time, the device driver waits for it to complete, pauses it or aborts it. Which of these options to take depends on the device driver implementation. Since the suspension must be effected as quickly as possible, however, pause or abort should be chosen if completion of the request will take time.

    Suspend events can be issued only for physical devices, but the same processing is applied to all logical devices included in the physical device.

    Pause: Processing is suspended, then continues after the device resumes operation.
    Abort: Processing is aborted just as when the abort function (abortfn) is executed, and is not continued after the device resumes operation.

  2. New requests other than a resume event are not accepted.

  3. The device power is cut off and other suspend operation is performed.

Abort should be avoided if possible because of its effects on applications. It should be used only in such cases as long input wait from a serial port, or when pause would be difficult. Normally it is best to wait for completion of a request or, if possible, choose pause (suspend and resume).

Requests arriving at the device driver in suspend state are made to wait until operation resumes, after which they are accepted for processing. If the request does not involve access to the device, however, or otherwise can be processed even during suspension, a request may be accepted without waiting for resumption.

TDV_RESUME

Resume

evttyp = TDV_RESUME
evtinf = NULL (none)

Resume processing takes place as follows.

  1. The device power is turned back on, the device states are restored and other device resume processing is performed.

  2. Paused processing is resumed.

  3. Accepting request is resumed.

Special Properties of Disk Devices

A disk device has a special role to play in a virtual memory system. When implementing a virtual memory system, in order to perform data transfer between memory and a disk, OS (specifically, a part to process a virtual memory in a T-Kernel Extension, etc.) needs to call a disk driver.

The need for the OS to perform data transfer with a disk arises when access is made to nonresident memory and the memory contents must be read from a disk (page in). The OS calls the disk driver in this case.

If nonresident memory is accessed in the disk driver, the OS must likewise call the disk driver. In such a case, when the disk driver is waiting for a page to be read in due to the access to nonresident memory, it is possible that the OS will again request disk access to that disk driver. Even then, the disk driver must be able to execute the later OS request.

A similar case may arise in suspend processing. When access is made to nonresident memory during suspend processing and a disk driver is called, if that disk driver is already suspended, page-in will not be possible. To avoid such a situation, suspend processing should suspend other devices before disk devices. If there are multiple disk devices, however, the order of their suspension is indeterminate. For this reason, during suspend processing a disk driver must not access nonresident memory.

Because of the above limitations, a disk driver shall not use (access) nonresident memory. It is possible, however, that the I/O buffer (buf) space specified with tk_rea_dev() or tk_wri_dev() can be nonresident memory since this is a memory location specified by the caller. In the case of I/O buffers, therefore, it is necessary to make the memory space resident (see LockSpace) at the time of I/O access.