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