sunos32_ioctl.c revision 1.25 1 /* $NetBSD: sunos32_ioctl.c,v 1.25 2007/12/08 18:36:23 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.25 2007/12/08 18:36:23 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, void *v, register_t *retval)
434 {
435 struct sunos32_sys_ioctl_args /* {
436 int fd;
437 netbsd32_u_long com;
438 netbsd32_caddr_t data;
439 } */ *uap = v;
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 int error;
445
446 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
447 return EBADF;
448
449 if ((fp->f_flag & (FREAD|FWRITE)) == 0)
450 return EBADF;
451
452 ctl = fp->f_ops->fo_ioctl;
453
454 switch (SCARG(uap, com)) {
455 case _IOR('t', 0, int):
456 SCARG(uap, com) = TIOCGETD;
457 break;
458 case _IOW('t', 1, int):
459 {
460 int disc;
461
462 if ((error = copyin(SCARG_P32(uap, data), &disc,
463 sizeof disc)) != 0)
464 return error;
465
466 /* map SunOS NTTYDISC into our termios discipline */
467 if (disc == 2)
468 disc = 0;
469 /* all other disciplines are not supported by NetBSD */
470 if (disc)
471 return ENXIO;
472
473 return (*ctl)(fp, TIOCSETD, &disc, l);
474 }
475 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
476 {
477 int x; /* unused */
478
479 return copyin(SCARG_P32(uap, data), &x, sizeof x);
480 }
481 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
482 {
483 int x = 0;
484
485 return copyout(&x, SCARG_P32(uap, data), sizeof x);
486 }
487 case _IO('t', 36): /* sun TIOCCONS, no parameters */
488 {
489 int on = 1;
490 return (*ctl)(fp, TIOCCONS, &on, l);
491 }
492 case _IOW('t', 37, struct sunos_ttysize):
493 {
494 struct winsize ws;
495 struct sunos_ttysize ss;
496
497 if ((error = (*ctl)(fp, TIOCGWINSZ, &ws, l)) != 0)
498 return (error);
499
500 if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0)
501 return error;
502
503 ws.ws_row = ss.ts_row;
504 ws.ws_col = ss.ts_col;
505
506 return ((*ctl)(fp, TIOCSWINSZ, &ws, l));
507 }
508 case _IOW('t', 38, struct sunos_ttysize):
509 {
510 struct winsize ws;
511 struct sunos_ttysize ss;
512
513 if ((error = (*ctl)(fp, TIOCGWINSZ, &ws, l)) != 0)
514 return (error);
515
516 ss.ts_row = ws.ws_row;
517 ss.ts_col = ws.ws_col;
518
519 return copyout(&ss, SCARG_P32(uap, data), sizeof (ss));
520 }
521 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
522 SCARG(uap, com) = TIOCSPGRP;
523 break;
524 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
525 {
526 /*
527 * sigh, must do error translation on pty devices
528 * (see also kern/tty_pty.c)
529 */
530 int pgrp;
531 struct vnode *vp;
532 error = (*ctl)(fp, TIOCGPGRP, &pgrp, l);
533 if (error) {
534 vp = (struct vnode *)fp->f_data;
535 if (error == EIO && vp != NULL &&
536 vp->v_type == VCHR && major(vp->v_rdev) == 21)
537 error = ENOTTY;
538 return (error);
539 }
540 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
541 }
542 case _IO('t', 132):
543 SCARG(uap, com) = TIOCSCTTY;
544 break;
545 case SUNOS_TCGETA:
546 case SUNOS_TCGETS:
547 {
548 struct termios bts;
549 struct sunos_termios sts;
550 struct sunos_termio st;
551
552 if ((error = (*ctl)(fp, TIOCGETA, &bts, l)) != 0)
553 return error;
554
555 btios2stios (&bts, &sts);
556 if (SCARG(uap, com) == SUNOS_TCGETA) {
557 stios2stio (&sts, &st);
558 return copyout(&st, SCARG_P32(uap, data),
559 sizeof (st));
560 } else
561 return copyout(&sts, SCARG_P32(uap, data),
562 sizeof (sts));
563 /*NOTREACHED*/
564 }
565 case SUNOS_TCSETA:
566 case SUNOS_TCSETAW:
567 case SUNOS_TCSETAF:
568 {
569 struct termios bts;
570 struct sunos_termios sts;
571 struct sunos_termio st;
572
573 if ((error = copyin(SCARG_P32(uap, data), &st,
574 sizeof (st))) != 0)
575 return error;
576
577 /* get full BSD termios so we don't lose information */
578 if ((error = (*ctl)(fp, TIOCGETA, &bts, l)) != 0)
579 return error;
580
581 /*
582 * convert to sun termios, copy in information from
583 * termio, and convert back, then set new values.
584 */
585 btios2stios(&bts, &sts);
586 stio2stios(&st, &sts);
587 stios2btios(&sts, &bts);
588
589 return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
590 &bts, l);
591 }
592 case SUNOS_TCSETS:
593 case SUNOS_TCSETSW:
594 case SUNOS_TCSETSF:
595 {
596 struct termios bts;
597 struct sunos_termios sts;
598
599 if ((error = copyin(SCARG_P32(uap, data), &sts,
600 sizeof (sts))) != 0)
601 return error;
602 stios2btios (&sts, &bts);
603 return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
604 &bts, l);
605 }
606 /*
607 * Pseudo-tty ioctl translations.
608 */
609 case _IOW('t', 32, int): { /* TIOCTCNTL */
610 int error1, on;
611
612 error1 = copyin(SCARG_P32(uap, data), &on, sizeof (on));
613 if (error1)
614 return error1;
615 return (*ctl)(fp, TIOCUCNTL, &on, l);
616 }
617 case _IOW('t', 33, int): { /* TIOCSIGNAL */
618 int error1, sig;
619
620 error1 = copyin(SCARG_P32(uap, data), &sig, sizeof (sig));
621 if (error1)
622 return error1;
623 return (*ctl)(fp, TIOCSIG, &sig, l);
624 }
625
626 /*
627 * Socket ioctl translations.
628 */
629 #define IFREQ_IN(a) { \
630 struct oifreq ifreq; \
631 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
632 if (error) \
633 return error; \
634 return (*ctl)(fp, a, &ifreq, l); \
635 }
636 #define IFREQ_INOUT(a) { \
637 struct oifreq ifreq; \
638 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
639 if (error) \
640 return error; \
641 if ((error = (*ctl)(fp, a, &ifreq, l)) != 0) \
642 return error; \
643 return copyout(&ifreq, SCARG_P32(uap, data), sizeof (ifreq)); \
644 }
645
646 case _IOW('i', 12, struct oifreq):
647 /* SIOCSIFADDR */
648 break;
649
650 case _IOWR('i', 13, struct oifreq):
651 IFREQ_INOUT(OOSIOCGIFADDR);
652
653 case _IOW('i', 14, struct oifreq):
654 /* SIOCSIFDSTADDR */
655 break;
656
657 case _IOWR('i', 15, struct oifreq):
658 IFREQ_INOUT(OOSIOCGIFDSTADDR);
659
660 case _IOW('i', 16, struct oifreq):
661 /* SIOCSIFFLAGS */
662 break;
663
664 case _IOWR('i', 17, struct oifreq):
665 /* SIOCGIFFLAGS */
666 break;
667
668 case _IOW('i', 21, struct oifreq):
669 IFREQ_IN(SIOCSIFMTU);
670
671 case _IOWR('i', 22, struct oifreq):
672 IFREQ_INOUT(SIOCGIFMTU);
673
674 case _IOWR('i', 23, struct oifreq):
675 IFREQ_INOUT(SIOCGIFBRDADDR);
676
677 case _IOW('i', 24, struct oifreq):
678 IFREQ_IN(SIOCSIFBRDADDR);
679
680 case _IOWR('i', 25, struct oifreq):
681 IFREQ_INOUT(OOSIOCGIFNETMASK);
682
683 case _IOW('i', 26, struct oifreq):
684 IFREQ_IN(SIOCSIFNETMASK);
685
686 case _IOWR('i', 27, struct oifreq):
687 IFREQ_INOUT(SIOCGIFMETRIC);
688
689 case _IOWR('i', 28, struct oifreq):
690 IFREQ_IN(SIOCSIFMETRIC);
691
692 case _IOW('i', 30, struct arpreq):
693 /* SIOCSARP */
694 break;
695
696 case _IOWR('i', 31, struct arpreq):
697 /* SIOCGARP */
698 break;
699
700 case _IOW('i', 32, struct arpreq):
701 /* SIOCDARP */
702 break;
703
704 case _IOW('i', 18, struct oifreq): /* SIOCSIFMEM */
705 case _IOWR('i', 19, struct oifreq): /* SIOCGIFMEM */
706 case _IOW('i', 40, struct oifreq): /* SIOCUPPER */
707 case _IOW('i', 41, struct oifreq): /* SIOCLOWER */
708 case _IOW('i', 44, struct oifreq): /* SIOCSETSYNC */
709 case _IOWR('i', 45, struct oifreq): /* SIOCGETSYNC */
710 case _IOWR('i', 46, struct oifreq): /* SIOCSDSTATS */
711 case _IOWR('i', 47, struct oifreq): /* SIOCSESTATS */
712 case _IOW('i', 48, int): /* SIOCSPROMISC */
713 case _IOW('i', 49, struct oifreq): /* SIOCADDMULTI */
714 case _IOW('i', 50, struct oifreq): /* SIOCDELMULTI */
715 return EOPNOTSUPP;
716
717 case _IOWR('i', 20, struct oifconf): /* SIOCGIFCONF */
718 {
719 struct oifconf ifcf;
720
721 /*
722 * XXX: two more problems
723 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
724 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
725 */
726 error = copyin(SCARG_P32(uap, data), &ifcf,
727 sizeof (ifcf));
728 if (error)
729 return error;
730 error = (*ctl)(fp, OOSIOCGIFCONF, &ifcf, l);
731 if (error)
732 return error;
733 return copyout(&ifcf, SCARG_P32(uap, data),
734 sizeof (ifcf));
735 }
736
737 /*
738 * Audio ioctl translations.
739 */
740 case _IOR('A', 1, struct sunos_audio_info): /* AUDIO_GETINFO */
741 sunos_au_getinfo:
742 {
743 struct audio_info aui;
744 struct sunos_audio_info sunos_aui;
745
746 error = (*ctl)(fp, AUDIO_GETINFO, &aui, l);
747 if (error)
748 return error;
749
750 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
751 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
752
753 /* `avail_ports' is `seek' in BSD */
754 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
755 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
756
757 sunos_aui.play.waiting = 0;
758 sunos_aui.record.waiting = 0;
759 sunos_aui.play.eof = 0;
760 sunos_aui.record.eof = 0;
761 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
762 /*XXXsunos_aui.output_muted = 0;*/
763 /*XXX*/sunos_aui.reserved[0] = 0;
764 /*XXX*/sunos_aui.reserved[1] = 0;
765 /*XXX*/sunos_aui.reserved[2] = 0;
766 /*XXX*/sunos_aui.reserved[3] = 0;
767
768 return copyout(&sunos_aui, SCARG_P32(uap, data),
769 sizeof (sunos_aui));
770 }
771
772 case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */
773 {
774 struct audio_info aui;
775 struct sunos_audio_info sunos_aui;
776
777 error = copyin(SCARG_P32(uap, data), &sunos_aui,
778 sizeof (sunos_aui));
779 if (error)
780 return error;
781
782 aui.play = *(struct audio_prinfo *)&sunos_aui.play;
783 aui.record = *(struct audio_prinfo *)&sunos_aui.record;
784 /* aui.__spare = sunos_aui.monitor_gain; */
785 aui.blocksize = ~0;
786 aui.hiwat = ~0;
787 aui.lowat = ~0;
788 /* XXX somebody check this please. - is: aui.backlog = ~0; */
789 aui.mode = ~0;
790 /*
791 * The bsd driver does not distinguish between paused and
792 * active. (In the sun driver, not active means samples are
793 * not output at all, but paused means the last streams buffer
794 * is drained and then output stops.) If either are 0, then
795 * when stop output. Otherwise, if either are non-zero,
796 * we resume.
797 */
798 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
799 aui.play.pause = 0;
800 else if (sunos_aui.play.pause != (u_char)~0 ||
801 sunos_aui.play.active != (u_char)~0)
802 aui.play.pause = 1;
803 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
804 aui.record.pause = 0;
805 else if (sunos_aui.record.pause != (u_char)~0 ||
806 sunos_aui.record.active != (u_char)~0)
807 aui.record.pause = 1;
808
809 error = (*ctl)(fp, AUDIO_SETINFO, &aui, l);
810 if (error)
811 return error;
812 /* Return new state */
813 goto sunos_au_getinfo;
814 }
815 case _IO('A', 3): /* AUDIO_DRAIN */
816 return (*ctl)(fp, AUDIO_DRAIN, NULL, l);
817 case _IOR('A', 4, int): /* AUDIO_GETDEV */
818 {
819 int devtype = SUNOS_AUDIO_DEV_AMD;
820 return copyout(&devtype, SCARG_P32(uap, data),
821 sizeof (devtype));
822 }
823
824 /*
825 * Selected streams ioctls.
826 */
827 #define SUNOS_S_FLUSHR 1
828 #define SUNOS_S_FLUSHW 2
829 #define SUNOS_S_FLUSHRW 3
830
831 #define SUNOS_S_INPUT 1
832 #define SUNOS_S_HIPRI 2
833 #define SUNOS_S_OUTPUT 4
834 #define SUNOS_S_MSG 8
835
836 case _IO('S', 5): /* I_FLUSH */
837 {
838 int tmp = 0;
839 switch ((intptr_t)SCARG_P32(uap, data)) {
840 case SUNOS_S_FLUSHR: tmp = FREAD;
841 case SUNOS_S_FLUSHW: tmp = FWRITE;
842 case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE;
843 }
844 return (*ctl)(fp, TIOCFLUSH, &tmp, l);
845 }
846 case _IO('S', 9): /* I_SETSIG */
847 {
848 int on = 1;
849 if (((intptr_t)SCARG_P32(uap, data) &
850 (SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
851 SUNOS_S_HIPRI)
852 return EOPNOTSUPP;
853 return (*ctl)(fp, FIOASYNC, &on, l);
854 }
855 /*
856 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
857 * (which was from the old sparc/scsi/sun_disklabel.c), and
858 * modified to suite.
859 */
860 case DKIOCGGEOM:
861 {
862 struct disklabel dl;
863
864 error = (*ctl)(fp, DIOCGDINFO, &dl, l);
865 if (error)
866 return (error);
867
868 #define datageom ((struct sun_dkgeom *)SCARG_P32(uap, data))
869 /* XXX can't do memset() on a user address (dsl) */
870 memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
871
872 datageom->sdkc_ncylinders = dl.d_ncylinders;
873 datageom->sdkc_acylinders = dl.d_acylinders;
874 datageom->sdkc_ntracks = dl.d_ntracks;
875 datageom->sdkc_nsectors = dl.d_nsectors;
876 datageom->sdkc_interleave = dl.d_interleave;
877 datageom->sdkc_sparespercyl = dl.d_sparespercyl;
878 datageom->sdkc_rpm = dl.d_rpm;
879 datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
880 #undef datageom
881 break;
882 }
883
884 case DKIOCINFO:
885 /* Homey don't do DKIOCINFO */
886 /* XXX can't do memset() on a user address (dsl) */
887 memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
888 break;
889
890 case DKIOCGPART:
891 {
892 struct partinfo pi;
893
894 error = (*ctl)(fp, DIOCGPART, &pi, l);
895 if (error)
896 return (error);
897
898 if (pi.disklab->d_secpercyl == 0)
899 return (ERANGE); /* XXX */
900 if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
901 return (ERANGE); /* XXX */
902 /* XXX can't do direct writes to a user address (dsl) */
903 #define datapart ((struct sun_dkpart *)SCARG_P32(uap, data))
904 datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
905 datapart->sdkp_nsectors = pi.part->p_size;
906 #undef datapart
907 }
908
909 }
910 return (netbsd32_ioctl(l, uap, retval));
911 }
912
913 /* SunOS fcntl(2) cmds not implemented */
914 #define SUN_F_RGETLK 10
915 #define SUN_F_RSETLK 11
916 #define SUN_F_CNVT 12
917 #define SUN_F_RSETLKW 13
918
919 /* SunOS flock translation */
920 struct sunos_flock {
921 short l_type;
922 short l_whence;
923 netbsd32_long l_start;
924 netbsd32_long l_len;
925 short l_pid;
926 short l_xxx;
927 };
928
929 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
930 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
931
932 #define SUNOS_F_RDLCK 1
933 #define SUNOS_F_WRLCK 2
934 #define SUNOS_F_UNLCK 3
935
936 static void
937 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp)
938 {
939 switch (iflp->l_type) {
940 case F_RDLCK:
941 oflp->l_type = SUNOS_F_RDLCK;
942 break;
943 case F_WRLCK:
944 oflp->l_type = SUNOS_F_WRLCK;
945 break;
946 case F_UNLCK:
947 oflp->l_type = SUNOS_F_UNLCK;
948 break;
949 default:
950 oflp->l_type = -1;
951 break;
952 }
953
954 oflp->l_whence = (short) iflp->l_whence;
955 oflp->l_start = (netbsd32_long) iflp->l_start;
956 oflp->l_len = (netbsd32_long) iflp->l_len;
957 oflp->l_pid = (short) iflp->l_pid;
958 oflp->l_xxx = 0;
959 }
960
961
962 static void
963 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
964 {
965 switch (iflp->l_type) {
966 case SUNOS_F_RDLCK:
967 oflp->l_type = F_RDLCK;
968 break;
969 case SUNOS_F_WRLCK:
970 oflp->l_type = F_WRLCK;
971 break;
972 case SUNOS_F_UNLCK:
973 oflp->l_type = F_UNLCK;
974 break;
975 default:
976 oflp->l_type = -1;
977 break;
978 }
979
980 oflp->l_whence = iflp->l_whence;
981 oflp->l_start = (off_t) iflp->l_start;
982 oflp->l_len = (off_t) iflp->l_len;
983 oflp->l_pid = (pid_t) iflp->l_pid;
984
985 }
986 static struct {
987 netbsd32_long sun_flg;
988 netbsd32_long bsd_flg;
989 } sunfcntl_flgtab[] = {
990 /* F_[GS]ETFLags that differ: */
991 #define SUN_FSETBLK 0x0010
992 #define SUN_SHLOCK 0x0080
993 #define SUN_EXLOCK 0x0100
994 #define SUN_FNBIO 0x1000
995 #define SUN_FSYNC 0x2000
996 #define SUN_NONBLOCK 0x4000
997 #define SUN_FNOCTTY 0x8000
998 { SUN_NONBLOCK, O_NONBLOCK },
999 { SUN_FNBIO, O_NONBLOCK },
1000 { SUN_SHLOCK, O_SHLOCK },
1001 { SUN_EXLOCK, O_EXLOCK },
1002 { SUN_FSYNC, O_FSYNC },
1003 { SUN_FSETBLK, 0 },
1004 { SUN_FNOCTTY, 0 }
1005 };
1006
1007 int
1008 sunos32_sys_fcntl(struct lwp *l, void *v, register_t *retval)
1009 {
1010 struct sunos32_sys_fcntl_args /* {
1011 syscallarg(int) fd;
1012 syscallarg(int) cmd;
1013 syscallarg(netbsd32_voidp) arg;
1014 } */ *uap = v;
1015 uintptr_t flg;
1016 int n, ret;
1017
1018 switch (SCARG(uap, cmd)) {
1019 case F_SETFL:
1020 flg = (intptr_t)SCARG_P32(uap, arg);
1021 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1022 while (--n >= 0) {
1023 if (flg & sunfcntl_flgtab[n].sun_flg) {
1024 flg &= ~sunfcntl_flgtab[n].sun_flg;
1025 flg |= sunfcntl_flgtab[n].bsd_flg;
1026 }
1027 }
1028 NETBSD32PTR32(SCARG(uap, arg), (void *)flg);
1029 break;
1030
1031 case F_GETLK:
1032 case F_SETLK:
1033 case F_SETLKW:
1034 {
1035 int error;
1036 struct sunos_flock ifl;
1037 struct flock fl;
1038
1039 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1040 if (error)
1041 return error;
1042 sunos_to_bsd_flock(&ifl, &fl);
1043
1044 error = do_fcntl_lock(l, SCARG(uap, fd), SCARG(uap, cmd), &fl);
1045 if (error || SCARG(uap, cmd) != F_GETLK)
1046 return error;
1047
1048 bsd_to_sunos_flock(&fl, &ifl);
1049 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1050 }
1051 break;
1052 case SUN_F_RGETLK:
1053 case SUN_F_RSETLK:
1054 case SUN_F_CNVT:
1055 case SUN_F_RSETLKW:
1056 return (EOPNOTSUPP);
1057 }
1058
1059 ret = netbsd32_fcntl(l, uap, retval);
1060
1061 switch (SCARG(uap, cmd)) {
1062 case F_GETFL:
1063 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1064 while (--n >= 0) {
1065 if (ret & sunfcntl_flgtab[n].bsd_flg) {
1066 ret &= ~sunfcntl_flgtab[n].bsd_flg;
1067 ret |= sunfcntl_flgtab[n].sun_flg;
1068 }
1069 }
1070 break;
1071 }
1072
1073 return (ret);
1074 }
1075