|
|
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 */ };
ic_cmd
ic_timout
ic_len
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.
ic_dp
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.
``MDI ioctls'' in HDK Technical Reference