'\"macro stdmacro
.if n .pH ddi_dki.ioctl @(#)ioctl	40.7 of 11/16/89
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} ioctl D2DK "" "DDI/DKI" "\&"
.if \nX=1 .ds x} ioctl D2DK "" "DDI/DKI"
.if \nX=2 .ds x} ioctl D2DK "" "\&"
.if \nX=3 .ds x} ioctl "" "" "\&"
.TH \*(x}
.IX "\f4ioctl\fP(D2DK)"
.SH "NAME"
\f4ioctl\f1 \- control a character device
.SH "SYNOPSIS"
.nf
.na
\f4#include <sys/cred.h>
#include <sys/types.h>
#include <sys/errno.h>
.sp 0.5
int \f2prefix\f4ioctl(\f4dev_t\f1 \f2dev\f1, \f4int\f1 \f2cmd\f1, \f4int\f1 \f2arg\f1, \f4int\f1 \f2mode\f1, \f4cred_t *\f1\f2cred_p,
	\f4int *\f1\f2rval_p\f4);\f1
.ad
.fi
.SH "ARGUMENTS"
.RS 0n
.IP \f2dev\f1 10n
Device number.
.IP \f2cmd\f1 10n
Command argument the driver \f4ioctl\f1 routine interprets as the 
operation to be performed.  It should be defined, along with an integer
value that is actually passed, in the header file.
.IP
The I/O control command name and value can be defined
in the driver code itself,
but this is not recommended.
If I/O control commands are defined in a header file,
the user program and the driver can both access the same definitions
to ensure that they agree about what each I/O control command value represents.
.IP
The I/O control command name is traditionally
an all uppercase alphabetic string.
This alphabetic name can be a mnemonic.
You should try to keep the values for your I/O control commands
distinct from others on the system.
Each driver's I/O control commands are discrete,
but it is possible for
user-level code to access a driver
with an I/O control command that is intended for another driver,
which can lead to serious consequences,
such as if it meant to pass
``drop carrier on a communication line,''
but instead sends the argument to a disk
where it is interpreted as ``reformat drive.''
Permissions can be set to prevent most such events,
but the more unique your I/O control command values are,
the safer you are.
.IP
A number of different schemes are legal for
assigning values to I/O control command names.
The most straightforward is to use decimal numbers;
for example
.P
.RS 14
.nf
\f4#define COMMAND1	01
#define COMMAND2	02\f1
.fi
.RE
.IP "" 10n
Similarly, one can assign hexadecimal numbers
as values
.P
.RS 14
.nf
\f4#define COMMANDA	0x0a
#define COMMANDFF	0xff\f1
.fi
.RE
.IP "" 10n
The drawback to these methods is
that one quickly gets an operating system that contains
several instances of each I/O control command value,
with the inherent risks discussed above.
.IP
A common method to assign I/O control command values that
are less apt to be duplicated is to use a left-shifted 8 scheme.
For instance
.P
.RS 14
.nf
\f4#define COMMAND10	('Q'<<8|10)
#define COMMAND11	('Q'<<8|11)
#define COMMAND12	('Q'<<8|12)\f1
.fi
.RE
.IP "" 10n
\f1Alternately, the shift-left-8 scheme can be defined as a constant
then used for the I/O control command definitions.
For example
.P
.RS 14
.nf
\f4#define ROTA		('q'<<8)
#define COMMAND23	(ROTA|234)
#define COMMAND25	(ROTA|254)
.fi
.RE
.IP "" 10n
An alternative coding style
is to use enumerations for the command argument,
which allows the compiler to do additional type checking.
.P
.RS 14
.nf
\f4typedef enum   {
	XX_COMMAND10 = 'Q'<<8 | 10,
	XX_COMMAND11 = 'Q'<<8 | 11,
	XX_COMMAND12 = 'Q'<<8 | 12,
} xx_cmds_t; ;\f1
.fi
.RE
.IP "" 10n
\f4termio\f1(7) specifies the command types that must work
for AT&T terminal drivers.
Terminal drivers typically have a command to read the
current \f4ioctl\f1 settings and at least
one other that defines new settings.
.IP \f2arg\f1 10n
Passes parameters between a user program and the
driver.  
.IP
When used with terminals, the argument is the address of a
user program structure containing driver or hardware settings. 
Alternatively, the argument may be an integer that has
meaning only to the driver.
The interpretation of the argument is driver
dependent and usually depends on the command type; the kernel does not
interpret the argument.
.IP \f2mode\f1 10n
Contains values set when the device was opened.
.IP
Use of this mode is optional.  However, the driver may use it to determine
if the device was opened for reading or writing.
The driver makes this determination by checking the \f4FREAD\f1 or
\f4FWRITE\f1 setting (values are in \f4file.h\f1).  
.IP
See the
\f2flag\f1 argument description of the \f4open\f1 routine for further
values for the \f4ioctl\f1 routine's \f2mode\f1 argument.
.IP "\f2*cred_p\f1" 10n
Pointer to the \f4cred\f1(D4DK) user credential structure.
.IP \f2*rval_p\f1 10n
Pointer to return value for calling process.  The driver may elect to set the
value which is valid only if the \f4ioctl\f1(D2DK) succeeds.
.RE
.SH "DESCRIPTION"
The \f4ioctl\f1(D2DK) routine provides character-access drivers with
an alternate entry point that can be used
for almost any operation other than
a simple transfer of characters in and out of buffers.
Most often, \f4ioctl\f1 is used
to control device hardware parameters
and establish the protocol used by the driver
in processing data.
.P
The kernel looks up the device's file table entry,
determines that this is a character device,
and looks up the entry point routines in \f4cdevsw\f1.
The kernel then packages the user request
and arguments as integers and passes them to
the driver's \f4ioctl\f1 routine.
The kernel itself does no processing of the passed command,
so it is up to the user program and the driver
to agree on what the arguments mean.
.P
I/O control commands are used to implement the terminal settings
passed from \f4ttymon\f1(1M) and \f4stty\f1(1),
to format disk devices,
to implement a trace driver for debugging,
and to clean up character queues.
Since the kernel does not interpret
the command type that defines the operation,
a driver is free to define its own commands.
.P
Drivers that use an \f4ioctl\f1 routine
typically have a command to ``read'' the current \f4ioctl\f1
settings, and at least one other that sets new settings.
You can use the mode argument to determine
if the device unit was opened for reading or writing,
if necessary, by checking the \f4FREAD\f1 or \f4FWRITE\f1 setting.
.P
If the third argument, \f2arg\f1, is a pointer to user space, the driver
should call the \f4copyin\f1(D3DK) and \f4copyout\f1(D3DK) functions
to transfer data between kernel and user space.
.P
To implement I/O control commands for a driver the following
two steps are required:
.RS 2n
.TP 4n
1.
Define the I/O control command names and the associated value
in the driver's header file and comment the commands.
.TP
2.
Code the \f4ioctl\f1 routine in the driver
that defines the functionality for
each I/O control command name that is in the header file.
.RE
.P
The \f4ioctl\f1 routine is coded with instructions
on the proper action to take for each command.
It is basically a \f4switch\f1 statement,
with each \f4case\f1 definition corresponding to an \f4ioctl\f1 name
to identify the action that should be taken.
However, the command passed to the driver by the user process
is an integer value associated with
the command name in the header file.
.P
It is critical that command definitions
and routines be clearly commented.
Because there is so much flexibility
in how commands are used,
uncommented commands can be very difficult to interpret at a later time.
.P
Terminal drivers use and support the \f4ioctl\f1 commands
defined on the \f4termio\f1(7) manual page.
For instance, \f4TCGETA\f1 gets
the parameters associated with the terminal
and stores them in the structure referenced
in the third argument of the routine call.
\f4TCSETA\f1 sets the parameters associated with the terminal
from the structure referenced in the third argument.
.P
\f3NOTE:\f1
STREAMS drivers do not have \f4ioctl\f1 routines.
The stream head converts I/O control commands to \f4M_IOCTL\f1
messages, which are handled by the driver's \f4put\f1(D2DK) or
\f4srv\f1(D2DK) routine.
.SH "RETURN VALUE"
The \f4ioctl\f1 routine should return \f40\f1 for success,
or the appropriate error number.  Refer to Appendix A for a
list of DDI/DKI error numbers.
The driver may also set the value returned to the calling process through
the \f2rval_p\f1 pointer.
.SH "SEE ALSO"
.na
\f4copyin\f1(D3DK),
\f4copyout\f1(D3DK)
.if n .pH ddi_dki.mmap @(#)mmap	40.2 of 8/22/89
.ad
