DragonFly On-Line Manual Pages
IOCTL(9) DragonFly Kernel Developer's Manual IOCTL(9)
NAME
ioctl, _IO, _IOR, _IOW, _IOWR -- how to implement a new ioctl call to
access device drivers
SYNOPSIS
#include <sys/ioccom.h>
_IO(g, t);
_IOR(g, n, t);
_IOW(g, n, t);
_IOWR(g, n, t);
DESCRIPTION
Whenever an ioctl(2) call is made, the kernel dispatches it to the device
driver which can then interpret the request number and data in a
specialized manner. Ioctls are defined as:
#define MYDEVIOCTL fun(g, n, t)
where the different symbols correspond to:
MYDEVIOCTL The name which will later be given in the ioctl(2) system
call as second argument, e.g.,
ioctl(fd, MYDEVIOCTL, ...)
fun() A macro which can be one of:
_IO() The call is a simple message to the kernel by
itself. It does not copy anything into the kernel,
nor does it want anything back.
_IOR() The call only reads parameters from the kernel and
does not pass any to it.
_IOW() The call only writes parameters to the kernel, but
does not want anything back.
_IOWR() The call writes data to the kernel and wants
information back.
We always consider reading or writing to the kernel, from the
user perspective.
g This integer describes to which subsystem the ioctl applies.
Here are some examples:
'8' aac(4)
'a' nata(4)
'B' bpf(4)
'C' cam(4)
'C' ciss(4)
'd' disklabel(5)
'd' diskslice
'd' drm(4)
'f' generic file-descriptor
'F' frame buffer
'h' HAMMER(5)
'i' iic(4)
'i' carp(4)
'i' gre(4)
'k' keyboard(4) and syscons(4)
'm' mem(4)
'm' /dev/midi
'm' mtio(4)
'M' sound(4) mixer
'n' smb(4)
'p' /dev/dsp and /dev/audio
'p' pci(4)
'p' ppbus(4)
'p' procfs(5)
'q' /dev/sequencer
'r' random number generator
't' tty(4)
't' tap(4)
't' tun(4)
't' SLIP ttys
'T' snp(4)
n This number uniquely identifies the ioctl within the group.
That said, two subsystems may share the same g, but there may
be only one n for a given g. This is an unsigned 8 bit
number.
t This specifies the type of the passed parameter. This one
gets internally transformed to the size of the parameter, so
for example, if you want to pass a structure, then you have
to specify that structure and not a pointer to it or
sizeof(struct MYDEV).
In order for the new ioctl to be visible to the system, it is installed
in either <sys/ioctl.h> or one of the files that are reached from
<sys/ioctl.h>.
RETURN VALUES
A distinction must be made at this point. All *_ioctl() routines from
within kernel should return either 0 for success or a defined error code,
as described in <sys/errno.h>. At the libc level though a conversion
takes place, so that eventually ioctl(2) returns either 0 for success or
-1 for failure, in which case the errno variable is set accordingly.
The use of magic numbers such as -1, to indicate that a given ioctl code
was not handled, is strongly discouraged. The value -1 is bound to the
ERESTART pseudo-error, which is returned inside kernel to modify return
to process.
EXAMPLES
Let's suppose that we want to pass an integer value to the kernel. From
the user point of view, this is like writing to the kernel. So we define
the ioctl as:
#define MYDEVIOCTL _IOW('i', 25, int)
Within the *_ioctl() routine of the driver, it can be then accessed like:
int
mydev_ioctl(struct dev_ioctl_args *ap)
{
int error;
int *a;
switch (ap->a_cmd) {
case MYDEVIOCTL:
a = (int *)ap->data;
kprintf("Value passed from userspace: %d\n", *a);
return (0); /* Success */
break;
/* Handle other ioctls here */
default:
/* Inappropriate ioctl for device */
error = ENOTTY;
break;
}
return (error);
}
In userspace:
int a = 101;
if (ioctl(fd, MYDEVIOCTL, &a) == -1) {
/* Handle failure */
}
SEE ALSO
ioctl(2)
DragonFly 5.3 October 4, 2018 DragonFly 5.3