1ioctl(9E) Driver Entry Points ioctl(9E)
2
3
4
6 ioctl - control a character device
7
9 #include <sys/cred.h>
10 #include <sys/file.h>
11 #include <sys/types.h>
12 #include <sys/errno.h>
13 #include <sys/ddi.h>
14 #include <sys/sunddi.h>
15
16
17
18 int prefixioctl(dev_t dev, int cmd, intptr_t arg, int mode,
19 cred_t *cred_p, int *rval_p);
20
21
23 Architecture independent level 1 (DDI/DKI). This entry point is
24 optional.
25
27 dev Device number.
28
29
30 cmd Command argument the driver ioctl() routine interprets as
31 the operation to be performed.
32
33
34 arg Passes parameters between a user program and the driver.
35 When used with terminals, the argument is the address of a
36 user program structure containing driver or hardware set‐
37 tings. Alternatively, the argument may be a value that has
38 meaning only to the driver. The interpretation of the argu‐
39 ment is driver dependent and usually depends on the command
40 type; the kernel does not interpret the argument.
41
42
43 mode A bit field that contains:
44
45 o Information set when the device was opened. The
46 driver may use it to determine if the device was
47 opened for reading or writing. The driver can make
48 this determination by checking the FREAD or
49 FWRITE flags. See the flag argument description of
50 the open() routine for further values.
51
52 o Information on whether the caller is a 32-bit or
53 64-bit thread.
54
55 o In some circumstances address space information
56 about the arg argument. See below.
57
58
59 cred_p Pointer to the user credential structure.
60
61
62 rval_p Pointer to return value for calling process. The driver may
63 elect to set the value which is valid only if the ioctl()
64 succeeds.
65
66
68 ioctl() provides character-access drivers with an alternate entry point
69 that can be used for almost any operation other than a simple transfer
70 of characters in and out of buffers. Most often, ioctl() is used to
71 control device hardware parameters and establish the protocol used by
72 the driver in processing data.
73
74
75 The kernel determines that this is a character device, and looks up the
76 entry point routines in cb_ops(9S). The kernel then packages the user
77 request and arguments as integers and passes them to the driver's
78 ioctl() routine. The kernel itself does no processing of the passed
79 command, so it is up to the user program and the driver to agree on
80 what the arguments mean.
81
82
83 I/O control commands are used to implement the terminal settings passed
84 from ttymon(1M) and stty(1), to format disk devices, to implement a
85 trace driver for debugging, and to clean up character queues. Since the
86 kernel does not interpret the command type that defines the operation,
87 a driver is free to define its own commands.
88
89
90 Drivers that use an ioctl() routine typically have a command to
91 ``read'' the current ioctl() settings, and at least one other that
92 sets new settings. Drivers can use the mode argument to determine if
93 the device unit was opened for reading or writing, if necessary, by
94 checking the FREAD or FWRITE setting.
95
96
97 If the third argument, arg, is a pointer to a user buffer, the driver
98 can call the copyin(9F) and copyout(9F) functions to transfer data
99 between kernel and user space.
100
101
102 Other kernel subsystems may need to call into the drivers ioctl() rou‐
103 tine. Drivers that intend to allow their ioctl() routine to be used in
104 this way should publish the ddi-kernel-ioctl property on the associated
105 devinfo node(s).
106
107
108 When the ddi-kernel-ioctl property is present, the mode argument is
109 used to pass address space information about arg through to the driver.
110 If the driver expects arg to contain a buffer address, and the FKIOCTL
111 flag is set in mode, then the driver should assume that it is being
112 handed a kernel buffer address. Otherwise, arg may be the address of a
113 buffer from a user program. The driver can use ddi_copyin(9F) and
114 ddi_copyout(9F) perform the correct type of copy operation for either
115 kernel or user address spaces. See the example on ddi_copyout(9F).
116
117
118 Drivers have to interact with 32-bit and 64-bit applications. If a
119 device driver shares data structures with the application (for example,
120 through exported kernel memory) and the driver gets recompiled for a
121 64-bit kernel but the application remains 32-bit, binary layout of any
122 data structures will be incompatible if they contain longs or pointers.
123 The driver needs to know whether there is a model mismatch between the
124 current thread and the kernel and take necessary action. The mode argu‐
125 ment has additional bits set to determine the C Language Type Model
126 which the current thread expects. mode has FILP32 set if the current
127 thread expects 32-bit ( ILP32) semantics, or FLP64 if the current
128 thread expects 64-bit ( LP64) semantics. mode is used in combination
129 with ddi_model_convert_from(9F) and the FMODELS mask to determine
130 whether there is a data model mismatch between the current thread and
131 the device driver (see the example below). The device driver might have
132 to adjust the shape of data structures before exporting them to a user
133 thread which supports a different data model.
134
135
136 To implement I/O control commands for a driver the following two steps
137 are required:
138
139 1. Define the I/O control command names and the associated
140 value in the driver's header and comment the commands.
141
142 2. Code the ioctl() routine in the driver that defines the
143 functionality for each I/O control command name that is in
144 the header.
145
146
147 The ioctl() routine is coded with instructions on the proper action to
148 take for each command. It is commonly a switch statement, with each
149 case definition corresponding to an ioctl() name to identify the
150 action that should be taken. However, the command passed to the driver
151 by the user process is an integer value associated with the command
152 name in the header.
153
155 ioctl() should return 0 on success, or the appropriate error number.
156 The driver may also set the value returned to the calling process
157 through rval_p.
158
160 Example 1 ioctl() entry point
161
162
163 The following is an example of the ioctl() entry point and how to sup‐
164 port 32-bit and 64-bit applications with the same device driver.
165
166
167 struct passargs32 {
168 int len;
169 caddr32_t addr;
170 };
171
172 struct passargs {
173 int len;
174 caddr_t addr;
175 };
176
177 xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
178 cred_t *credp, int *rvalp) {
179 struct passargs pa;
180
181 #ifdef _MULTI_DATAMODEL
182 switch (ddi_model_convert_from(mode & FMODELS)) {
183 case DDI_MODEL_ILP32:
184 {
185 struct passargs32 pa32;
186
187 ddi_copyin(arg, &pa32, sizeof (struct passargs32),\
188 mode);
189 pa.len = pa32.len;
190 pa.address = pa32.address;
191 break;
192 }
193 case DDI_MODEL_NONE:
194 ddi_copyin(arg, &pa, sizeof (struct passargs),\
195 mode);
196 break;
197 }
198 #else /* _MULTI_DATAMODEL */
199 ddi_copyin(arg, &pa, sizeof (struct passargs), mode);
200 #endif /* _MULTI_DATAMODEL */
201
202 do_ioctl(&pa);
203 ....
204 }
205
206
208 stty(1), ttymon(1M), dkio(7I), fbio(7I), termio(7I), open(9E), put(9E),
209 srv(9E), copyin(9F), copyout(9F), ddi_copyin(9F), ddi_copyout(9F),
210 ddi_model_convert_from(9F), cb_ops(9S)
211
212
213 Writing Device Drivers
214
216 Non-STREAMS driver ioctl() routines must make sure that user data is
217 copied into or out of the kernel address space explicitly using
218 copyin(9F), copyout(9F), ddi_copyin(9F), or ddi_copyout(9F), as appro‐
219 priate.
220
221
222 It is a severe error to simply dereference pointers to the user address
223 space, even when in user context.
224
225
226 Failure to use the appropriate copying routines can result in panics
227 under load on some platforms, and reproducible panics on others.
228
230 STREAMS drivers do not have ioctl() routines. The stream head converts
231 I/O control commands to M_IOCTL messages, which are handled by the
232 driver's put(9E) or srv(9E) routine.
233
234
235
236SunOS 5.11 3 Dec 1996 ioctl(9E)