1 /* $NetBSD: sunos_ioctl.c,v 1.60 2008/03/21 21:54:59 ad Exp $ */
4 * Copyright (c) 1993 Markus Wild.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: sunos_ioctl.c,v 1.60 2008/03/21 21:54:59 ad Exp $");
32 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/filedesc.h>
37 #include <sys/ioctl.h>
38 #include <sys/termios.h>
40 #include <sys/socket.h>
41 #include <sys/audioio.h>
42 #include <sys/vnode.h>
43 #include <sys/mount.h>
44 #include <sys/disklabel.h>
45 #include <sys/syscallargs.h>
47 #include <miscfs/specfs/specdev.h>
51 #include <compat/sys/sockio.h>
53 #include <dev/sun/disklabel.h>
55 #include <compat/sunos/sunos.h>
56 #include <compat/sunos/sunos_syscallargs.h>
57 #include <compat/common/compat_util.h>
61 * This file is something of a hodge-podge.
62 * Support gets added as things turn up....
65 static const struct speedtab sptab
[] = {
86 static const u_long s2btab
[] = {
105 static void stios2btios(struct sunos_termios
*, struct termios
*);
106 static void btios2stios(struct termios
*, struct sunos_termios
*);
107 static void stios2stio(struct sunos_termios
*, struct sunos_termio
*);
108 static void stio2stios(struct sunos_termio
*, struct sunos_termios
*);
111 * These two conversion functions have mostly been done
112 * with some perl cut&paste, then hand-edited to comment
113 * out what doesn't exist under NetBSD.
114 * A note from Markus's code:
115 * (l & BITMASK1) / BITMASK1 * BITMASK2 is translated
116 * optimally by gcc m68k, much better than any ?: stuff.
117 * Code may vary with different architectures of course.
119 * I don't know what optimizer you used, but seeing divu's and
120 * bfextu's in the m68k assembly output did not encourage me...
121 * as well, gcc on the sparc definitely generates much better
126 stios2btios(struct sunos_termios
*st
, struct termios
*bt
)
131 r
= ((l
& 0x00000001) ? IGNBRK
: 0);
132 r
|= ((l
& 0x00000002) ? BRKINT
: 0);
133 r
|= ((l
& 0x00000004) ? IGNPAR
: 0);
134 r
|= ((l
& 0x00000008) ? PARMRK
: 0);
135 r
|= ((l
& 0x00000010) ? INPCK
: 0);
136 r
|= ((l
& 0x00000020) ? ISTRIP
: 0);
137 r
|= ((l
& 0x00000040) ? INLCR
: 0);
138 r
|= ((l
& 0x00000080) ? IGNCR
: 0);
139 r
|= ((l
& 0x00000100) ? ICRNL
: 0);
140 /* ((l & 0x00000200) ? IUCLC : 0) */
141 r
|= ((l
& 0x00000400) ? IXON
: 0);
142 r
|= ((l
& 0x00000800) ? IXANY
: 0);
143 r
|= ((l
& 0x00001000) ? IXOFF
: 0);
144 r
|= ((l
& 0x00002000) ? IMAXBEL
: 0);
148 r
= ((l
& 0x00000001) ? OPOST
: 0);
149 /* ((l & 0x00000002) ? OLCUC : 0) */
150 r
|= ((l
& 0x00000004) ? ONLCR
: 0);
151 /* ((l & 0x00000008) ? OCRNL : 0) */
152 /* ((l & 0x00000010) ? ONOCR : 0) */
153 /* ((l & 0x00000020) ? ONLRET : 0) */
154 /* ((l & 0x00000040) ? OFILL : 0) */
155 /* ((l & 0x00000080) ? OFDEL : 0) */
156 /* ((l & 0x00000100) ? NLDLY : 0) */
157 /* ((l & 0x00000100) ? NL1 : 0) */
158 /* ((l & 0x00000600) ? CRDLY : 0) */
159 /* ((l & 0x00000200) ? CR1 : 0) */
160 /* ((l & 0x00000400) ? CR2 : 0) */
161 /* ((l & 0x00000600) ? CR3 : 0) */
162 /* ((l & 0x00001800) ? TABDLY : 0) */
163 /* ((l & 0x00000800) ? TAB1 : 0) */
164 /* ((l & 0x00001000) ? TAB2 : 0) */
165 r
|= ((l
& 0x00001800) ? OXTABS
: 0);
166 /* ((l & 0x00002000) ? BSDLY : 0) */
167 /* ((l & 0x00002000) ? BS1 : 0) */
168 /* ((l & 0x00004000) ? VTDLY : 0) */
169 /* ((l & 0x00004000) ? VT1 : 0) */
170 /* ((l & 0x00008000) ? FFDLY : 0) */
171 /* ((l & 0x00008000) ? FF1 : 0) */
172 /* ((l & 0x00010000) ? PAGEOUT : 0) */
173 /* ((l & 0x00020000) ? WRAP : 0) */
177 switch (l
& 0x00000030) {
191 r
|= ((l
& 0x00000040) ? CSTOPB
: 0);
192 r
|= ((l
& 0x00000080) ? CREAD
: 0);
193 r
|= ((l
& 0x00000100) ? PARENB
: 0);
194 r
|= ((l
& 0x00000200) ? PARODD
: 0);
195 r
|= ((l
& 0x00000400) ? HUPCL
: 0);
196 r
|= ((l
& 0x00000800) ? CLOCAL
: 0);
197 /* ((l & 0x00001000) ? LOBLK : 0) */
198 r
|= ((l
& 0x80000000) ? (CRTS_IFLOW
|CCTS_OFLOW
) : 0);
201 bt
->c_ispeed
= bt
->c_ospeed
= s2btab
[l
& 0x0000000f];
204 r
= ((l
& 0x00000001) ? ISIG
: 0);
205 r
|= ((l
& 0x00000002) ? ICANON
: 0);
206 /* ((l & 0x00000004) ? XCASE : 0) */
207 r
|= ((l
& 0x00000008) ? ECHO
: 0);
208 r
|= ((l
& 0x00000010) ? ECHOE
: 0);
209 r
|= ((l
& 0x00000020) ? ECHOK
: 0);
210 r
|= ((l
& 0x00000040) ? ECHONL
: 0);
211 r
|= ((l
& 0x00000080) ? NOFLSH
: 0);
212 r
|= ((l
& 0x00000100) ? TOSTOP
: 0);
213 r
|= ((l
& 0x00000200) ? ECHOCTL
: 0);
214 r
|= ((l
& 0x00000400) ? ECHOPRT
: 0);
215 r
|= ((l
& 0x00000800) ? ECHOKE
: 0);
216 /* ((l & 0x00001000) ? DEFECHO : 0) */
217 r
|= ((l
& 0x00002000) ? FLUSHO
: 0);
218 r
|= ((l
& 0x00004000) ? PENDIN
: 0);
221 bt
->c_cc
[VINTR
] = st
->c_cc
[0] ? st
->c_cc
[0] : _POSIX_VDISABLE
;
222 bt
->c_cc
[VQUIT
] = st
->c_cc
[1] ? st
->c_cc
[1] : _POSIX_VDISABLE
;
223 bt
->c_cc
[VERASE
] = st
->c_cc
[2] ? st
->c_cc
[2] : _POSIX_VDISABLE
;
224 bt
->c_cc
[VKILL
] = st
->c_cc
[3] ? st
->c_cc
[3] : _POSIX_VDISABLE
;
225 bt
->c_cc
[VEOF
] = st
->c_cc
[4] ? st
->c_cc
[4] : _POSIX_VDISABLE
;
226 bt
->c_cc
[VEOL
] = st
->c_cc
[5] ? st
->c_cc
[5] : _POSIX_VDISABLE
;
227 bt
->c_cc
[VEOL2
] = st
->c_cc
[6] ? st
->c_cc
[6] : _POSIX_VDISABLE
;
228 /* bt->c_cc[VSWTCH] = st->c_cc[7] ? st->c_cc[7] : _POSIX_VDISABLE; */
229 bt
->c_cc
[VSTART
] = st
->c_cc
[8] ? st
->c_cc
[8] : _POSIX_VDISABLE
;
230 bt
->c_cc
[VSTOP
] = st
->c_cc
[9] ? st
->c_cc
[9] : _POSIX_VDISABLE
;
231 bt
->c_cc
[VSUSP
] = st
->c_cc
[10] ? st
->c_cc
[10] : _POSIX_VDISABLE
;
232 bt
->c_cc
[VDSUSP
] = st
->c_cc
[11] ? st
->c_cc
[11] : _POSIX_VDISABLE
;
233 bt
->c_cc
[VREPRINT
] = st
->c_cc
[12] ? st
->c_cc
[12] : _POSIX_VDISABLE
;
234 bt
->c_cc
[VDISCARD
] = st
->c_cc
[13] ? st
->c_cc
[13] : _POSIX_VDISABLE
;
235 bt
->c_cc
[VWERASE
] = st
->c_cc
[14] ? st
->c_cc
[14] : _POSIX_VDISABLE
;
236 bt
->c_cc
[VLNEXT
] = st
->c_cc
[15] ? st
->c_cc
[15] : _POSIX_VDISABLE
;
237 bt
->c_cc
[VSTATUS
] = st
->c_cc
[16] ? st
->c_cc
[16] : _POSIX_VDISABLE
;
239 /* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
240 bt
->c_cc
[VMIN
] = (bt
->c_lflag
& ICANON
) ? 1 : bt
->c_cc
[VEOF
];
241 bt
->c_cc
[VTIME
] = (bt
->c_lflag
& ICANON
) ? 1 : bt
->c_cc
[VEOL
];
246 btios2stios(struct termios
*bt
, struct sunos_termios
*st
)
252 r
= ((l
& IGNBRK
) ? 0x00000001 : 0);
253 r
|= ((l
& BRKINT
) ? 0x00000002 : 0);
254 r
|= ((l
& IGNPAR
) ? 0x00000004 : 0);
255 r
|= ((l
& PARMRK
) ? 0x00000008 : 0);
256 r
|= ((l
& INPCK
) ? 0x00000010 : 0);
257 r
|= ((l
& ISTRIP
) ? 0x00000020 : 0);
258 r
|= ((l
& INLCR
) ? 0x00000040 : 0);
259 r
|= ((l
& IGNCR
) ? 0x00000080 : 0);
260 r
|= ((l
& ICRNL
) ? 0x00000100 : 0);
261 /* ((l & IUCLC) ? 0x00000200 : 0) */
262 r
|= ((l
& IXON
) ? 0x00000400 : 0);
263 r
|= ((l
& IXANY
) ? 0x00000800 : 0);
264 r
|= ((l
& IXOFF
) ? 0x00001000 : 0);
265 r
|= ((l
& IMAXBEL
) ? 0x00002000 : 0);
269 r
= ((l
& OPOST
) ? 0x00000001 : 0);
270 /* ((l & OLCUC) ? 0x00000002 : 0) */
271 r
|= ((l
& ONLCR
) ? 0x00000004 : 0);
272 /* ((l & OCRNL) ? 0x00000008 : 0) */
273 /* ((l & ONOCR) ? 0x00000010 : 0) */
274 /* ((l & ONLRET) ? 0x00000020 : 0) */
275 /* ((l & OFILL) ? 0x00000040 : 0) */
276 /* ((l & OFDEL) ? 0x00000080 : 0) */
277 /* ((l & NLDLY) ? 0x00000100 : 0) */
278 /* ((l & NL1) ? 0x00000100 : 0) */
279 /* ((l & CRDLY) ? 0x00000600 : 0) */
280 /* ((l & CR1) ? 0x00000200 : 0) */
281 /* ((l & CR2) ? 0x00000400 : 0) */
282 /* ((l & CR3) ? 0x00000600 : 0) */
283 /* ((l & TABDLY) ? 0x00001800 : 0) */
284 /* ((l & TAB1) ? 0x00000800 : 0) */
285 /* ((l & TAB2) ? 0x00001000 : 0) */
286 r
|= ((l
& OXTABS
) ? 0x00001800 : 0);
287 /* ((l & BSDLY) ? 0x00002000 : 0) */
288 /* ((l & BS1) ? 0x00002000 : 0) */
289 /* ((l & VTDLY) ? 0x00004000 : 0) */
290 /* ((l & VT1) ? 0x00004000 : 0) */
291 /* ((l & FFDLY) ? 0x00008000 : 0) */
292 /* ((l & FF1) ? 0x00008000 : 0) */
293 /* ((l & PAGEOUT) ? 0x00010000 : 0) */
294 /* ((l & WRAP) ? 0x00020000 : 0) */
312 r
|= ((l
& CSTOPB
) ? 0x00000040 : 0);
313 r
|= ((l
& CREAD
) ? 0x00000080 : 0);
314 r
|= ((l
& PARENB
) ? 0x00000100 : 0);
315 r
|= ((l
& PARODD
) ? 0x00000200 : 0);
316 r
|= ((l
& HUPCL
) ? 0x00000400 : 0);
317 r
|= ((l
& CLOCAL
) ? 0x00000800 : 0);
318 /* ((l & LOBLK) ? 0x00001000 : 0) */
319 r
|= ((l
& (CRTS_IFLOW
|CCTS_OFLOW
)) ? 0x80000000 : 0);
323 r
= ((l
& ISIG
) ? 0x00000001 : 0);
324 r
|= ((l
& ICANON
) ? 0x00000002 : 0);
325 /* ((l & XCASE) ? 0x00000004 : 0) */
326 r
|= ((l
& ECHO
) ? 0x00000008 : 0);
327 r
|= ((l
& ECHOE
) ? 0x00000010 : 0);
328 r
|= ((l
& ECHOK
) ? 0x00000020 : 0);
329 r
|= ((l
& ECHONL
) ? 0x00000040 : 0);
330 r
|= ((l
& NOFLSH
) ? 0x00000080 : 0);
331 r
|= ((l
& TOSTOP
) ? 0x00000100 : 0);
332 r
|= ((l
& ECHOCTL
) ? 0x00000200 : 0);
333 r
|= ((l
& ECHOPRT
) ? 0x00000400 : 0);
334 r
|= ((l
& ECHOKE
) ? 0x00000800 : 0);
335 /* ((l & DEFECHO) ? 0x00001000 : 0) */
336 r
|= ((l
& FLUSHO
) ? 0x00002000 : 0);
337 r
|= ((l
& PENDIN
) ? 0x00004000 : 0);
340 s
= ttspeedtab(bt
->c_ospeed
, sptab
);
344 st
->c_cc
[0] = bt
->c_cc
[VINTR
] != _POSIX_VDISABLE
? bt
->c_cc
[VINTR
]:0;
345 st
->c_cc
[1] = bt
->c_cc
[VQUIT
] != _POSIX_VDISABLE
? bt
->c_cc
[VQUIT
]:0;
346 st
->c_cc
[2] = bt
->c_cc
[VERASE
] != _POSIX_VDISABLE
? bt
->c_cc
[VERASE
]:0;
347 st
->c_cc
[3] = bt
->c_cc
[VKILL
] != _POSIX_VDISABLE
? bt
->c_cc
[VKILL
]:0;
348 st
->c_cc
[4] = bt
->c_cc
[VEOF
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOF
]:0;
349 st
->c_cc
[5] = bt
->c_cc
[VEOL
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOL
]:0;
350 st
->c_cc
[6] = bt
->c_cc
[VEOL2
] != _POSIX_VDISABLE
? bt
->c_cc
[VEOL2
]:0;
352 /* bt->c_cc[VSWTCH] != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
353 st
->c_cc
[8] = bt
->c_cc
[VSTART
] != _POSIX_VDISABLE
? bt
->c_cc
[VSTART
]:0;
354 st
->c_cc
[9] = bt
->c_cc
[VSTOP
] != _POSIX_VDISABLE
? bt
->c_cc
[VSTOP
]:0;
355 st
->c_cc
[10]= bt
->c_cc
[VSUSP
] != _POSIX_VDISABLE
? bt
->c_cc
[VSUSP
]:0;
356 st
->c_cc
[11]= bt
->c_cc
[VDSUSP
] != _POSIX_VDISABLE
? bt
->c_cc
[VDSUSP
]:0;
357 st
->c_cc
[12]= bt
->c_cc
[VREPRINT
]!= _POSIX_VDISABLE
? bt
->c_cc
[VREPRINT
]:0;
358 st
->c_cc
[13]= bt
->c_cc
[VDISCARD
]!= _POSIX_VDISABLE
? bt
->c_cc
[VDISCARD
]:0;
359 st
->c_cc
[14]= bt
->c_cc
[VWERASE
] != _POSIX_VDISABLE
? bt
->c_cc
[VWERASE
]:0;
360 st
->c_cc
[15]= bt
->c_cc
[VLNEXT
] != _POSIX_VDISABLE
? bt
->c_cc
[VLNEXT
]:0;
361 st
->c_cc
[16]= bt
->c_cc
[VSTATUS
] != _POSIX_VDISABLE
? bt
->c_cc
[VSTATUS
]:0;
363 if (!(bt
->c_lflag
& ICANON
)) {
364 /* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
365 st
->c_cc
[4] = bt
->c_cc
[VMIN
];
366 st
->c_cc
[5] = bt
->c_cc
[VTIME
];
373 stios2stio(struct sunos_termios
*ts
, struct sunos_termio
*t
)
375 t
->c_iflag
= ts
->c_iflag
;
376 t
->c_oflag
= ts
->c_oflag
;
377 t
->c_cflag
= ts
->c_cflag
;
378 t
->c_lflag
= ts
->c_lflag
;
379 t
->c_line
= ts
->c_line
;
380 memcpy(t
->c_cc
, ts
->c_cc
, 8);
384 stio2stios(struct sunos_termio
*t
, struct sunos_termios
*ts
)
386 ts
->c_iflag
= t
->c_iflag
;
387 ts
->c_oflag
= t
->c_oflag
;
388 ts
->c_cflag
= t
->c_cflag
;
389 ts
->c_lflag
= t
->c_lflag
;
390 ts
->c_line
= t
->c_line
;
391 memcpy(ts
->c_cc
, t
->c_cc
, 8); /* don't touch the upper fields! */
395 sunos_sys_ioctl(struct lwp
*l
, const struct sunos_sys_ioctl_args
*uap
, register_t
*retval
)
403 int (*ctl
)(struct file
*, u_long
, void *);
404 struct sys_ioctl_args pass_ua
;
407 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
)
410 if ((fp
->f_flag
& (FREAD
|FWRITE
)) == 0) {
415 error
= EPASSTHROUGH
;
416 SCARG(&pass_ua
, com
) = SCARG(uap
, com
);
417 ctl
= fp
->f_ops
->fo_ioctl
;
419 switch (SCARG(uap
, com
)) {
420 case _IOR('t', 0, int):
421 SCARG(&pass_ua
, com
) = TIOCGETD
;
423 case _IOW('t', 1, int):
427 if ((error
= copyin(SCARG(uap
, data
), (void *)&disc
,
431 /* map SunOS NTTYDISC into our termios discipline */
434 /* all other disciplines are not supported by NetBSD */
440 error
= (*ctl
)(fp
, TIOCSETD
, &disc
);
442 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
446 error
= copyin((void *)&x
, SCARG(uap
, data
), sizeof x
);
449 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
453 error
= copyout((void *)&x
, SCARG(uap
, data
), sizeof x
);
456 case _IO('t', 36): /* sun TIOCCONS, no parameters */
459 error
= (*ctl
)(fp
, TIOCCONS
, &on
);
462 case _IOW('t', 37, struct sunos_ttysize
):
465 struct sunos_ttysize ss
;
467 if ((error
= (*ctl
)(fp
, TIOCGWINSZ
, &ws
)) != 0)
470 if ((error
= copyin (SCARG(uap
, data
), &ss
, sizeof (ss
))) != 0)
473 ws
.ws_row
= ss
.ts_row
;
474 ws
.ws_col
= ss
.ts_col
;
476 error
= (*ctl
)(fp
, TIOCSWINSZ
, &ws
);
479 case _IOW('t', 38, struct sunos_ttysize
):
482 struct sunos_ttysize ss
;
484 if ((error
= (*ctl
)(fp
, TIOCGWINSZ
, &ws
)) != 0)
487 ss
.ts_row
= ws
.ws_row
;
488 ss
.ts_col
= ws
.ws_col
;
490 error
= copyout((void *)&ss
, SCARG(uap
, data
), sizeof (ss
));
493 case _IOR('t', 119, int): /* TIOCGPGRP */
497 error
= (*ctl
)(fp
, TIOCGPGRP
, &pgrp
);
498 if (error
== 0 && pgrp
== 0)
502 error
= copyout((void *)&pgrp
, SCARG(uap
, data
), sizeof(pgrp
));
505 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
506 SCARG(&pass_ua
, com
) = TIOCSPGRP
;
508 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
511 * sigh, must do error translation on pty devices. if the pgrp
512 * returned is 0 (and no error), we convert this to EIO, if it
518 error
= (*ctl
)(fp
, TIOCGPGRP
, &pgrp
);
520 vp
= (struct vnode
*)fp
->f_data
;
521 if ((error
== EIO
|| (error
== 0 && pgrp
== 0)) &&
523 vp
->v_type
== VCHR
&&
524 major(vp
->v_rdev
) == 21)
528 error
= copyout((void *)&pgrp
, SCARG(uap
, data
), sizeof(pgrp
));
532 SCARG(&pass_ua
, com
) = TIOCSCTTY
;
538 struct sunos_termios sts
;
539 struct sunos_termio st
;
541 if ((error
= (*ctl
)(fp
, TIOCGETA
, &bts
)) != 0)
544 btios2stios (&bts
, &sts
);
545 if (SCARG(uap
, com
) == SUNOS_TCGETA
) {
546 stios2stio (&sts
, &st
);
547 error
= copyout((void *)&st
, SCARG(uap
, data
),
550 error
= copyout((void *)&sts
, SCARG(uap
, data
),
559 struct sunos_termios sts
;
560 struct sunos_termio st
;
562 if ((error
= copyin(SCARG(uap
, data
), &st
, sizeof (st
))) != 0)
565 /* get full BSD termios so we don't lose information */
566 if ((error
= (*ctl
)(fp
, TIOCGETA
, &bts
)) != 0)
570 * convert to sun termios, copy in information from
571 * termio, and convert back, then set new values.
573 btios2stios(&bts
, &sts
);
574 stio2stios(&st
, &sts
);
575 stios2btios(&sts
, &bts
);
577 error
= (*ctl
)(fp
, SCARG(uap
, com
) - SUNOS_TCSETA
+ TIOCSETA
,
586 struct sunos_termios sts
;
588 if ((error
= copyin (SCARG(uap
, data
), (void *)&sts
,
591 stios2btios (&sts
, &bts
);
592 error
= (*ctl
)(fp
, SCARG(uap
, com
) - SUNOS_TCSETS
+ TIOCSETA
,
597 * Pseudo-tty ioctl translations.
599 case _IOW('t', 32, int): { /* TIOCTCNTL */
602 error
= copyin (SCARG(uap
, data
), (void *)&on
, sizeof (on
));
605 error
= (*ctl
)(fp
, TIOCUCNTL
, &on
);
608 case _IOW('t', 33, int): { /* TIOCSIGNAL */
611 error
= copyin (SCARG(uap
, data
), (void *)&sig
, sizeof (sig
));
614 error
= (*ctl
)(fp
, TIOCSIG
, &sig
);
619 * Socket ioctl translations.
621 #define IFREQ_IN(a) { \
622 struct oifreq ifreq; \
623 error = copyin (SCARG(uap, data), (void *)&ifreq, sizeof (ifreq)); \
626 error = (*ctl)(fp, a, &ifreq); \
629 #define IFREQ_INOUT(a) { \
630 struct oifreq ifreq; \
631 error = copyin (SCARG(uap, data), (void *)&ifreq, sizeof (ifreq)); \
634 if ((error = (*ctl)(fp, a, &ifreq)) != 0) \
636 error = copyout ((void *)&ifreq, SCARG(uap, data), sizeof (ifreq)); \
640 case _IOW('i', 12, struct oifreq
): /* SIOCSIFADDR */
641 case _IOW('i', 14, struct oifreq
): /* SIOCSIFDSTADDR */
642 case _IOW('i', 16, struct oifreq
): /* SIOCSIFFLAGS */
643 case _IOWR('i', 17, struct oifreq
): /* SIOCGIFFLAGS */
644 case _IOW('i', 30, struct arpreq
): /* SIOCSARP */
645 case _IOWR('i', 31, struct arpreq
): /* SIOCGARP */
646 case _IOW('i', 32, struct arpreq
): /* SIOCDARP */
649 case _IOWR('i', 13, struct oifreq
):
650 IFREQ_INOUT(OOSIOCGIFADDR
);
652 case _IOWR('i', 15, struct oifreq
):
653 IFREQ_INOUT(OOSIOCGIFDSTADDR
);
655 case _IOW('i', 21, struct oifreq
):
656 IFREQ_IN(SIOCSIFMTU
);
658 case _IOWR('i', 22, struct oifreq
):
659 IFREQ_INOUT(SIOCGIFMTU
);
661 case _IOWR('i', 23, struct oifreq
):
662 IFREQ_INOUT(SIOCGIFBRDADDR
);
664 case _IOW('i', 24, struct oifreq
):
665 IFREQ_IN(SIOCSIFBRDADDR
);
667 case _IOWR('i', 25, struct oifreq
):
668 IFREQ_INOUT(OOSIOCGIFNETMASK
);
670 case _IOW('i', 26, struct oifreq
):
671 IFREQ_IN(SIOCSIFNETMASK
);
673 case _IOWR('i', 27, struct oifreq
):
674 IFREQ_INOUT(SIOCGIFMETRIC
);
676 case _IOWR('i', 28, struct oifreq
):
677 IFREQ_IN(SIOCSIFMETRIC
);
679 case _IOW('i', 18, struct oifreq
): /* SIOCSIFMEM */
680 case _IOWR('i', 19, struct oifreq
): /* SIOCGIFMEM */
681 case _IOW('i', 40, struct oifreq
): /* SIOCUPPER */
682 case _IOW('i', 41, struct oifreq
): /* SIOCLOWER */
683 case _IOW('i', 44, struct oifreq
): /* SIOCSETSYNC */
684 case _IOWR('i', 45, struct oifreq
): /* SIOCGETSYNC */
685 case _IOWR('i', 46, struct oifreq
): /* SIOCSDSTATS */
686 case _IOWR('i', 47, struct oifreq
): /* SIOCSESTATS */
687 case _IOW('i', 48, int): /* SIOCSPROMISC */
688 case _IOW('i', 49, struct oifreq
): /* SIOCADDMULTI */
689 case _IOW('i', 50, struct oifreq
): /* SIOCDELMULTI */
693 case _IOWR('i', 20, struct oifconf
): /* SIOCGIFCONF */
698 * XXX: two more problems
699 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
700 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
702 error
= copyin (SCARG(uap
, data
), &ifc
, sizeof (ifc
));
705 error
= (*ctl
)(fp
, OOSIOCGIFCONF
, &ifc
);
708 error
= copyout ((void *)&ifc
, SCARG(uap
, data
),
714 * Audio ioctl translations.
716 case _IOR('A', 1, struct sunos_audio_info
): /* AUDIO_GETINFO */
719 struct audio_info aui
;
720 struct sunos_audio_info sunos_aui
;
722 error
= (*ctl
)(fp
, AUDIO_GETINFO
, &aui
);
726 sunos_aui
.play
= *(struct sunos_audio_prinfo
*)&aui
.play
;
727 sunos_aui
.record
= *(struct sunos_audio_prinfo
*)&aui
.record
;
729 /* `avail_ports' is `seek' in BSD */
730 sunos_aui
.play
.avail_ports
= AUDIO_SPEAKER
| AUDIO_HEADPHONE
;
731 sunos_aui
.record
.avail_ports
= AUDIO_SPEAKER
| AUDIO_HEADPHONE
;
733 sunos_aui
.play
.waiting
= 0;
734 sunos_aui
.record
.waiting
= 0;
735 sunos_aui
.play
.eof
= 0;
736 sunos_aui
.record
.eof
= 0;
737 sunos_aui
.monitor_gain
= 0; /* aui.__spare; XXX */
738 /*XXXsunos_aui.output_muted = 0;*/
739 /*XXX*/sunos_aui
.reserved
[0] = 0;
740 /*XXX*/sunos_aui
.reserved
[1] = 0;
741 /*XXX*/sunos_aui
.reserved
[2] = 0;
742 /*XXX*/sunos_aui
.reserved
[3] = 0;
744 error
= copyout ((void *)&sunos_aui
, SCARG(uap
, data
),
749 case _IOWR('A', 2, struct sunos_audio_info
): /* AUDIO_SETINFO */
751 struct audio_info aui
;
752 struct sunos_audio_info sunos_aui
;
754 error
= copyin (SCARG(uap
, data
), (void *)&sunos_aui
,
759 aui
.play
= *(struct audio_prinfo
*)&sunos_aui
.play
;
760 aui
.record
= *(struct audio_prinfo
*)&sunos_aui
.record
;
761 /* aui.__spare = sunos_aui.monitor_gain; */
765 /* XXX somebody check this please. - is: aui.backlog = ~0; */
768 * The bsd driver does not distinguish between paused and
769 * active. (In the sun driver, not active means samples are
770 * not output at all, but paused means the last streams buffer
771 * is drained and then output stops.) If either are 0, then
772 * when stop output. Otherwise, if either are non-zero,
775 if (sunos_aui
.play
.pause
== 0 || sunos_aui
.play
.active
== 0)
777 else if (sunos_aui
.play
.pause
!= (u_char
)~0 ||
778 sunos_aui
.play
.active
!= (u_char
)~0)
780 if (sunos_aui
.record
.pause
== 0 || sunos_aui
.record
.active
== 0)
781 aui
.record
.pause
= 0;
782 else if (sunos_aui
.record
.pause
!= (u_char
)~0 ||
783 sunos_aui
.record
.active
!= (u_char
)~0)
784 aui
.record
.pause
= 1;
786 error
= (*ctl
)(fp
, AUDIO_SETINFO
, &aui
);
789 /* Return new state */
790 goto sunos_au_getinfo
;
792 case _IO('A', 3): /* AUDIO_DRAIN */
793 error
= (*ctl
)(fp
, AUDIO_DRAIN
, NULL
);
795 case _IOR('A', 4, int): /* AUDIO_GETDEV */
797 int devtype
= SUNOS_AUDIO_DEV_AMD
;
798 error
= copyout ((void *)&devtype
, SCARG(uap
, data
),
804 * Selected streams ioctls.
806 #define SUNOS_S_FLUSHR 1
807 #define SUNOS_S_FLUSHW 2
808 #define SUNOS_S_FLUSHRW 3
810 #define SUNOS_S_INPUT 1
811 #define SUNOS_S_HIPRI 2
812 #define SUNOS_S_OUTPUT 4
813 #define SUNOS_S_MSG 8
815 case _IO('S', 5): /* I_FLUSH */
818 switch ((int)(u_long
)SCARG(uap
, data
)) {
819 case SUNOS_S_FLUSHR
: tmp
= FREAD
;
820 case SUNOS_S_FLUSHW
: tmp
= FWRITE
;
821 case SUNOS_S_FLUSHRW
: tmp
= FREAD
|FWRITE
;
823 error
= (*ctl
)(fp
, TIOCFLUSH
, &tmp
);
826 case _IO('S', 9): /* I_SETSIG */
829 if (((int)(u_long
)SCARG(uap
, data
) &
830 (SUNOS_S_HIPRI
|SUNOS_S_INPUT
)) == SUNOS_S_HIPRI
) {
834 error
= (*ctl
)(fp
, FIOASYNC
, &on
);
838 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
839 * (which was from the old sparc/scsi/sun_disklabel.c), and
846 error
= (*ctl
)(fp
, DIOCGDINFO
, &dl
);
850 #define datageom ((struct sun_dkgeom *)SCARG(uap, data))
851 memset(SCARG(uap
, data
), 0, sizeof(*datageom
));
853 datageom
->sdkc_ncylinders
= dl
.d_ncylinders
;
854 datageom
->sdkc_acylinders
= dl
.d_acylinders
;
855 datageom
->sdkc_ntracks
= dl
.d_ntracks
;
856 datageom
->sdkc_nsectors
= dl
.d_nsectors
;
857 datageom
->sdkc_interleave
= dl
.d_interleave
;
858 datageom
->sdkc_sparespercyl
= dl
.d_sparespercyl
;
859 datageom
->sdkc_rpm
= dl
.d_rpm
;
860 datageom
->sdkc_pcylinders
= dl
.d_ncylinders
+ dl
.d_acylinders
;
866 /* Homey don't do DKIOCINFO */
867 memset(SCARG(uap
, data
), 0, sizeof(struct sun_dkctlr
));
874 error
= (*ctl
)(fp
, DIOCGPART
, &pi
);
878 if (pi
.disklab
->d_secpercyl
== 0) {
879 error
= ERANGE
; /* XXX */
882 if (pi
.part
->p_offset
% pi
.disklab
->d_secpercyl
!= 0) {
883 error
= ERANGE
; /* XXX */
887 #define datapart ((struct sun_dkpart *)SCARG(uap, data))
888 datapart
->sdkp_cyloffset
= pi
.part
->p_offset
/ pi
.disklab
->d_secpercyl
;
889 datapart
->sdkp_nsectors
= pi
.part
->p_size
;
897 fd_putfile(SCARG(uap
, fd
));
898 if (error
== EPASSTHROUGH
) {
899 SCARG(&pass_ua
, fd
) = SCARG(uap
, fd
);
900 SCARG(&pass_ua
, data
) = SCARG(uap
, data
);
901 error
= sys_ioctl(l
, &pass_ua
, retval
);
906 /* SunOS fcntl(2) cmds not implemented */
907 #define SUN_F_RGETLK 10
908 #define SUN_F_RSETLK 11
909 #define SUN_F_CNVT 12
910 #define SUN_F_RSETLKW 13
912 /* SunOS flock translation */
922 static void bsd_to_sunos_flock(struct flock
*, struct sunos_flock
*);
923 static void sunos_to_bsd_flock(struct sunos_flock
*, struct flock
*);
925 #define SUNOS_F_RDLCK 1
926 #define SUNOS_F_WRLCK 2
927 #define SUNOS_F_UNLCK 3
930 bsd_to_sunos_flock(struct flock
*iflp
, struct sunos_flock
*oflp
)
932 switch (iflp
->l_type
) {
934 oflp
->l_type
= SUNOS_F_RDLCK
;
937 oflp
->l_type
= SUNOS_F_WRLCK
;
940 oflp
->l_type
= SUNOS_F_UNLCK
;
947 oflp
->l_whence
= (short) iflp
->l_whence
;
948 oflp
->l_start
= (long) iflp
->l_start
;
949 oflp
->l_len
= (long) iflp
->l_len
;
950 oflp
->l_pid
= (short) iflp
->l_pid
;
956 sunos_to_bsd_flock(struct sunos_flock
*iflp
, struct flock
*oflp
)
958 switch (iflp
->l_type
) {
960 oflp
->l_type
= F_RDLCK
;
963 oflp
->l_type
= F_WRLCK
;
966 oflp
->l_type
= F_UNLCK
;
973 oflp
->l_whence
= iflp
->l_whence
;
974 oflp
->l_start
= (off_t
) iflp
->l_start
;
975 oflp
->l_len
= (off_t
) iflp
->l_len
;
976 oflp
->l_pid
= (pid_t
) iflp
->l_pid
;
982 } sunfcntl_flgtab
[] = {
983 /* F_[GS]ETFLags that differ: */
984 #define SUN_FSETBLK 0x0010
985 #define SUN_SHLOCK 0x0080
986 #define SUN_EXLOCK 0x0100
987 #define SUN_FNBIO 0x1000
988 #define SUN_FSYNC 0x2000
989 #define SUN_NONBLOCK 0x4000
990 #define SUN_FNOCTTY 0x8000
991 { SUN_NONBLOCK
, O_NONBLOCK
},
992 { SUN_FNBIO
, O_NONBLOCK
},
993 { SUN_SHLOCK
, O_SHLOCK
},
994 { SUN_EXLOCK
, O_EXLOCK
},
995 { SUN_FSYNC
, O_FSYNC
},
1001 sunos_sys_fcntl(struct lwp
*l
, const struct sunos_sys_fcntl_args
*uap
, register_t
*retval
)
1005 struct sys_fcntl_args bsd_ua
;
1007 SCARG(&bsd_ua
, fd
) = SCARG(uap
, fd
);
1008 SCARG(&bsd_ua
, cmd
) = SCARG(uap
, cmd
);
1009 SCARG(&bsd_ua
, arg
) = SCARG(uap
, arg
);
1012 switch (SCARG(uap
, cmd
)) {
1014 flg
= (long)SCARG(uap
, arg
);
1015 n
= sizeof(sunfcntl_flgtab
) / sizeof(sunfcntl_flgtab
[0]);
1017 if (flg
& sunfcntl_flgtab
[n
].sun_flg
) {
1018 flg
&= ~sunfcntl_flgtab
[n
].sun_flg
;
1019 flg
|= sunfcntl_flgtab
[n
].bsd_flg
;
1022 SCARG(&bsd_ua
, arg
) = (void *)flg
;
1030 struct sunos_flock ifl
;
1033 error
= copyin(SCARG(uap
, arg
), &ifl
, sizeof ifl
);
1036 sunos_to_bsd_flock(&ifl
, &fl
);
1038 error
= do_fcntl_lock(SCARG(uap
, fd
), SCARG(uap
, cmd
), &fl
);
1042 if (error
|| SCARG(uap
, cmd
) != F_GETLK
)
1045 bsd_to_sunos_flock(&fl
, &ifl
);
1047 return copyout(&ifl
, SCARG(uap
, arg
), sizeof ifl
);
1054 return (EOPNOTSUPP
);
1060 ret
= sys_fcntl(l
, &bsd_ua
, retval
);
1062 switch (SCARG(&bsd_ua
, cmd
)) {
1064 n
= sizeof(sunfcntl_flgtab
) / sizeof(sunfcntl_flgtab
[0]);
1066 if (ret
& sunfcntl_flgtab
[n
].bsd_flg
) {
1067 ret
&= ~sunfcntl_flgtab
[n
].bsd_flg
;
1068 ret
|= sunfcntl_flgtab
[n
].sun_flg
;