Home | History | Annotate | Line # | Download | only in sunos32
sunos32_ioctl.c revision 1.10
      1 /*	$NetBSD: sunos32_ioctl.c,v 1.10 2003/01/18 08:38:15 thorpej 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.10 2003/01/18 08:38:15 thorpej 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 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 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) __P((struct file *, u_long, caddr_t, 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), (caddr_t)&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, (caddr_t)&disc, p);
    484 	    }
    485 	case _IOW('t', 101, int):	/* sun SUNOS_TIOCSSOFTCAR */
    486 	    {
    487 		int x;	/* unused */
    488 
    489 		return copyin((caddr_t)&x, (caddr_t)(u_long)SCARG(uap, data), sizeof x);
    490 	    }
    491 	case _IOR('t', 100, int):	/* sun SUNOS_TIOCSSOFTCAR */
    492 	    {
    493 		int x = 0;
    494 
    495 		return copyout((caddr_t)&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, (caddr_t)&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, (caddr_t)&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, (caddr_t)&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, (caddr_t)&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 ((caddr_t)&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, (caddr_t)&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((caddr_t)&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, (caddr_t)&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((caddr_t)&st, (caddr_t)(u_long)SCARG(uap, data),
    569 			    sizeof (st));
    570 		} else
    571 			return copyout((caddr_t)&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), (caddr_t)&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, (caddr_t)&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 		    (caddr_t)&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), (caddr_t)&sts,
    610 		    sizeof (sts))) != 0)
    611 			return error;
    612 		stios2btios (&sts, &bts);
    613 		return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
    614 		    (caddr_t)&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), (caddr_t)&on, sizeof (on));
    623 		if (error)
    624 			return error;
    625 		return (*ctl)(fp, TIOCUCNTL, (caddr_t)&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), (caddr_t)&sig, sizeof (sig));
    631 		if (error)
    632 			return error;
    633 		return (*ctl)(fp, TIOCSIG, (caddr_t)&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), (caddr_t)&ifreq, sizeof (ifreq)); \
    642 	if (error) \
    643 		return error; \
    644 	return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
    645 }
    646 #define IFREQ_INOUT(a) { \
    647 	struct ifreq ifreq; \
    648 	error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
    649 	if (error) \
    650 		return error; \
    651 	if ((error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) != 0) \
    652 		return error; \
    653 	return copyout ((caddr_t)&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), (caddr_t)&ifconf,
    737 		    sizeof (ifconf));
    738 		if (error)
    739 			return error;
    740 		error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p);
    741 		if (error)
    742 			return error;
    743 		return copyout ((caddr_t)&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, (caddr_t)&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 ((caddr_t)&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), (caddr_t)&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, (caddr_t)&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, (void *)0, p);
    827 	case _IOR('A', 4, int):	/* AUDIO_GETDEV */
    828 	    {
    829 		int devtype = SUNOS_AUDIO_DEV_AMD;
    830 		return copyout ((caddr_t)&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, (caddr_t)&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, (caddr_t)&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, (caddr_t)&dl, p);
    875 		if (error)
    876 			return (error);
    877 
    878 #define datageom	((struct sun_dkgeom *)(u_long)SCARG(uap, data))
    879 		memset((caddr_t)(u_long)SCARG(uap, data), 0, sizeof(*datageom));
    880 
    881 		datageom->sdkc_ncylinders = dl.d_ncylinders;
    882 		datageom->sdkc_acylinders = dl.d_acylinders;
    883 		datageom->sdkc_ntracks = dl.d_ntracks;
    884 		datageom->sdkc_nsectors = dl.d_nsectors;
    885 		datageom->sdkc_interleave = dl.d_interleave;
    886 		datageom->sdkc_sparespercyl = dl.d_sparespercyl;
    887 		datageom->sdkc_rpm = dl.d_rpm;
    888 		datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
    889 #undef datageom
    890 		break;
    891 	    }
    892 
    893 	case DKIOCINFO:
    894 		/* Homey don't do DKIOCINFO */
    895 		memset((caddr_t)(u_long)SCARG(uap, data), 0, sizeof(struct sun_dkctlr));
    896 		break;
    897 
    898 	case DKIOCGPART:
    899             {
    900 		struct partinfo pi;
    901 
    902 		error = (*ctl)(fp, DIOCGPART, (caddr_t)&pi, p);
    903 		if (error)
    904 			return (error);
    905 
    906 		if (pi.disklab->d_secpercyl == 0)
    907 			return (ERANGE);	/* XXX */
    908 		if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
    909 			return (ERANGE);	/* XXX */
    910 #define datapart	((struct sun_dkpart *)(u_long)SCARG(uap, data))
    911 		datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
    912 		datapart->sdkp_nsectors = pi.part->p_size;
    913 #undef datapart
    914 	    }
    915 
    916 	}
    917 	return (netbsd32_ioctl(l, uap, retval));
    918 }
    919 
    920 /* SunOS fcntl(2) cmds not implemented */
    921 #define SUN_F_RGETLK	10
    922 #define SUN_F_RSETLK	11
    923 #define SUN_F_CNVT	12
    924 #define SUN_F_RSETLKW	13
    925 
    926 /* SunOS flock translation */
    927 struct sunos_flock {
    928 	short	l_type;
    929 	short	l_whence;
    930 	netbsd32_long	l_start;
    931 	netbsd32_long	l_len;
    932 	short	l_pid;
    933 	short	l_xxx;
    934 };
    935 
    936 static void bsd_to_sunos_flock __P((struct flock *, struct sunos_flock *));
    937 static void sunos_to_bsd_flock __P((struct sunos_flock *, struct flock *));
    938 
    939 #define SUNOS_F_RDLCK	1
    940 #define	SUNOS_F_WRLCK	2
    941 #define SUNOS_F_UNLCK	3
    942 
    943 static void
    944 bsd_to_sunos_flock(iflp, oflp)
    945 	struct flock		*iflp;
    946 	struct sunos_flock	*oflp;
    947 {
    948 	switch (iflp->l_type) {
    949 	case F_RDLCK:
    950 		oflp->l_type = SUNOS_F_RDLCK;
    951 		break;
    952 	case F_WRLCK:
    953 		oflp->l_type = SUNOS_F_WRLCK;
    954 		break;
    955 	case F_UNLCK:
    956 		oflp->l_type = SUNOS_F_UNLCK;
    957 		break;
    958 	default:
    959 		oflp->l_type = -1;
    960 		break;
    961 	}
    962 
    963 	oflp->l_whence = (short) iflp->l_whence;
    964 	oflp->l_start = (netbsd32_long) iflp->l_start;
    965 	oflp->l_len = (netbsd32_long) iflp->l_len;
    966 	oflp->l_pid = (short) iflp->l_pid;
    967 	oflp->l_xxx = 0;
    968 }
    969 
    970 
    971 static void
    972 sunos_to_bsd_flock(iflp, oflp)
    973 	struct sunos_flock	*iflp;
    974 	struct flock		*oflp;
    975 {
    976 	switch (iflp->l_type) {
    977 	case SUNOS_F_RDLCK:
    978 		oflp->l_type = F_RDLCK;
    979 		break;
    980 	case SUNOS_F_WRLCK:
    981 		oflp->l_type = F_WRLCK;
    982 		break;
    983 	case SUNOS_F_UNLCK:
    984 		oflp->l_type = F_UNLCK;
    985 		break;
    986 	default:
    987 		oflp->l_type = -1;
    988 		break;
    989 	}
    990 
    991 	oflp->l_whence = iflp->l_whence;
    992 	oflp->l_start = (off_t) iflp->l_start;
    993 	oflp->l_len = (off_t) iflp->l_len;
    994 	oflp->l_pid = (pid_t) iflp->l_pid;
    995 
    996 }
    997 static struct {
    998 	netbsd32_long	sun_flg;
    999 	netbsd32_long	bsd_flg;
   1000 } sunfcntl_flgtab[] = {
   1001 	/* F_[GS]ETFLags that differ: */
   1002 #define SUN_FSETBLK	0x0010
   1003 #define SUN_SHLOCK	0x0080
   1004 #define SUN_EXLOCK	0x0100
   1005 #define SUN_FNBIO	0x1000
   1006 #define SUN_FSYNC	0x2000
   1007 #define SUN_NONBLOCK	0x4000
   1008 #define SUN_FNOCTTY	0x8000
   1009 	{ SUN_NONBLOCK, O_NONBLOCK },
   1010 	{ SUN_FNBIO, O_NONBLOCK },
   1011 	{ SUN_SHLOCK, O_SHLOCK },
   1012 	{ SUN_EXLOCK, O_EXLOCK },
   1013 	{ SUN_FSYNC, O_FSYNC },
   1014 	{ SUN_FSETBLK, 0 },
   1015 	{ SUN_FNOCTTY, 0 }
   1016 };
   1017 
   1018 int
   1019 sunos32_sys_fcntl(l, v, retval)
   1020 	struct lwp *l;
   1021 	void *v;
   1022 	register_t *retval;
   1023 {
   1024 	struct sunos32_sys_fcntl_args /* {
   1025 		syscallarg(int) fd;
   1026 		syscallarg(int) cmd;
   1027 		syscallarg(netbsd32_voidp) arg;
   1028 	} */ *uap = v;
   1029 	struct proc *p = l->l_proc;
   1030 	netbsd32_long flg;
   1031 	int n, ret;
   1032 
   1033 	switch (SCARG(uap, cmd)) {
   1034 	case F_SETFL:
   1035 		flg = (netbsd32_long)SCARG(uap, arg);
   1036 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
   1037 		while (--n >= 0) {
   1038 			if (flg & sunfcntl_flgtab[n].sun_flg) {
   1039 				flg &= ~sunfcntl_flgtab[n].sun_flg;
   1040 				flg |= sunfcntl_flgtab[n].bsd_flg;
   1041 			}
   1042 		}
   1043 		SCARG(uap, arg) = (netbsd32_voidp)flg;
   1044 		break;
   1045 
   1046 	case F_GETLK:
   1047 	case F_SETLK:
   1048 	case F_SETLKW:
   1049 		{
   1050 			int error;
   1051 			struct sunos_flock	 ifl;
   1052 			struct flock		*flp, fl;
   1053 			caddr_t sg = stackgap_init(p, 0);
   1054 			struct sys_fcntl_args		fa;
   1055 
   1056 			SCARG(&fa, fd) = SCARG(uap, fd);
   1057 			SCARG(&fa, cmd) = SCARG(uap, cmd);
   1058 
   1059 			flp = stackgap_alloc(p, &sg, sizeof(struct flock));
   1060 			SCARG(&fa, arg) = (void *) flp;
   1061 
   1062 			error = copyin((caddr_t)(u_long)SCARG(uap, arg), &ifl, sizeof ifl);
   1063 			if (error)
   1064 				return error;
   1065 
   1066 			sunos_to_bsd_flock(&ifl, &fl);
   1067 
   1068 			error = copyout(&fl, flp, sizeof fl);
   1069 			if (error)
   1070 				return error;
   1071 
   1072 			error = sys_fcntl(l, &fa, retval);
   1073 			if (error || SCARG(&fa, cmd) != F_GETLK)
   1074 				return error;
   1075 
   1076 			error = copyin(flp, &fl, sizeof fl);
   1077 			if (error)
   1078 				return error;
   1079 
   1080 			bsd_to_sunos_flock(&fl, &ifl);
   1081 
   1082 			return copyout(&ifl, (caddr_t)(u_long)SCARG(uap, arg), sizeof ifl);
   1083 		}
   1084 		break;
   1085 	case SUN_F_RGETLK:
   1086 	case SUN_F_RSETLK:
   1087 	case SUN_F_CNVT:
   1088 	case SUN_F_RSETLKW:
   1089 		return (EOPNOTSUPP);
   1090 	}
   1091 
   1092 	ret = netbsd32_fcntl(l, uap, retval);
   1093 
   1094 	switch (SCARG(uap, cmd)) {
   1095 	case F_GETFL:
   1096 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
   1097 		while (--n >= 0) {
   1098 			if (ret & sunfcntl_flgtab[n].bsd_flg) {
   1099 				ret &= ~sunfcntl_flgtab[n].bsd_flg;
   1100 				ret |= sunfcntl_flgtab[n].sun_flg;
   1101 			}
   1102 		}
   1103 		break;
   1104 	}
   1105 
   1106 	return (ret);
   1107 }
   1108