Subject: kern/5934: ioctl.9 - a try to describe how to add new ioctls
To: None <gnats-bugs@gnats.netbsd.org>
From: Heiko W.Rupp <hwr@pilhuhn.de>
List: netbsd-bugs
Date: 08/08/1998 18:28:15
>Number:         5934
>Category:       kern
>Synopsis:       ioctl.9 - a try to describe how to add new ioctls
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Aug  8 09:35:01 1998
>Last-Modified:
>Originator:     Heiko W.Rupp
>Organization:
>Release:        NetBSD-1.3.2
>Environment:
System: NetBSD quaak 1.3.2 NetBSD 1.3.2 (QUAAK-TEST) #28: Sat Aug 8 16:46:38 MEST 1998 hwr@quaak:/u/u2/src/sys/arch/i386/compile/QUAAK-TEST i386


>Description:

.Dd August 8, 1998
.Dt IOCTL 9
.Os NetBSD
.Sh NAME
.Nm ioctl
.Nd how to implement a new ioctl call to access device drivers
.Sh SYNOPSIS
.Fd #include <sys/ioctl.h>
.Fd #include <sys/ioccom.h>
.Ft int
.Fn ioctl (int, unsigned long, ...)
.Sh DESCRIPTION
.Nm Ioctl
are internally as 
.Bl -tag -witdh define
.It #define FOOIOCTL   fun(t,n,pt)
.El
where the different wariables and funcions are:
.Bl -tag -width FOOIOCTL
.It Fn FOOIOCTL 
the name as the ioctl is later known in a as second argument to a 
.Xr ioctl
system call. E.g. ioctl(s,FOOIOCTL,...)
.It Fn fun
a macro which can be one of
.Bl -tag -withh _IOWR
.It _IOR 
the call only reads parameters from the kernel and does not
pass any to it
.It _IOW
the call only writes parameters to the kernel, but does not want anything 
back
.It _IOWR
the call writes data to the kernel and wants information back.
.El
.It t
This integer describes to which subsystem the ioctl applies.
T
can be one of 
.Bl -tag -with 'a'
.It 'd' the disk subsystem
.It 'f' files
.It 'i' a (pseudo) interface
.It 'r' the routing subsystem
.It 's' the socket layer
.It 't' the tty layer
.It 'u' user defined ???
.El
.It n
This numbers the ioctl within the group. There may be only one 
.Fn n
for a given
.Fn t .
This is a unsigned 8 byte number.
.It pt
This specifyies the type of the passed parameter. This one gets internally
transformed to the sizeof the parameter, so if you e.g. want to pass
a structure, then you have to spezify that structure and not a pointer
to it or sizeof(struct foo)
.El

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>.
.Sh EXAMPLE

   #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 accessd like

   driver_ioctl(..,cmd,data) 
                u_long cmd;
                caddr_t data;

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

.Sh NOTES
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.
.Sh SEE ALSO
.Xr ioctl 2
>How-To-Repeat:
>Fix:
>Audit-Trail:
>Unformatted: