int io_devctl (resmgr_context_t * ctp , io_devctl_t * msg , RESMGR_OCB_T * ocb )
Classification: I/O
Default handler: iofunc_devctl_default()
Helper functions: iofunc_devctl(), iofunc_devctl_verify()
Client functions: devctl(), ioctl()
Messages: _IO_DEVCTL
Data structure:
struct _io_devctl { uint16_t type; uint16_t combine_len; int32_t dcmd; int32_t nbytes; int32_t zero; }; struct _io_devctl_reply { uint32_t zero; int32_t ret_val; int32_t nbytes; int32_t zero2; }; typedef union { struct _io_devctl i; struct _io_devctl_reply o; } io_devctl_t;
Description: Performs the device I/O operation as passed from the client's devctl() in dcmd. The client encodes a direction into the top two bits of dcmd, indicating how the devctl() is to transfer data (the "to" field refers to the _POSIX_DEVDIR_TO bit; the "from" field refers to the _POSIX_DEVDIR_FROM bit):
to field | from field | Meaning |
---|---|---|
0 | 0 | No data transfer |
0 | 1 | Transfer from driver to client |
1 | 0 | Transfer from client to driver |
1 | 1 | Transfer bidirectionally |
In the case of no data transfer, the driver is expected to simply perform the command given in dcmd. In the case of a data transfer, the driver is expected to transfer the data from and/or to the client, using the helper functions resmgr_msgreadv() and resmgr_msgwritev(). The client indicates the size of the transfer in the nbytes member; the driver is expected to set the outgoing structure's nbytes member to the number of bytes transferred.
Note that the input and output data structures are zero-padded so that they align with each other. This means that the implicit data area begins at the same address in the input and output structures.
If using the helper routine iofunc_devctl(), beware that it'll return the constant _RESMGR_DEFAULT in the case where it can't do anything with the devctl() message. This return value is there to decouple legitimate errno return values from an "unrecognized command" return value. Upon receiving a _RESMGR_DEFAULT, the base-layer library will respond with an errno of ENOSYS, which the client's devctl() library function will translate into ENOTTY (which is the "correct" POSIX value).
It's up to your function to check the open mode against the operation; no checking is done anywhere in either the client's devctl() library or in the resource manager library. For example, it's possible to open a resource manager "read-only" and then issue a devctl() to it telling it to "format the hard disk" (which is very much a "write" operation). It would be prudent to verify the open mode first before proceeding with the operation.
You can use the iofunc_devctl_verify() helper function to check the security and validity of the message. The default handler doesn't call this routine.
Note that the range of dcmd values you can use is limited (0x0000 through 0x0FFF inclusive is reserved for QSS). Other values may be in use; take a look through the include files that have the name <sys/dcmd_*.h>.
Returns: The status via the helper macro _RESMGR_STATUS and the reply buffer (with reply data, if required).
For an example, take a look at "A simple io_devctl() example," below.