Home | History | Annotate | Line # | Download | only in sunos32
sunos32_ioctl.c revision 1.28
      1 /*	$NetBSD: sunos32_ioctl.c,v 1.28 2008/03/21 21:54:59 ad Exp $	*/
      2 /* from: NetBSD: sunos_ioctl.c,v 1.35 2001/02/03 22:20:02 mrg Exp 	*/
      3 
      4 /*
      5  * Copyright (c) 2001 Matthew R. Green
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1993 Markus Wild.
     34  * All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. The name of the author may not be used to endorse or promote products
     42  *    derived from this software without specific prior written permission
     43  *
     44  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     47  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     49  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     51  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     52  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     53  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     54  *
     55  * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
     56  */
     57 
     58 #include <sys/cdefs.h>
     59 __KERNEL_RCSID(0, "$NetBSD: sunos32_ioctl.c,v 1.28 2008/03/21 21:54:59 ad 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 
    433 static int
    434 sunos32_do_ioctl(int fd, int cmd, void *arg, struct lwp *l)
    435 {
    436 	file_t *fp;
    437 	struct vnode *vp;
    438 	int error;
    439 
    440 	if ((fp = fd_getfile(fd)) == NULL)
    441 		return EBADF;
    442 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
    443 		fd_putfile(fd);
    444 		return EBADF;
    445 	}
    446 	error = fp->f_ops->fo_ioctl(fp, cmd, arg);
    447 	if (error == EIO && cmd == TIOCGPGRP) {
    448 		vp = (struct vnode *)fp->f_data;
    449 		if (vp != NULL && vp->v_type == VCHR && major(vp->v_rdev) == 21)
    450 			error = ENOTTY;
    451 	}
    452 	fd_putfile(fd);
    453 	return error;
    454 }
    455 
    456 int
    457 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap, register_t *retval)
    458 {
    459 	/* {
    460 		int	fd;
    461 		netbsd32_u_long	com;
    462 		netbsd32_caddr_t	data;
    463 	} */
    464 	struct netbsd32_ioctl_args bsd_ua;
    465 	int error;
    466 
    467 	SCARG(&bsd_ua, fd) = SCARG(uap, fd);
    468 	SCARG(&bsd_ua, com) = SCARG(uap, com);
    469 	SCARG(&bsd_ua, data) = SCARG(uap, data);
    470 
    471 	switch (SCARG(uap, com)) {
    472 	case _IOR('t', 0, int):
    473 		SCARG(&bsd_ua, com) = TIOCGETD;
    474 		break;
    475 	case _IOW('t', 1, int):
    476 	    {
    477 		int disc;
    478 
    479 		if ((error = copyin(SCARG_P32(uap, data), &disc,
    480 		    sizeof disc)) != 0)
    481 			return error;
    482 
    483 		/* map SunOS NTTYDISC into our termios discipline */
    484 		if (disc == 2)
    485 			disc = 0;
    486 		/* all other disciplines are not supported by NetBSD */
    487 		if (disc)
    488 			return ENXIO;
    489 
    490 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l);
    491 	    }
    492 	case _IOW('t', 101, int):	/* sun SUNOS_TIOCSSOFTCAR */
    493 	    {
    494 		int x;	/* unused */
    495 
    496 		return copyin(SCARG_P32(uap, data), &x, sizeof x);
    497 	    }
    498 	case _IOR('t', 100, int):	/* sun SUNOS_TIOCSSOFTCAR */
    499 	    {
    500 		int x = 0;
    501 
    502 		return copyout(&x, SCARG_P32(uap, data), sizeof x);
    503 	    }
    504 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
    505 	    {
    506 		int on = 1;
    507 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l);
    508 	    }
    509 	case _IOW('t', 37, struct sunos_ttysize):
    510 	    {
    511 		struct winsize ws;
    512 		struct sunos_ttysize ss;
    513 
    514 		if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
    515 			return (error);
    516 
    517 		if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0)
    518 			return error;
    519 
    520 		ws.ws_row = ss.ts_row;
    521 		ws.ws_col = ss.ts_col;
    522 
    523 		return (sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l));
    524 	    }
    525 	case _IOW('t', 38, struct sunos_ttysize):
    526 	    {
    527 		struct winsize ws;
    528 		struct sunos_ttysize ss;
    529 
    530 		if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
    531 			return (error);
    532 
    533 		ss.ts_row = ws.ws_row;
    534 		ss.ts_col = ws.ws_col;
    535 
    536 		return copyout(&ss, SCARG_P32(uap, data), sizeof (ss));
    537 	    }
    538 	case _IOW('t', 130, int):	/* TIOCSETPGRP: posix variant */
    539 		SCARG(&bsd_ua, com) = TIOCSPGRP;
    540 		break;
    541 	case _IOR('t', 131, int):	/* TIOCGETPGRP: posix variant */
    542 	    {
    543 		/*
    544 		 * sigh, must do error translation on pty devices
    545 		 * (see also kern/tty_pty.c)
    546 		 */
    547 		int pgrp;
    548 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp, l);
    549 		if (error)
    550 			return (error);
    551 		return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
    552 	    }
    553 	case _IO('t', 132):
    554 		SCARG(&bsd_ua, com) = TIOCSCTTY;
    555 		break;
    556 	case SUNOS_TCGETA:
    557 	case SUNOS_TCGETS:
    558 	    {
    559 		struct termios bts;
    560 		struct sunos_termios sts;
    561 		struct sunos_termio st;
    562 
    563 		if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0)
    564 			return error;
    565 
    566 		btios2stios (&bts, &sts);
    567 		if (SCARG(uap, com) == SUNOS_TCGETA) {
    568 			stios2stio (&sts, &st);
    569 			return copyout(&st, SCARG_P32(uap, data),
    570 			    sizeof (st));
    571 		} else
    572 			return copyout(&sts, SCARG_P32(uap, data),
    573 			    sizeof (sts));
    574 		/*NOTREACHED*/
    575 	    }
    576 	case SUNOS_TCSETA:
    577 	case SUNOS_TCSETAW:
    578 	case SUNOS_TCSETAF:
    579 	    {
    580 		struct termios bts;
    581 		struct sunos_termios sts;
    582 		struct sunos_termio st;
    583 
    584 		if ((error = copyin(SCARG_P32(uap, data), &st,
    585 		    sizeof (st))) != 0)
    586 			return error;
    587 
    588 		/* get full BSD termios so we don't lose information */
    589 		if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0)
    590 			return error;
    591 
    592 		/*
    593 		 * convert to sun termios, copy in information from
    594 		 * termio, and convert back, then set new values.
    595 		 */
    596 		btios2stios(&bts, &sts);
    597 		stio2stios(&st, &sts);
    598 		stios2btios(&sts, &bts);
    599 
    600 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
    601 		    &bts, l);
    602 	    }
    603 	case SUNOS_TCSETS:
    604 	case SUNOS_TCSETSW:
    605 	case SUNOS_TCSETSF:
    606 	    {
    607 		struct termios bts;
    608 		struct sunos_termios sts;
    609 
    610 		if ((error = copyin(SCARG_P32(uap, data), &sts,
    611 		    sizeof (sts))) != 0)
    612 			return error;
    613 		stios2btios (&sts, &bts);
    614 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
    615 		    &bts, l);
    616 	    }
    617 /*
    618  * Pseudo-tty ioctl translations.
    619  */
    620 	case _IOW('t', 32, int): {	/* TIOCTCNTL */
    621 		int error1, on;
    622 
    623 		error1 = copyin(SCARG_P32(uap, data), &on, sizeof (on));
    624 		if (error1)
    625 			return error1;
    626 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCUCNTL, &on, l);
    627 	}
    628 	case _IOW('t', 33, int): {	/* TIOCSIGNAL */
    629 		int error1, sig;
    630 
    631 		error1 = copyin(SCARG_P32(uap, data), &sig, sizeof (sig));
    632 		if (error1)
    633 			return error1;
    634 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSIG, &sig, l);
    635 	}
    636 
    637 /*
    638  * Socket ioctl translations.
    639  */
    640 #define IFREQ_IN(a) { \
    641 	struct oifreq ifreq; \
    642 	error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
    643 	if (error) \
    644 		return error; \
    645 	return sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l); \
    646 }
    647 #define IFREQ_INOUT(a) { \
    648 	struct oifreq ifreq; \
    649 	error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
    650 	if (error) \
    651 		return error; \
    652 	if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l)) != 0) \
    653 		return error; \
    654 	return copyout(&ifreq, SCARG_P32(uap, data), sizeof (ifreq)); \
    655 }
    656 
    657 	case _IOW('i', 12, struct oifreq):
    658 		/* SIOCSIFADDR */
    659 		break;
    660 
    661 	case _IOWR('i', 13, struct oifreq):
    662 		IFREQ_INOUT(OOSIOCGIFADDR);
    663 
    664 	case _IOW('i', 14, struct oifreq):
    665 		/* SIOCSIFDSTADDR */
    666 		break;
    667 
    668 	case _IOWR('i', 15, struct oifreq):
    669 		IFREQ_INOUT(OOSIOCGIFDSTADDR);
    670 
    671 	case _IOW('i', 16, struct oifreq):
    672 		/* SIOCSIFFLAGS */
    673 		break;
    674 
    675 	case _IOWR('i', 17, struct oifreq):
    676 		/* SIOCGIFFLAGS */
    677 		break;
    678 
    679 	case _IOW('i', 21, struct oifreq):
    680 		IFREQ_IN(SIOCSIFMTU);
    681 
    682 	case _IOWR('i', 22, struct oifreq):
    683 		IFREQ_INOUT(SIOCGIFMTU);
    684 
    685 	case _IOWR('i', 23, struct oifreq):
    686 		IFREQ_INOUT(SIOCGIFBRDADDR);
    687 
    688 	case _IOW('i', 24, struct oifreq):
    689 		IFREQ_IN(SIOCSIFBRDADDR);
    690 
    691 	case _IOWR('i', 25, struct oifreq):
    692 		IFREQ_INOUT(OOSIOCGIFNETMASK);
    693 
    694 	case _IOW('i', 26, struct oifreq):
    695 		IFREQ_IN(SIOCSIFNETMASK);
    696 
    697 	case _IOWR('i', 27, struct oifreq):
    698 		IFREQ_INOUT(SIOCGIFMETRIC);
    699 
    700 	case _IOWR('i', 28, struct oifreq):
    701 		IFREQ_IN(SIOCSIFMETRIC);
    702 
    703 	case _IOW('i', 30, struct arpreq):
    704 		/* SIOCSARP */
    705 		break;
    706 
    707 	case _IOWR('i', 31, struct arpreq):
    708 		/* SIOCGARP */
    709 		break;
    710 
    711 	case _IOW('i', 32, struct arpreq):
    712 		/* SIOCDARP */
    713 		break;
    714 
    715 	case _IOW('i', 18, struct oifreq):	/* SIOCSIFMEM */
    716 	case _IOWR('i', 19, struct oifreq):	/* SIOCGIFMEM */
    717 	case _IOW('i', 40, struct oifreq):	/* SIOCUPPER */
    718 	case _IOW('i', 41, struct oifreq):	/* SIOCLOWER */
    719 	case _IOW('i', 44, struct oifreq):	/* SIOCSETSYNC */
    720 	case _IOWR('i', 45, struct oifreq):	/* SIOCGETSYNC */
    721 	case _IOWR('i', 46, struct oifreq):	/* SIOCSDSTATS */
    722 	case _IOWR('i', 47, struct oifreq):	/* SIOCSESTATS */
    723 	case _IOW('i', 48, int):		/* SIOCSPROMISC */
    724 	case _IOW('i', 49, struct oifreq):	/* SIOCADDMULTI */
    725 	case _IOW('i', 50, struct oifreq):	/* SIOCDELMULTI */
    726 		return EOPNOTSUPP;
    727 
    728 	case _IOWR('i', 20, struct oifconf):	/* SIOCGIFCONF */
    729 	    {
    730 		struct oifconf ifcf;
    731 
    732 		/*
    733 		 * XXX: two more problems
    734 		 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
    735 		 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
    736 		 */
    737 		error = copyin(SCARG_P32(uap, data), &ifcf,
    738 		    sizeof (ifcf));
    739 		if (error)
    740 			return error;
    741 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), OOSIOCGIFCONF, &ifcf, l);
    742 		if (error)
    743 			return error;
    744 		return copyout(&ifcf, SCARG_P32(uap, data),
    745 		    sizeof (ifcf));
    746 	    }
    747 
    748 /*
    749  * Audio ioctl translations.
    750  */
    751 	case _IOR('A', 1, struct sunos_audio_info):	/* AUDIO_GETINFO */
    752 	sunos_au_getinfo:
    753 	    {
    754 		struct audio_info aui;
    755 		struct sunos_audio_info sunos_aui;
    756 
    757 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_GETINFO, &aui, l);
    758 		if (error)
    759 			return error;
    760 
    761 		sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
    762 		sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
    763 
    764 		/* `avail_ports' is `seek' in BSD */
    765 		sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
    766 		sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
    767 
    768 		sunos_aui.play.waiting = 0;
    769 		sunos_aui.record.waiting = 0;
    770 		sunos_aui.play.eof = 0;
    771 		sunos_aui.record.eof = 0;
    772 		sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
    773 		/*XXXsunos_aui.output_muted = 0;*/
    774 		/*XXX*/sunos_aui.reserved[0] = 0;
    775 		/*XXX*/sunos_aui.reserved[1] = 0;
    776 		/*XXX*/sunos_aui.reserved[2] = 0;
    777 		/*XXX*/sunos_aui.reserved[3] = 0;
    778 
    779 		return copyout(&sunos_aui, SCARG_P32(uap, data),
    780 				sizeof (sunos_aui));
    781 	    }
    782 
    783 	case _IOWR('A', 2, struct sunos_audio_info):	/* AUDIO_SETINFO */
    784 	    {
    785 		struct audio_info aui;
    786 		struct sunos_audio_info sunos_aui;
    787 
    788 		error = copyin(SCARG_P32(uap, data), &sunos_aui,
    789 		    sizeof (sunos_aui));
    790 		if (error)
    791 			return error;
    792 
    793 		aui.play = *(struct audio_prinfo *)&sunos_aui.play;
    794 		aui.record = *(struct audio_prinfo *)&sunos_aui.record;
    795 		/* aui.__spare = sunos_aui.monitor_gain; */
    796 		aui.blocksize = ~0;
    797 		aui.hiwat = ~0;
    798 		aui.lowat = ~0;
    799 		/* XXX somebody check this please. - is: aui.backlog = ~0; */
    800 		aui.mode = ~0;
    801 		/*
    802 		 * The bsd driver does not distinguish between paused and
    803 		 * active. (In the sun driver, not active means samples are
    804 		 * not output at all, but paused means the last streams buffer
    805 		 * is drained and then output stops.)  If either are 0, then
    806 		 * when stop output. Otherwise, if either are non-zero,
    807 		 * we resume.
    808 		 */
    809 		if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
    810 			aui.play.pause = 0;
    811 		else if (sunos_aui.play.pause != (u_char)~0 ||
    812 			 sunos_aui.play.active != (u_char)~0)
    813 			aui.play.pause = 1;
    814 		if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
    815 			aui.record.pause = 0;
    816 		else if (sunos_aui.record.pause != (u_char)~0 ||
    817 			 sunos_aui.record.active != (u_char)~0)
    818 			aui.record.pause = 1;
    819 
    820 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_SETINFO, &aui, l);
    821 		if (error)
    822 			return error;
    823 		/* Return new state */
    824 		goto sunos_au_getinfo;
    825 	    }
    826 	case _IO('A', 3):	/* AUDIO_DRAIN */
    827 		return sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_DRAIN, NULL, l);
    828 	case _IOR('A', 4, int):	/* AUDIO_GETDEV */
    829 	    {
    830 		int devtype = SUNOS_AUDIO_DEV_AMD;
    831 		return copyout(&devtype, SCARG_P32(uap, data),
    832 				sizeof (devtype));
    833 	    }
    834 
    835 /*
    836  * Selected streams ioctls.
    837  */
    838 #define SUNOS_S_FLUSHR		1
    839 #define SUNOS_S_FLUSHW		2
    840 #define SUNOS_S_FLUSHRW		3
    841 
    842 #define SUNOS_S_INPUT		1
    843 #define SUNOS_S_HIPRI		2
    844 #define SUNOS_S_OUTPUT		4
    845 #define SUNOS_S_MSG		8
    846 
    847 	case _IO('S', 5):	/* I_FLUSH */
    848 	    {
    849 		int tmp = 0;
    850 		switch ((intptr_t)SCARG_P32(uap, data)) {
    851 		case SUNOS_S_FLUSHR:	tmp = FREAD;
    852 		case SUNOS_S_FLUSHW:	tmp = FWRITE;
    853 		case SUNOS_S_FLUSHRW:	tmp = FREAD|FWRITE;
    854 		}
    855                 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCFLUSH, &tmp, l);
    856 	    }
    857 	case _IO('S', 9):	/* I_SETSIG */
    858 	    {
    859 		int on = 1;
    860 		if (((intptr_t)SCARG_P32(uap, data) &
    861 			(SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
    862 		    SUNOS_S_HIPRI)
    863 			return EOPNOTSUPP;
    864                 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), FIOASYNC, &on, l);
    865 	    }
    866 	/*
    867 	 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
    868 	 * (which was from the old sparc/scsi/sun_disklabel.c), and
    869 	 * modified to suite.
    870 	 */
    871 	case DKIOCGGEOM:
    872             {
    873 		struct disklabel dl;
    874 
    875 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGDINFO, &dl, l);
    876 		if (error)
    877 			return (error);
    878 
    879 #define datageom	((struct sun_dkgeom *)SCARG_P32(uap, data))
    880 		/* XXX can't do memset() on a user address (dsl) */
    881 		memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
    882 
    883 		datageom->sdkc_ncylinders = dl.d_ncylinders;
    884 		datageom->sdkc_acylinders = dl.d_acylinders;
    885 		datageom->sdkc_ntracks = dl.d_ntracks;
    886 		datageom->sdkc_nsectors = dl.d_nsectors;
    887 		datageom->sdkc_interleave = dl.d_interleave;
    888 		datageom->sdkc_sparespercyl = dl.d_sparespercyl;
    889 		datageom->sdkc_rpm = dl.d_rpm;
    890 		datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
    891 #undef datageom
    892 		break;
    893 	    }
    894 
    895 	case DKIOCINFO:
    896 		/* Homey don't do DKIOCINFO */
    897 		/* XXX can't do memset() on a user address (dsl) */
    898 		memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
    899 		break;
    900 
    901 	case DKIOCGPART:
    902             {
    903 		struct partinfo pi;
    904 
    905 		error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGPART, &pi, l);
    906 		if (error)
    907 			return (error);
    908 
    909 		if (pi.disklab->d_secpercyl == 0)
    910 			return (ERANGE);	/* XXX */
    911 		if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
    912 			return (ERANGE);	/* XXX */
    913 		/* XXX can't do direct writes to a user address (dsl) */
    914 #define datapart	((struct sun_dkpart *)SCARG_P32(uap, data))
    915 		datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
    916 		datapart->sdkp_nsectors = pi.part->p_size;
    917 #undef datapart
    918 	    }
    919 
    920 	}
    921 	return (netbsd32_ioctl(l, &bsd_ua, retval));
    922 }
    923 
    924 /* SunOS fcntl(2) cmds not implemented */
    925 #define SUN_F_RGETLK	10
    926 #define SUN_F_RSETLK	11
    927 #define SUN_F_CNVT	12
    928 #define SUN_F_RSETLKW	13
    929 
    930 /* SunOS flock translation */
    931 struct sunos_flock {
    932 	short	l_type;
    933 	short	l_whence;
    934 	netbsd32_long	l_start;
    935 	netbsd32_long	l_len;
    936 	short	l_pid;
    937 	short	l_xxx;
    938 };
    939 
    940 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
    941 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
    942 
    943 #define SUNOS_F_RDLCK	1
    944 #define	SUNOS_F_WRLCK	2
    945 #define SUNOS_F_UNLCK	3
    946 
    947 static void
    948 bsd_to_sunos_flock(struct flock *iflp, 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(struct sunos_flock *iflp, 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(struct lwp *l, const struct sunos32_sys_fcntl_args *uap, register_t *retval)
   1020 {
   1021 	/* {
   1022 		syscallarg(int) fd;
   1023 		syscallarg(int) cmd;
   1024 		syscallarg(netbsd32_voidp) arg;
   1025 	} */
   1026 	struct sys_fcntl_args bsd_ua;
   1027 	uintptr_t flg;
   1028 	int n, ret;
   1029 
   1030 	SCARG(&bsd_ua, fd) = SCARG(uap, fd);
   1031 	SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
   1032 	SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
   1033 
   1034 	switch (SCARG(uap, cmd)) {
   1035 	case F_SETFL:
   1036 		flg = (intptr_t)SCARG_P32(uap, arg);
   1037 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
   1038 		while (--n >= 0) {
   1039 			if (flg & sunfcntl_flgtab[n].sun_flg) {
   1040 				flg &= ~sunfcntl_flgtab[n].sun_flg;
   1041 				flg |= sunfcntl_flgtab[n].bsd_flg;
   1042 			}
   1043 		}
   1044 		SCARG(&bsd_ua, arg) = (void *)flg;
   1045 		break;
   1046 
   1047 	case F_GETLK:
   1048 	case F_SETLK:
   1049 	case F_SETLKW:
   1050 		{
   1051 			int error;
   1052 			struct sunos_flock	ifl;
   1053 			struct flock		fl;
   1054 
   1055 			error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
   1056 			if (error)
   1057 				return error;
   1058 			sunos_to_bsd_flock(&ifl, &fl);
   1059 
   1060 			error = do_fcntl_lock(SCARG(uap, fd), SCARG(uap, cmd), &fl);
   1061 			if (error || SCARG(uap, cmd) != F_GETLK)
   1062 				return error;
   1063 
   1064 			bsd_to_sunos_flock(&fl, &ifl);
   1065 			return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
   1066 		}
   1067 		break;
   1068 	case SUN_F_RGETLK:
   1069 	case SUN_F_RSETLK:
   1070 	case SUN_F_CNVT:
   1071 	case SUN_F_RSETLKW:
   1072 		return (EOPNOTSUPP);
   1073 	}
   1074 
   1075 	ret = sys_fcntl(l, &bsd_ua, retval);
   1076 	if (ret != 0)
   1077 		return ret;
   1078 
   1079 	switch (SCARG(uap, cmd)) {
   1080 	case F_GETFL:
   1081 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
   1082 		ret = *retval;
   1083 		while (--n >= 0) {
   1084 			if (ret & sunfcntl_flgtab[n].bsd_flg) {
   1085 				ret &= ~sunfcntl_flgtab[n].bsd_flg;
   1086 				ret |= sunfcntl_flgtab[n].sun_flg;
   1087 			}
   1088 		}
   1089 		*retval = ret;
   1090 		break;
   1091 	}
   1092 
   1093 	return 0;
   1094 }
   1095