sunos32_ioctl.c revision 1.26 1 /* $NetBSD: sunos32_ioctl.c,v 1.26 2007/12/20 23:03:04 dsl Exp $ */
2 /* from: NetBSD: sunos_ioctl.c,v 1.35 2001/02/03 22:20:02 mrg Exp */
3
4 /*
5 * Copyright (c) 2001 Matthew R. Green
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1993 Markus Wild.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. The name of the author may not be used to endorse or promote products
42 * derived from this software without specific prior written permission
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
56 */
57
58 #include <sys/cdefs.h>
59 __KERNEL_RCSID(0, "$NetBSD: sunos32_ioctl.c,v 1.26 2007/12/20 23:03:04 dsl Exp $");
60
61 #if defined(_KERNEL_OPT)
62 #include "opt_compat_netbsd32.h"
63 #include "opt_execfmt.h"
64 #endif
65
66 #include <sys/param.h>
67 #include <sys/proc.h>
68 #include <sys/systm.h>
69 #include <sys/file.h>
70 #include <sys/filedesc.h>
71 #include <sys/ioctl.h>
72 #include <sys/termios.h>
73 #include <sys/tty.h>
74 #include <sys/socket.h>
75 #include <sys/audioio.h>
76 #include <sys/vnode.h>
77 #include <sys/mount.h>
78 #include <sys/disklabel.h>
79 #include <sys/syscallargs.h>
80
81 #include <miscfs/specfs/specdev.h>
82
83 #include <net/if.h>
84
85 #include <dev/sun/disklabel.h>
86
87 #include <compat/sys/sockio.h>
88
89 #include <compat/sunos/sunos.h>
90 #include <compat/sunos/sunos_syscallargs.h>
91 #include <compat/netbsd32/netbsd32.h>
92 #include <compat/netbsd32/netbsd32_syscallargs.h>
93 #include <compat/sunos32/sunos32.h>
94 #include <compat/sunos32/sunos32_syscallargs.h>
95 #include <compat/common/compat_util.h>
96
97 /*
98 * SunOS ioctl calls.
99 * This file is something of a hodge-podge.
100 * Support gets added as things turn up....
101 */
102
103 static const struct speedtab sptab[] = {
104 { 0, 0 },
105 { 50, 1 },
106 { 75, 2 },
107 { 110, 3 },
108 { 134, 4 },
109 { 135, 4 },
110 { 150, 5 },
111 { 200, 6 },
112 { 300, 7 },
113 { 600, 8 },
114 { 1200, 9 },
115 { 1800, 10 },
116 { 2400, 11 },
117 { 4800, 12 },
118 { 9600, 13 },
119 { 19200, 14 },
120 { 38400, 15 },
121 { -1, -1 }
122 };
123
124 static const netbsd32_u_long s2btab[] = {
125 0,
126 50,
127 75,
128 110,
129 134,
130 150,
131 200,
132 300,
133 600,
134 1200,
135 1800,
136 2400,
137 4800,
138 9600,
139 19200,
140 38400,
141 };
142
143 static void stios2btios(struct sunos_termios *, struct termios *);
144 static void btios2stios(struct termios *, struct sunos_termios *);
145 static void stios2stio(struct sunos_termios *, struct sunos_termio *);
146 static void stio2stios(struct sunos_termio *, struct sunos_termios *);
147
148 /*
149 * These two conversion functions have mostly been done
150 * with some perl cut&paste, then hand-edited to comment
151 * out what doesn't exist under NetBSD.
152 * A note from Markus's code:
153 * (l & BITMASK1) / BITMASK1 * BITMASK2 is translated
154 * optimally by gcc m68k, much better than any ?: stuff.
155 * Code may vary with different architectures of course.
156 *
157 * I don't know what optimizer you used, but seeing divu's and
158 * bfextu's in the m68k assembly output did not encourage me...
159 * as well, gcc on the sparc definitely generates much better
160 * code with `?:'.
161 */
162
163 static void
164 stios2btios(struct sunos_termios *st, struct termios *bt)
165 {
166 netbsd32_u_long l, r;
167
168 l = st->c_iflag;
169 r = ((l & 0x00000001) ? IGNBRK : 0);
170 r |= ((l & 0x00000002) ? BRKINT : 0);
171 r |= ((l & 0x00000004) ? IGNPAR : 0);
172 r |= ((l & 0x00000008) ? PARMRK : 0);
173 r |= ((l & 0x00000010) ? INPCK : 0);
174 r |= ((l & 0x00000020) ? ISTRIP : 0);
175 r |= ((l & 0x00000040) ? INLCR : 0);
176 r |= ((l & 0x00000080) ? IGNCR : 0);
177 r |= ((l & 0x00000100) ? ICRNL : 0);
178 /* ((l & 0x00000200) ? IUCLC : 0) */
179 r |= ((l & 0x00000400) ? IXON : 0);
180 r |= ((l & 0x00000800) ? IXANY : 0);
181 r |= ((l & 0x00001000) ? IXOFF : 0);
182 r |= ((l & 0x00002000) ? IMAXBEL : 0);
183 bt->c_iflag = r;
184
185 l = st->c_oflag;
186 r = ((l & 0x00000001) ? OPOST : 0);
187 /* ((l & 0x00000002) ? OLCUC : 0) */
188 r |= ((l & 0x00000004) ? ONLCR : 0);
189 /* ((l & 0x00000008) ? OCRNL : 0) */
190 /* ((l & 0x00000010) ? ONOCR : 0) */
191 /* ((l & 0x00000020) ? ONLRET : 0) */
192 /* ((l & 0x00000040) ? OFILL : 0) */
193 /* ((l & 0x00000080) ? OFDEL : 0) */
194 /* ((l & 0x00000100) ? NLDLY : 0) */
195 /* ((l & 0x00000100) ? NL1 : 0) */
196 /* ((l & 0x00000600) ? CRDLY : 0) */
197 /* ((l & 0x00000200) ? CR1 : 0) */
198 /* ((l & 0x00000400) ? CR2 : 0) */
199 /* ((l & 0x00000600) ? CR3 : 0) */
200 /* ((l & 0x00001800) ? TABDLY : 0) */
201 /* ((l & 0x00000800) ? TAB1 : 0) */
202 /* ((l & 0x00001000) ? TAB2 : 0) */
203 r |= ((l & 0x00001800) ? OXTABS : 0);
204 /* ((l & 0x00002000) ? BSDLY : 0) */
205 /* ((l & 0x00002000) ? BS1 : 0) */
206 /* ((l & 0x00004000) ? VTDLY : 0) */
207 /* ((l & 0x00004000) ? VT1 : 0) */
208 /* ((l & 0x00008000) ? FFDLY : 0) */
209 /* ((l & 0x00008000) ? FF1 : 0) */
210 /* ((l & 0x00010000) ? PAGEOUT : 0) */
211 /* ((l & 0x00020000) ? WRAP : 0) */
212 bt->c_oflag = r;
213
214 l = st->c_cflag;
215 switch (l & 0x00000030) {
216 case 0:
217 r = CS5;
218 break;
219 case 0x00000010:
220 r = CS6;
221 break;
222 case 0x00000020:
223 r = CS7;
224 break;
225 case 0x00000030:
226 r = CS8;
227 break;
228 }
229 r |= ((l & 0x00000040) ? CSTOPB : 0);
230 r |= ((l & 0x00000080) ? CREAD : 0);
231 r |= ((l & 0x00000100) ? PARENB : 0);
232 r |= ((l & 0x00000200) ? PARODD : 0);
233 r |= ((l & 0x00000400) ? HUPCL : 0);
234 r |= ((l & 0x00000800) ? CLOCAL : 0);
235 /* ((l & 0x00001000) ? LOBLK : 0) */
236 r |= ((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
237 bt->c_cflag = r;
238
239 bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
240
241 l = st->c_lflag;
242 r = ((l & 0x00000001) ? ISIG : 0);
243 r |= ((l & 0x00000002) ? ICANON : 0);
244 /* ((l & 0x00000004) ? XCASE : 0) */
245 r |= ((l & 0x00000008) ? ECHO : 0);
246 r |= ((l & 0x00000010) ? ECHOE : 0);
247 r |= ((l & 0x00000020) ? ECHOK : 0);
248 r |= ((l & 0x00000040) ? ECHONL : 0);
249 r |= ((l & 0x00000080) ? NOFLSH : 0);
250 r |= ((l & 0x00000100) ? TOSTOP : 0);
251 r |= ((l & 0x00000200) ? ECHOCTL : 0);
252 r |= ((l & 0x00000400) ? ECHOPRT : 0);
253 r |= ((l & 0x00000800) ? ECHOKE : 0);
254 /* ((l & 0x00001000) ? DEFECHO : 0) */
255 r |= ((l & 0x00002000) ? FLUSHO : 0);
256 r |= ((l & 0x00004000) ? PENDIN : 0);
257 bt->c_lflag = r;
258
259 bt->c_cc[VINTR] = st->c_cc[0] ? st->c_cc[0] : _POSIX_VDISABLE;
260 bt->c_cc[VQUIT] = st->c_cc[1] ? st->c_cc[1] : _POSIX_VDISABLE;
261 bt->c_cc[VERASE] = st->c_cc[2] ? st->c_cc[2] : _POSIX_VDISABLE;
262 bt->c_cc[VKILL] = st->c_cc[3] ? st->c_cc[3] : _POSIX_VDISABLE;
263 bt->c_cc[VEOF] = st->c_cc[4] ? st->c_cc[4] : _POSIX_VDISABLE;
264 bt->c_cc[VEOL] = st->c_cc[5] ? st->c_cc[5] : _POSIX_VDISABLE;
265 bt->c_cc[VEOL2] = st->c_cc[6] ? st->c_cc[6] : _POSIX_VDISABLE;
266 /* bt->c_cc[VSWTCH] = st->c_cc[7] ? st->c_cc[7] : _POSIX_VDISABLE; */
267 bt->c_cc[VSTART] = st->c_cc[8] ? st->c_cc[8] : _POSIX_VDISABLE;
268 bt->c_cc[VSTOP] = st->c_cc[9] ? st->c_cc[9] : _POSIX_VDISABLE;
269 bt->c_cc[VSUSP] = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
270 bt->c_cc[VDSUSP] = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
271 bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
272 bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
273 bt->c_cc[VWERASE] = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
274 bt->c_cc[VLNEXT] = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
275 bt->c_cc[VSTATUS] = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
276
277 /* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
278 bt->c_cc[VMIN] = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOF];
279 bt->c_cc[VTIME] = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOL];
280 }
281
282
283 static void
284 btios2stios(struct termios *bt, struct sunos_termios *st)
285 {
286 netbsd32_u_long l, r;
287 int s;
288
289 l = bt->c_iflag;
290 r = ((l & IGNBRK) ? 0x00000001 : 0);
291 r |= ((l & BRKINT) ? 0x00000002 : 0);
292 r |= ((l & IGNPAR) ? 0x00000004 : 0);
293 r |= ((l & PARMRK) ? 0x00000008 : 0);
294 r |= ((l & INPCK) ? 0x00000010 : 0);
295 r |= ((l & ISTRIP) ? 0x00000020 : 0);
296 r |= ((l & INLCR) ? 0x00000040 : 0);
297 r |= ((l & IGNCR) ? 0x00000080 : 0);
298 r |= ((l & ICRNL) ? 0x00000100 : 0);
299 /* ((l & IUCLC) ? 0x00000200 : 0) */
300 r |= ((l & IXON) ? 0x00000400 : 0);
301 r |= ((l & IXANY) ? 0x00000800 : 0);
302 r |= ((l & IXOFF) ? 0x00001000 : 0);
303 r |= ((l & IMAXBEL) ? 0x00002000 : 0);
304 st->c_iflag = r;
305
306 l = bt->c_oflag;
307 r = ((l & OPOST) ? 0x00000001 : 0);
308 /* ((l & OLCUC) ? 0x00000002 : 0) */
309 r |= ((l & ONLCR) ? 0x00000004 : 0);
310 /* ((l & OCRNL) ? 0x00000008 : 0) */
311 /* ((l & ONOCR) ? 0x00000010 : 0) */
312 /* ((l & ONLRET) ? 0x00000020 : 0) */
313 /* ((l & OFILL) ? 0x00000040 : 0) */
314 /* ((l & OFDEL) ? 0x00000080 : 0) */
315 /* ((l & NLDLY) ? 0x00000100 : 0) */
316 /* ((l & NL1) ? 0x00000100 : 0) */
317 /* ((l & CRDLY) ? 0x00000600 : 0) */
318 /* ((l & CR1) ? 0x00000200 : 0) */
319 /* ((l & CR2) ? 0x00000400 : 0) */
320 /* ((l & CR3) ? 0x00000600 : 0) */
321 /* ((l & TABDLY) ? 0x00001800 : 0) */
322 /* ((l & TAB1) ? 0x00000800 : 0) */
323 /* ((l & TAB2) ? 0x00001000 : 0) */
324 r |= ((l & OXTABS) ? 0x00001800 : 0);
325 /* ((l & BSDLY) ? 0x00002000 : 0) */
326 /* ((l & BS1) ? 0x00002000 : 0) */
327 /* ((l & VTDLY) ? 0x00004000 : 0) */
328 /* ((l & VT1) ? 0x00004000 : 0) */
329 /* ((l & FFDLY) ? 0x00008000 : 0) */
330 /* ((l & FF1) ? 0x00008000 : 0) */
331 /* ((l & PAGEOUT) ? 0x00010000 : 0) */
332 /* ((l & WRAP) ? 0x00020000 : 0) */
333 st->c_oflag = r;
334
335 l = bt->c_cflag;
336 switch (l & CSIZE) {
337 case CS5:
338 r = 0;
339 break;
340 case CS6:
341 r = 0x00000010;
342 break;
343 case CS7:
344 r = 0x00000020;
345 break;
346 case CS8:
347 r = 0x00000030;
348 break;
349 }
350 r |= ((l & CSTOPB) ? 0x00000040 : 0);
351 r |= ((l & CREAD) ? 0x00000080 : 0);
352 r |= ((l & PARENB) ? 0x00000100 : 0);
353 r |= ((l & PARODD) ? 0x00000200 : 0);
354 r |= ((l & HUPCL) ? 0x00000400 : 0);
355 r |= ((l & CLOCAL) ? 0x00000800 : 0);
356 /* ((l & LOBLK) ? 0x00001000 : 0) */
357 r |= ((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
358 st->c_cflag = r;
359
360 l = bt->c_lflag;
361 r = ((l & ISIG) ? 0x00000001 : 0);
362 r |= ((l & ICANON) ? 0x00000002 : 0);
363 /* ((l & XCASE) ? 0x00000004 : 0) */
364 r |= ((l & ECHO) ? 0x00000008 : 0);
365 r |= ((l & ECHOE) ? 0x00000010 : 0);
366 r |= ((l & ECHOK) ? 0x00000020 : 0);
367 r |= ((l & ECHONL) ? 0x00000040 : 0);
368 r |= ((l & NOFLSH) ? 0x00000080 : 0);
369 r |= ((l & TOSTOP) ? 0x00000100 : 0);
370 r |= ((l & ECHOCTL) ? 0x00000200 : 0);
371 r |= ((l & ECHOPRT) ? 0x00000400 : 0);
372 r |= ((l & ECHOKE) ? 0x00000800 : 0);
373 /* ((l & DEFECHO) ? 0x00001000 : 0) */
374 r |= ((l & FLUSHO) ? 0x00002000 : 0);
375 r |= ((l & PENDIN) ? 0x00004000 : 0);
376 st->c_lflag = r;
377
378 s = ttspeedtab(bt->c_ospeed, sptab);
379 if (s >= 0)
380 st->c_cflag |= s;
381
382 st->c_cc[0] = bt->c_cc[VINTR] != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
383 st->c_cc[1] = bt->c_cc[VQUIT] != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
384 st->c_cc[2] = bt->c_cc[VERASE] != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
385 st->c_cc[3] = bt->c_cc[VKILL] != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
386 st->c_cc[4] = bt->c_cc[VEOF] != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
387 st->c_cc[5] = bt->c_cc[VEOL] != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
388 st->c_cc[6] = bt->c_cc[VEOL2] != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
389 st->c_cc[7] = 0;
390 /* bt->c_cc[VSWTCH] != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
391 st->c_cc[8] = bt->c_cc[VSTART] != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
392 st->c_cc[9] = bt->c_cc[VSTOP] != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
393 st->c_cc[10]= bt->c_cc[VSUSP] != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
394 st->c_cc[11]= bt->c_cc[VDSUSP] != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
395 st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
396 st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
397 st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
398 st->c_cc[15]= bt->c_cc[VLNEXT] != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
399 st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
400
401 if (!(bt->c_lflag & ICANON)) {
402 /* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
403 st->c_cc[4] = bt->c_cc[VMIN];
404 st->c_cc[5] = bt->c_cc[VTIME];
405 }
406
407 st->c_line = 0;
408 }
409
410 static void
411 stios2stio(struct sunos_termios *ts, struct sunos_termio *t)
412 {
413 t->c_iflag = ts->c_iflag;
414 t->c_oflag = ts->c_oflag;
415 t->c_cflag = ts->c_cflag;
416 t->c_lflag = ts->c_lflag;
417 t->c_line = ts->c_line;
418 memcpy(t->c_cc, ts->c_cc, 8);
419 }
420
421 static void
422 stio2stios(struct sunos_termio *t, struct sunos_termios *ts)
423 {
424 ts->c_iflag = t->c_iflag;
425 ts->c_oflag = t->c_oflag;
426 ts->c_cflag = t->c_cflag;
427 ts->c_lflag = t->c_lflag;
428 ts->c_line = t->c_line;
429 memcpy(ts->c_cc, t->c_cc, 8); /* don't touch the upper fields! */
430 }
431
432 int
433 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap, register_t *retval)
434 {
435 /* {
436 int fd;
437 netbsd32_u_long com;
438 netbsd32_caddr_t data;
439 } */
440 struct proc *p = l->l_proc;
441 struct filedesc *fdp = p->p_fd;
442 struct file *fp;
443 int (*ctl)(struct file *, u_long, void *, struct lwp *);
444 struct netbsd32_ioctl_args bsd_ua;
445 int error;
446
447 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
448 SCARG(&bsd_ua, com) = SCARG(uap, com);
449 SCARG(&bsd_ua, data) = SCARG(uap, data);
450
451 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
452 return EBADF;
453
454 if ((fp->f_flag & (FREAD|FWRITE)) == 0)
455 return EBADF;
456
457 ctl = fp->f_ops->fo_ioctl;
458
459 switch (SCARG(uap, com)) {
460 case _IOR('t', 0, int):
461 SCARG(&bsd_ua, com) = TIOCGETD;
462 break;
463 case _IOW('t', 1, int):
464 {
465 int disc;
466
467 if ((error = copyin(SCARG_P32(uap, data), &disc,
468 sizeof disc)) != 0)
469 return error;
470
471 /* map SunOS NTTYDISC into our termios discipline */
472 if (disc == 2)
473 disc = 0;
474 /* all other disciplines are not supported by NetBSD */
475 if (disc)
476 return ENXIO;
477
478 return (*ctl)(fp, TIOCSETD, &disc, l);
479 }
480 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
481 {
482 int x; /* unused */
483
484 return copyin(SCARG_P32(uap, data), &x, sizeof x);
485 }
486 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
487 {
488 int x = 0;
489
490 return copyout(&x, SCARG_P32(uap, data), sizeof x);
491 }
492 case _IO('t', 36): /* sun TIOCCONS, no parameters */
493 {
494 int on = 1;
495 return (*ctl)(fp, TIOCCONS, &on, l);
496 }
497 case _IOW('t', 37, struct sunos_ttysize):
498 {
499 struct winsize ws;
500 struct sunos_ttysize ss;
501
502 if ((error = (*ctl)(fp, TIOCGWINSZ, &ws, l)) != 0)
503 return (error);
504
505 if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0)
506 return error;
507
508 ws.ws_row = ss.ts_row;
509 ws.ws_col = ss.ts_col;
510
511 return ((*ctl)(fp, TIOCSWINSZ, &ws, l));
512 }
513 case _IOW('t', 38, struct sunos_ttysize):
514 {
515 struct winsize ws;
516 struct sunos_ttysize ss;
517
518 if ((error = (*ctl)(fp, TIOCGWINSZ, &ws, l)) != 0)
519 return (error);
520
521 ss.ts_row = ws.ws_row;
522 ss.ts_col = ws.ws_col;
523
524 return copyout(&ss, SCARG_P32(uap, data), sizeof (ss));
525 }
526 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
527 SCARG(&bsd_ua, com) = TIOCSPGRP;
528 break;
529 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
530 {
531 /*
532 * sigh, must do error translation on pty devices
533 * (see also kern/tty_pty.c)
534 */
535 int pgrp;
536 struct vnode *vp;
537 error = (*ctl)(fp, TIOCGPGRP, &pgrp, l);
538 if (error) {
539 vp = (struct vnode *)fp->f_data;
540 if (error == EIO && vp != NULL &&
541 vp->v_type == VCHR && major(vp->v_rdev) == 21)
542 error = ENOTTY;
543 return (error);
544 }
545 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
546 }
547 case _IO('t', 132):
548 SCARG(&bsd_ua, com) = TIOCSCTTY;
549 break;
550 case SUNOS_TCGETA:
551 case SUNOS_TCGETS:
552 {
553 struct termios bts;
554 struct sunos_termios sts;
555 struct sunos_termio st;
556
557 if ((error = (*ctl)(fp, TIOCGETA, &bts, l)) != 0)
558 return error;
559
560 btios2stios (&bts, &sts);
561 if (SCARG(uap, com) == SUNOS_TCGETA) {
562 stios2stio (&sts, &st);
563 return copyout(&st, SCARG_P32(uap, data),
564 sizeof (st));
565 } else
566 return copyout(&sts, SCARG_P32(uap, data),
567 sizeof (sts));
568 /*NOTREACHED*/
569 }
570 case SUNOS_TCSETA:
571 case SUNOS_TCSETAW:
572 case SUNOS_TCSETAF:
573 {
574 struct termios bts;
575 struct sunos_termios sts;
576 struct sunos_termio st;
577
578 if ((error = copyin(SCARG_P32(uap, data), &st,
579 sizeof (st))) != 0)
580 return error;
581
582 /* get full BSD termios so we don't lose information */
583 if ((error = (*ctl)(fp, TIOCGETA, &bts, l)) != 0)
584 return error;
585
586 /*
587 * convert to sun termios, copy in information from
588 * termio, and convert back, then set new values.
589 */
590 btios2stios(&bts, &sts);
591 stio2stios(&st, &sts);
592 stios2btios(&sts, &bts);
593
594 return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
595 &bts, l);
596 }
597 case SUNOS_TCSETS:
598 case SUNOS_TCSETSW:
599 case SUNOS_TCSETSF:
600 {
601 struct termios bts;
602 struct sunos_termios sts;
603
604 if ((error = copyin(SCARG_P32(uap, data), &sts,
605 sizeof (sts))) != 0)
606 return error;
607 stios2btios (&sts, &bts);
608 return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
609 &bts, l);
610 }
611 /*
612 * Pseudo-tty ioctl translations.
613 */
614 case _IOW('t', 32, int): { /* TIOCTCNTL */
615 int error1, on;
616
617 error1 = copyin(SCARG_P32(uap, data), &on, sizeof (on));
618 if (error1)
619 return error1;
620 return (*ctl)(fp, TIOCUCNTL, &on, l);
621 }
622 case _IOW('t', 33, int): { /* TIOCSIGNAL */
623 int error1, sig;
624
625 error1 = copyin(SCARG_P32(uap, data), &sig, sizeof (sig));
626 if (error1)
627 return error1;
628 return (*ctl)(fp, TIOCSIG, &sig, l);
629 }
630
631 /*
632 * Socket ioctl translations.
633 */
634 #define IFREQ_IN(a) { \
635 struct oifreq ifreq; \
636 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
637 if (error) \
638 return error; \
639 return (*ctl)(fp, a, &ifreq, l); \
640 }
641 #define IFREQ_INOUT(a) { \
642 struct oifreq ifreq; \
643 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
644 if (error) \
645 return error; \
646 if ((error = (*ctl)(fp, a, &ifreq, l)) != 0) \
647 return error; \
648 return copyout(&ifreq, SCARG_P32(uap, data), sizeof (ifreq)); \
649 }
650
651 case _IOW('i', 12, struct oifreq):
652 /* SIOCSIFADDR */
653 break;
654
655 case _IOWR('i', 13, struct oifreq):
656 IFREQ_INOUT(OOSIOCGIFADDR);
657
658 case _IOW('i', 14, struct oifreq):
659 /* SIOCSIFDSTADDR */
660 break;
661
662 case _IOWR('i', 15, struct oifreq):
663 IFREQ_INOUT(OOSIOCGIFDSTADDR);
664
665 case _IOW('i', 16, struct oifreq):
666 /* SIOCSIFFLAGS */
667 break;
668
669 case _IOWR('i', 17, struct oifreq):
670 /* SIOCGIFFLAGS */
671 break;
672
673 case _IOW('i', 21, struct oifreq):
674 IFREQ_IN(SIOCSIFMTU);
675
676 case _IOWR('i', 22, struct oifreq):
677 IFREQ_INOUT(SIOCGIFMTU);
678
679 case _IOWR('i', 23, struct oifreq):
680 IFREQ_INOUT(SIOCGIFBRDADDR);
681
682 case _IOW('i', 24, struct oifreq):
683 IFREQ_IN(SIOCSIFBRDADDR);
684
685 case _IOWR('i', 25, struct oifreq):
686 IFREQ_INOUT(OOSIOCGIFNETMASK);
687
688 case _IOW('i', 26, struct oifreq):
689 IFREQ_IN(SIOCSIFNETMASK);
690
691 case _IOWR('i', 27, struct oifreq):
692 IFREQ_INOUT(SIOCGIFMETRIC);
693
694 case _IOWR('i', 28, struct oifreq):
695 IFREQ_IN(SIOCSIFMETRIC);
696
697 case _IOW('i', 30, struct arpreq):
698 /* SIOCSARP */
699 break;
700
701 case _IOWR('i', 31, struct arpreq):
702 /* SIOCGARP */
703 break;
704
705 case _IOW('i', 32, struct arpreq):
706 /* SIOCDARP */
707 break;
708
709 case _IOW('i', 18, struct oifreq): /* SIOCSIFMEM */
710 case _IOWR('i', 19, struct oifreq): /* SIOCGIFMEM */
711 case _IOW('i', 40, struct oifreq): /* SIOCUPPER */
712 case _IOW('i', 41, struct oifreq): /* SIOCLOWER */
713 case _IOW('i', 44, struct oifreq): /* SIOCSETSYNC */
714 case _IOWR('i', 45, struct oifreq): /* SIOCGETSYNC */
715 case _IOWR('i', 46, struct oifreq): /* SIOCSDSTATS */
716 case _IOWR('i', 47, struct oifreq): /* SIOCSESTATS */
717 case _IOW('i', 48, int): /* SIOCSPROMISC */
718 case _IOW('i', 49, struct oifreq): /* SIOCADDMULTI */
719 case _IOW('i', 50, struct oifreq): /* SIOCDELMULTI */
720 return EOPNOTSUPP;
721
722 case _IOWR('i', 20, struct oifconf): /* SIOCGIFCONF */
723 {
724 struct oifconf ifcf;
725
726 /*
727 * XXX: two more problems
728 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
729 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
730 */
731 error = copyin(SCARG_P32(uap, data), &ifcf,
732 sizeof (ifcf));
733 if (error)
734 return error;
735 error = (*ctl)(fp, OOSIOCGIFCONF, &ifcf, l);
736 if (error)
737 return error;
738 return copyout(&ifcf, SCARG_P32(uap, data),
739 sizeof (ifcf));
740 }
741
742 /*
743 * Audio ioctl translations.
744 */
745 case _IOR('A', 1, struct sunos_audio_info): /* AUDIO_GETINFO */
746 sunos_au_getinfo:
747 {
748 struct audio_info aui;
749 struct sunos_audio_info sunos_aui;
750
751 error = (*ctl)(fp, AUDIO_GETINFO, &aui, l);
752 if (error)
753 return error;
754
755 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
756 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
757
758 /* `avail_ports' is `seek' in BSD */
759 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
760 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
761
762 sunos_aui.play.waiting = 0;
763 sunos_aui.record.waiting = 0;
764 sunos_aui.play.eof = 0;
765 sunos_aui.record.eof = 0;
766 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
767 /*XXXsunos_aui.output_muted = 0;*/
768 /*XXX*/sunos_aui.reserved[0] = 0;
769 /*XXX*/sunos_aui.reserved[1] = 0;
770 /*XXX*/sunos_aui.reserved[2] = 0;
771 /*XXX*/sunos_aui.reserved[3] = 0;
772
773 return copyout(&sunos_aui, SCARG_P32(uap, data),
774 sizeof (sunos_aui));
775 }
776
777 case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */
778 {
779 struct audio_info aui;
780 struct sunos_audio_info sunos_aui;
781
782 error = copyin(SCARG_P32(uap, data), &sunos_aui,
783 sizeof (sunos_aui));
784 if (error)
785 return error;
786
787 aui.play = *(struct audio_prinfo *)&sunos_aui.play;
788 aui.record = *(struct audio_prinfo *)&sunos_aui.record;
789 /* aui.__spare = sunos_aui.monitor_gain; */
790 aui.blocksize = ~0;
791 aui.hiwat = ~0;
792 aui.lowat = ~0;
793 /* XXX somebody check this please. - is: aui.backlog = ~0; */
794 aui.mode = ~0;
795 /*
796 * The bsd driver does not distinguish between paused and
797 * active. (In the sun driver, not active means samples are
798 * not output at all, but paused means the last streams buffer
799 * is drained and then output stops.) If either are 0, then
800 * when stop output. Otherwise, if either are non-zero,
801 * we resume.
802 */
803 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
804 aui.play.pause = 0;
805 else if (sunos_aui.play.pause != (u_char)~0 ||
806 sunos_aui.play.active != (u_char)~0)
807 aui.play.pause = 1;
808 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
809 aui.record.pause = 0;
810 else if (sunos_aui.record.pause != (u_char)~0 ||
811 sunos_aui.record.active != (u_char)~0)
812 aui.record.pause = 1;
813
814 error = (*ctl)(fp, AUDIO_SETINFO, &aui, l);
815 if (error)
816 return error;
817 /* Return new state */
818 goto sunos_au_getinfo;
819 }
820 case _IO('A', 3): /* AUDIO_DRAIN */
821 return (*ctl)(fp, AUDIO_DRAIN, NULL, l);
822 case _IOR('A', 4, int): /* AUDIO_GETDEV */
823 {
824 int devtype = SUNOS_AUDIO_DEV_AMD;
825 return copyout(&devtype, SCARG_P32(uap, data),
826 sizeof (devtype));
827 }
828
829 /*
830 * Selected streams ioctls.
831 */
832 #define SUNOS_S_FLUSHR 1
833 #define SUNOS_S_FLUSHW 2
834 #define SUNOS_S_FLUSHRW 3
835
836 #define SUNOS_S_INPUT 1
837 #define SUNOS_S_HIPRI 2
838 #define SUNOS_S_OUTPUT 4
839 #define SUNOS_S_MSG 8
840
841 case _IO('S', 5): /* I_FLUSH */
842 {
843 int tmp = 0;
844 switch ((intptr_t)SCARG_P32(uap, data)) {
845 case SUNOS_S_FLUSHR: tmp = FREAD;
846 case SUNOS_S_FLUSHW: tmp = FWRITE;
847 case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE;
848 }
849 return (*ctl)(fp, TIOCFLUSH, &tmp, l);
850 }
851 case _IO('S', 9): /* I_SETSIG */
852 {
853 int on = 1;
854 if (((intptr_t)SCARG_P32(uap, data) &
855 (SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
856 SUNOS_S_HIPRI)
857 return EOPNOTSUPP;
858 return (*ctl)(fp, FIOASYNC, &on, l);
859 }
860 /*
861 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
862 * (which was from the old sparc/scsi/sun_disklabel.c), and
863 * modified to suite.
864 */
865 case DKIOCGGEOM:
866 {
867 struct disklabel dl;
868
869 error = (*ctl)(fp, DIOCGDINFO, &dl, l);
870 if (error)
871 return (error);
872
873 #define datageom ((struct sun_dkgeom *)SCARG_P32(uap, data))
874 /* XXX can't do memset() on a user address (dsl) */
875 memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
876
877 datageom->sdkc_ncylinders = dl.d_ncylinders;
878 datageom->sdkc_acylinders = dl.d_acylinders;
879 datageom->sdkc_ntracks = dl.d_ntracks;
880 datageom->sdkc_nsectors = dl.d_nsectors;
881 datageom->sdkc_interleave = dl.d_interleave;
882 datageom->sdkc_sparespercyl = dl.d_sparespercyl;
883 datageom->sdkc_rpm = dl.d_rpm;
884 datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
885 #undef datageom
886 break;
887 }
888
889 case DKIOCINFO:
890 /* Homey don't do DKIOCINFO */
891 /* XXX can't do memset() on a user address (dsl) */
892 memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
893 break;
894
895 case DKIOCGPART:
896 {
897 struct partinfo pi;
898
899 error = (*ctl)(fp, DIOCGPART, &pi, l);
900 if (error)
901 return (error);
902
903 if (pi.disklab->d_secpercyl == 0)
904 return (ERANGE); /* XXX */
905 if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
906 return (ERANGE); /* XXX */
907 /* XXX can't do direct writes to a user address (dsl) */
908 #define datapart ((struct sun_dkpart *)SCARG_P32(uap, data))
909 datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
910 datapart->sdkp_nsectors = pi.part->p_size;
911 #undef datapart
912 }
913
914 }
915 return (netbsd32_ioctl(l, &bsd_ua, retval));
916 }
917
918 /* SunOS fcntl(2) cmds not implemented */
919 #define SUN_F_RGETLK 10
920 #define SUN_F_RSETLK 11
921 #define SUN_F_CNVT 12
922 #define SUN_F_RSETLKW 13
923
924 /* SunOS flock translation */
925 struct sunos_flock {
926 short l_type;
927 short l_whence;
928 netbsd32_long l_start;
929 netbsd32_long l_len;
930 short l_pid;
931 short l_xxx;
932 };
933
934 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
935 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
936
937 #define SUNOS_F_RDLCK 1
938 #define SUNOS_F_WRLCK 2
939 #define SUNOS_F_UNLCK 3
940
941 static void
942 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp)
943 {
944 switch (iflp->l_type) {
945 case F_RDLCK:
946 oflp->l_type = SUNOS_F_RDLCK;
947 break;
948 case F_WRLCK:
949 oflp->l_type = SUNOS_F_WRLCK;
950 break;
951 case F_UNLCK:
952 oflp->l_type = SUNOS_F_UNLCK;
953 break;
954 default:
955 oflp->l_type = -1;
956 break;
957 }
958
959 oflp->l_whence = (short) iflp->l_whence;
960 oflp->l_start = (netbsd32_long) iflp->l_start;
961 oflp->l_len = (netbsd32_long) iflp->l_len;
962 oflp->l_pid = (short) iflp->l_pid;
963 oflp->l_xxx = 0;
964 }
965
966
967 static void
968 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
969 {
970 switch (iflp->l_type) {
971 case SUNOS_F_RDLCK:
972 oflp->l_type = F_RDLCK;
973 break;
974 case SUNOS_F_WRLCK:
975 oflp->l_type = F_WRLCK;
976 break;
977 case SUNOS_F_UNLCK:
978 oflp->l_type = F_UNLCK;
979 break;
980 default:
981 oflp->l_type = -1;
982 break;
983 }
984
985 oflp->l_whence = iflp->l_whence;
986 oflp->l_start = (off_t) iflp->l_start;
987 oflp->l_len = (off_t) iflp->l_len;
988 oflp->l_pid = (pid_t) iflp->l_pid;
989
990 }
991 static struct {
992 netbsd32_long sun_flg;
993 netbsd32_long bsd_flg;
994 } sunfcntl_flgtab[] = {
995 /* F_[GS]ETFLags that differ: */
996 #define SUN_FSETBLK 0x0010
997 #define SUN_SHLOCK 0x0080
998 #define SUN_EXLOCK 0x0100
999 #define SUN_FNBIO 0x1000
1000 #define SUN_FSYNC 0x2000
1001 #define SUN_NONBLOCK 0x4000
1002 #define SUN_FNOCTTY 0x8000
1003 { SUN_NONBLOCK, O_NONBLOCK },
1004 { SUN_FNBIO, O_NONBLOCK },
1005 { SUN_SHLOCK, O_SHLOCK },
1006 { SUN_EXLOCK, O_EXLOCK },
1007 { SUN_FSYNC, O_FSYNC },
1008 { SUN_FSETBLK, 0 },
1009 { SUN_FNOCTTY, 0 }
1010 };
1011
1012 int
1013 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap, register_t *retval)
1014 {
1015 /* {
1016 syscallarg(int) fd;
1017 syscallarg(int) cmd;
1018 syscallarg(netbsd32_voidp) arg;
1019 } */
1020 struct sys_fcntl_args bsd_ua;
1021 uintptr_t flg;
1022 int n, ret;
1023
1024 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
1025 SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
1026 SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
1027
1028 switch (SCARG(uap, cmd)) {
1029 case F_SETFL:
1030 flg = (intptr_t)SCARG_P32(uap, arg);
1031 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1032 while (--n >= 0) {
1033 if (flg & sunfcntl_flgtab[n].sun_flg) {
1034 flg &= ~sunfcntl_flgtab[n].sun_flg;
1035 flg |= sunfcntl_flgtab[n].bsd_flg;
1036 }
1037 }
1038 SCARG(&bsd_ua, arg) = (void *)flg;
1039 break;
1040
1041 case F_GETLK:
1042 case F_SETLK:
1043 case F_SETLKW:
1044 {
1045 int error;
1046 struct sunos_flock ifl;
1047 struct flock fl;
1048
1049 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1050 if (error)
1051 return error;
1052 sunos_to_bsd_flock(&ifl, &fl);
1053
1054 error = do_fcntl_lock(l, SCARG(uap, fd), SCARG(uap, cmd), &fl);
1055 if (error || SCARG(uap, cmd) != F_GETLK)
1056 return error;
1057
1058 bsd_to_sunos_flock(&fl, &ifl);
1059 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1060 }
1061 break;
1062 case SUN_F_RGETLK:
1063 case SUN_F_RSETLK:
1064 case SUN_F_CNVT:
1065 case SUN_F_RSETLKW:
1066 return (EOPNOTSUPP);
1067 }
1068
1069 ret = sys_fcntl(l, &bsd_ua, retval);
1070 if (ret != 0)
1071 return ret;
1072
1073 switch (SCARG(uap, cmd)) {
1074 case F_GETFL:
1075 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1076 ret = *retval;
1077 while (--n >= 0) {
1078 if (ret & sunfcntl_flgtab[n].bsd_flg) {
1079 ret &= ~sunfcntl_flgtab[n].bsd_flg;
1080 ret |= sunfcntl_flgtab[n].sun_flg;
1081 }
1082 }
1083 *retval = ret;
1084 break;
1085 }
1086
1087 return 0;
1088 }
1089