SVR5 and SCO OpenServer 5


M_IOCTL -- statisfy STREAMS ioctl system calls


Generated by the Stream head in response to an I_STR, I_LINK, I_UNLINK, I_PLINK, and I_PUNLINK ioctl STREAMS system calls documented on the streamio manual page and in response to ioctl calls that contain a command argument value not defined in streamio. When one of these ioctls is received from a user process, the Stream head uses values from the process (supplied in the call) to create an M_IOCTL message containing them, and sends the message downstream. M_IOCTL messages are intended to perform the general ioctl functions of character device drivers.

For an I_STR ioctl, the user values are supplied in a structure of the following form, provided as an argument to the ioctl call (see I_STR in streamio):

   struct strioctl
   int ic_cmd;	/* downstream request */
   int ic_timout;	/* ACK/NAK timeout    */
   int ic_len;	/* length of data arg */
   char *ic_dp;	/* ptr to data arg    */

request (or command) defined by a downstream module or driver

time the Stream head will wait for acknowledgment to the M_IOCTL message before timing out.

On input, contains the length of the data argument passed in; on return from the call, it contains the length of the data, if any, being returned to the user. The maximum size of ic_len is determined by the value of the STRMSGSZ tunable parameter. By default, this is 16384 but it can be set to higher values. If you must increase the size of this parameter to accomodate the needs of your device, the driver's installation scripts should increment the value on the target system rather than hard-coding the new value in case another installed package has also incremented it. The driver's uninstall scripts should then decrement this value.

pointer to an optional data argument.

The form of an M_IOCTL message consists of one M_IOCTL message block linked to zero or more M_DATA message blocks. STREAMS constructs an M_IOCTL message block by placing an iocblk(D4str) structure in its data buffer.

ioc_id is an identifier generated internally; it is used to match each M_IOCTL message sent downstream with a response which must be sent upstream to the Stream head. The response is contained in an M_IOCACK(D7str) (positive acknowledgment) or an M_IOCNAK(D7str) (negative acknowledgment) message. Both of these message types have the same format as an M_IOCTL message and contain an iocblk structure in the first block with optional data blocks following.

For an I_STR ioctl, when a user supplies data to be sent downstream, The Stream head copies the data, pointed to by ic_dp in the strioctl structure, into M_DATA(D7str) message blocks and linkes the blocks to the initial M_IOCTL message block. ioc_count is copied from ic_len. If there is no data, ioc_count is zero.

STREAMS does not explicitly support all ioctl system call commands. Only the ioctls that are documented on the streamio manual page plus the ioctls for terminal control (TCSETA, TCSETS, and so forth) are processed by the STREAMS interface. Other ioctl commands are transmitted as transparent M_IOCTL messages. For example, the user-level program issues the following:

   ioctl(fd, cmd, arg);
In the kernel, this is translated to an M_IOCTL message (bp) that has ioc_cmd set as cmd, and ioc_count set to the constant TRANSPARENT, defined in the <sys/stream.h> header file. The ioc_count member thus distinguishes this case from a normal I_STR ioctl call with an ioc_cmd of the same value as cmd.

Following on in the continuation M_DATA(D7str) block of this M_IOCTL mesage is the value of the arg parameter as an int. In other words, the M_DATA block is sizeof(int) bytes. Any modules or drivers that see an M_IOCTL with cmd can then process this message. The driver/module can uses the M_COPYIN(D7str) and M_COPYOUT(D7str) messages with the copyreq structure to request that data be copied in from user space to the kernel, or out from the kernel to user space respectively. The stream head responds to these messages with an M_IOCDATA(D7str) message that contains the results in a copyresp structure.

For an M_COPYIN request, the M_COPYIN message specifies the data in user space to copy, and, if succesful, the returning M_IOCDATA message contains this data in the continuation (bp->b_cont) part of the message (which is of type M_DATA(D7str)).

For an M_COPYOUT request, the continuation (bp->b_cont) part should contain the data to copy out, and the request structure specifies the location in user space to which the data should be copied. The M_IOCDATA that the Streamhead returns simply shows if the copy request succeeded or not.

TRANSPARENT is used to support old non-STREAMS ioctl commands for drivers, especially drivers that used to be non-STREAMS based.

Note that the I_STR ioctl cannot set ic_len to TRANSPARENT; the ioctl call will return EINVAL. Transparaent ioctls are only generated when an unsupported ioctl cmd is applied to a STREAM. ic_len < 0 or ic_timeout < -1.

M_IOCACK and M_IOCNAK message types have the same format as an M_IOCTL message and contain an iocblk structure in the first block. An M_IOCACK block may be linked to following M_DATA blocks. If one of these messages reaches the Stream head with an identifier that does not match that of the currently outstanding M_IOCTL message, the response message is discarded. A common means of ensuring that the correct identifier is returned is for the replying module to convert the M_IOCTL message type into the appropriate response type and set ioc_count to 0 if no data is returned. Then the qreply(K_STR) function is used to send the response to the Stream head.

In an M_IOCACK or M_IOCNAK message, ioc_error holds any return error condition set by a downstream module. If this value is nonzero, it is returned to the user in errno. Note that both an M_IOCNAK and an M_IOCACK can return an error. ioc_rval holds any M_IOCACK return value set by a responding module.

For an I_STR ioctl, if a user supplies data to be sent downstream, the Stream head copies the data (pointed to by ic_dp in the strioctl structure) into M_DATA message blocks. It then links the blocks to the initial M_IOCTL message block. ioc_count is copied from ic_len. If there is no data, ioc_count is 0.

If a module processing an I_STR ioctl wants to send data to a user process as part of its response, it must use the M_IOCACK message that it constructs such that the M_IOCACK block is linked to one or more following M_DATA blocks containing the user data. The module must set ioc_count to the number of data bytes sent. The Stream head places the data in the address pointed to by ic_dp in the user I_STR strioctl structure.

The first module or driver that understands the request contained in the M_IOCTL acts on it and generally returns an M_IOCACK message. Intermediate modules that do not recognize a particular request must pass it on. If a driver does not recognize the request, or if the receiving module cannot acknowledge it, an M_IOCNAK message must be returned.

The Stream head waits for the response message and returns any information contained in an M_IOCACK to the user. The Stream head will time out if no response is received in ic_timeout interval.

If a module processing a transparent ioctl (that is, it received a transparent M_IOCTL) wants to send data to a user process, it can use only an M_COPYOUT message. For a transparent ioctl, no data can be sent to the user process in an M_IOCACK message. All data must have been sent in a preceding M_COPYOUT message. The Stream head will ignore any data contained in an M_IOCACK message (in M_DATA blocks) and will free the blocks.

No data can be sent with an M_IOCNAK message for any type of M_IOCTL. The Stream head will ignore and will free any M_DATA blocks.

The Stream head blocks the user process until an M_IOCACK or M_IOCNAK response to the M_IOCTL (same ioc_id) is received. For an M_IOCTL generated from an I_STR ioctl, the Stream head will time out if no response is received in ic_timeout intervall (the user may specify an explicit interval or specify use of the default interval). For M_IOCTL messages generated from all other ioctls, the default (infinite) is used.

Message type

Ordinary (non-priority).

Version applicability

ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp, 7.1, 7.1mp, 8, 8mp
oddi: 1, 2, 2mp, 3, 3mp, 4, 4mp, 5, 5mp

Differences between versions

This message type is identical in DDI and ODDI, but note the differences in the iocblk(D4str) structure between the two interfaces.



``MDI ioctls'' in HDK Technical Reference

19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005