ioctl - how to implement a new ioctl call to access device drivers
#include <sys/ioctl.h>
#include <sys/ioccom.h>
int
ioctl(int, unsigned long, ...);
ioctl are internally defined as
#define FOOIOCTL fun(t,n,pt)
where the different variables and functions are:
FOOIOCTL the name which will later be given in the ioctl(2) system call
as second argument, e.g.
ioctl(s, FOOIOCTL, ...).
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.
t This integer describes to which subsystem the ioctl applies. t
can be one of
'1' pulse-per-second interface
'4' i4b(4)
'a' ISO networking
'A' ac devices (hp300)
'A' Advanced Power Management (hpcmips, i386, sparc), see
apm(4)
'A' ADB devices (mac68k, macppc)
'A' audio(4)
'A' i4btel(4)
'b' tb(4)
'B' bell device (x68k)
'B' bpf(4)
'c' coda
'c' cd(4)
'c' ch(4)
'C' clock devices (amiga, atari, hp300, x68k)
'C' i4bctl(4)
'd' the disk subsystem
'E' envsys(4)
'f' files
'F' Sun-compatible framebuffers
'F' ccd(4) and vnd(4)
'g' qdss framebuffers
'G' grf devices (amiga, atari, hp300, mac68k, x68k)
'h' HIL devices (hp300)
'H' HIL devices (hp300)
'H' HPc framebuffers
'i' a (pseudo) interface
'I' ite(4) (mac68k)
'J' ISA joystick interface
'k' Sun-compatible (and other) keyboards
'K' lkm(4)
'l' leo devices (atari)
'm' mtio(4)
'M' mouse devices (atari)
'M' mlx(4)
'n' virtual console device (arm32)
'n' SMB networking
'O' OpenPROM and OpenFirmware
'p' power control (x68k)
'P' parallel port (amiga, x68k)
'P' profiling (arm32)
'P' printer/plotter interface (hp300)
'P' magma(4) bpp (sparc)
'q' altq(9)
'q' pmax graphics devices
'Q' altq(9)
'Q' raw SCSI commands
'r' the routing subsystem
'r' md(4)
'R' i4brbch(4)
'R' rnd(4)
's' the socket layer
's' satlink devices
'S' SCSI disks (arc, hp300, pmax)
'S' watchdog devices (sh3)
'S' ISA speaker devices
'S' stic devices
'S' scanners
't' the tty layer
'u' user defined ???
'U' scsibus (see scsi(4))
'v' Sun-compatible ``firm events''
'V' view device (amiga, atari)
'V' sram device (x68k)
'w' watchdog devices
'W' wt devices
'W' wscons devices
'x' bt8xx devices
'Z' ite devices (amiga, atari, x68k)
'Z' passthrough ioctls
n This numbers the ioctl within the group. There may be only one
n for a given t. This is a unsigned 8 bit number.
pt This specifies the type of the passed parameter. This one gets
internally transformed to the size of the parameter, so if you
e.g. want to pass a structure, then you have to specify that
structure and not a pointer to it or sizeof(struct foo)
In order for the new ioctl to be known to the system it is installed in
either <sys/ioctl.h> or one of the files that are reached from
<sys/ioctl.h>.
#define FOOIOCTL _IOWR('i', 23, int)
int a = 3;
error = ioctl(s, FOOICTL, a);
Within the ioctl()-routine of the driver, it can be then accessed like
driver_ioctl(..., u_long cmd, caddr_t data)
{
...
switch (cmd) {
case FOOIOCTL:
int *a = (int *)data;
printf(" Value passed: %d\n", *a);
break;
}
}
Note that if you e.g. try to read information from e.g. a ethernet driver
where the name of the card is included in the third argument (e.g.
ioctl(s, READFROMETH, struct ifreq *)), then you have to use the _IOWR()
form not the _IOR(), as passing the name of the card to the kernel
already consists of writing data.
All ioctl() routines should return either 0 or a defined error code. The
use of magic numbers such as -1, to indicate that a given ioctl code was
not handled is strongly discouraged. The value -1 coincides with the
historic value for ERESTART which was shown to produce user space code
that never returned from a call to ioctl(2).
For ioctl codes that are not handled by a given routine, the pseudo error
value EPASSTHROUGH is provided. EPASSTHROUGH indicates that no error
occurred during processing (it did not fail), but neither was anything
processed (it did not succeed). This supercedes the use of either ENOTTY
(which is an explicit failure) or -1 (which has no contextual meaning) as
a return value. ENOTTY will get passed directly back to user space and
bypass any further processing by other ioctl layers. Only code that
wishes to suppress possible further processing of an ioctl code (eg, the
tty line discipline code) should return ENOTTY. All other code should
return EPASSTHROUGH, even if it knows that no other layers will be called
upon.
If the value EPASSTHROUGH is returned to sys_ioctl(), then it will there
be changed to ENOTTY to be returned to user space, thereby providing the
proper error notification to the application.
ioctl(2)
BSD December 7, 2001 BSD
[ Back ] |