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