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