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