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