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