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