Updated: 2022/Sep/29

Please read Privacy Policy. It's for your privacy.

IOCTL(9)                   Kernel Developer's Manual                  IOCTL(9)

     ioctl - how to implement a new ioctl call to access device drivers

     #include <sys/ioctl.h>
     #include <sys/ioccom.h>

     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

     t         This integer describes to which subsystem the ioctl applies.  t
               can be one of
               '1'    pulse-per-second interface
               'a'    ISO networking
               'A'    ac devices (hp300)
               'A'    Advanced Power Management (hpcmips, i386, sparc), see
               'A'    ADB devices (mac68k, macppc)
               'A'    audio(4)
               'b'    Bluetooth HCI sockets, see bluetooth(4)
               'b'    Bluetooth Hub Control, see bthub(4)
               'b'    Bluetooth SCO audio driver, see btsco(4)
               'B'    bell device (x68k)
               'B'    bpf(4)
               'c'    coda
               'c'    cd(4)
               'c'    ch(4)
               'C'    clock devices (amiga, atari, hp300, x68k)
               '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
               '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'    pci(4)
               'P'    compat/ossaudio and soundcard.h
               'P'    sparc/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'    rnd(4)
               's'    the socket layer
               '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 an 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 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

     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

     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 supersedes 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 (e.g.,
     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.

           #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, void *data)
                   switch (cmd) {

                   case FOOIOCTL:
                           int *a = (int *)data;
                           printf(" Value passed: %d\n", *a);

     Note that if you for example try to read information from an 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.


NetBSD 10.99                     July 7, 2022                     NetBSD 10.99