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