Home | History | Annotate | Line # | Download | only in sunos
sunos_ioctl.c revision 1.9
      1 /*
      2  * Copyright (c) 1993 Markus Wild.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. The name of the author may not be used to endorse or promote products
     11  *    derived from this software without specific prior written permission
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  *
     24  * loosely from: Header: sun_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
     25  * $Id: sunos_ioctl.c,v 1.9 1994/04/26 19:52:29 pk Exp $
     26  */
     27 
     28 #include <sys/param.h>
     29 #include <sys/proc.h>
     30 #include <sys/file.h>
     31 #include <sys/filedesc.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/termios.h>
     34 #include <sys/tty.h>
     35 #include <sys/socket.h>
     36 #include <sys/ioctl.h>
     37 #include <net/if.h>
     38 
     39 /*
     40  * SunOS ioctl calls.
     41  * This file is something of a hodge-podge.
     42  * Support gets added as things turn up....
     43  */
     44 
     45 struct sun_ttysize {
     46 	int	ts_row;
     47 	int	ts_col;
     48 };
     49 
     50 struct sun_termio {
     51 	u_short	c_iflag;
     52 	u_short	c_oflag;
     53 	u_short	c_cflag;
     54 	u_short	c_lflag;
     55 	char	c_line;
     56 	unsigned char c_cc[8];
     57 };
     58 #define SUN_TCGETA	_IOR('T', 1, struct sun_termio)
     59 #define SUN_TCSETA	_IOW('T', 2, struct sun_termio)
     60 #define SUN_TCSETAW	_IOW('T', 3, struct sun_termio)
     61 #define SUN_TCSETAF	_IOW('T', 4, struct sun_termio)
     62 #define SUN_TCSBRK	_IO('T', 5)
     63 
     64 struct sun_termios {
     65 	u_long	c_iflag;
     66 	u_long	c_oflag;
     67 	u_long	c_cflag;
     68 	u_long	c_lflag;
     69 	char	c_line;
     70 	u_char	c_cc[17];
     71 };
     72 #define SUN_TCXONC	_IO('T', 6)
     73 #define SUN_TCFLSH	_IO('T', 7)
     74 #define SUN_TCGETS	_IOR('T', 8, struct sun_termios)
     75 #define SUN_TCSETS	_IOW('T', 9, struct sun_termios)
     76 #define SUN_TCSETSW	_IOW('T', 10, struct sun_termios)
     77 #define SUN_TCSETSF	_IOW('T', 11, struct sun_termios)
     78 #define SUN_TCSNDBRK	_IO('T', 12)
     79 #define SUN_TCDRAIN	_IO('T', 13)
     80 
     81 static struct speedtab sptab[] = {
     82 	{ 0, 0 },
     83 	{ 50, 1 },
     84 	{ 75, 2 },
     85 	{ 110, 3 },
     86 	{ 134, 4 },
     87 	{ 135, 4 },
     88 	{ 150, 5 },
     89 	{ 200, 6 },
     90 	{ 300, 7 },
     91 	{ 600, 8 },
     92 	{ 1200, 9 },
     93 	{ 1800, 10 },
     94 	{ 2400, 11 },
     95 	{ 4800, 12 },
     96 	{ 9600, 13 },
     97 	{ 19200, 14 },
     98 	{ 38400, 15 },
     99 	{ -1, -1 }
    100 };
    101 
    102 static u_long s2btab[] = {
    103 	0,
    104 	50,
    105 	75,
    106 	110,
    107 	134,
    108 	150,
    109 	200,
    110 	300,
    111 	600,
    112 	1200,
    113 	1800,
    114 	2400,
    115 	4800,
    116 	9600,
    117 	19200,
    118 	38400,
    119 };
    120 
    121 /*
    122  * these two conversion functions have mostly been done
    123  * with some perl cut&paste, then handedited to comment
    124  * out what doesn't exist under NetBSD.
    125  * A note from Markus's code:
    126  *	(l & BITMASK1) / BITMASK1 * BITMASK2  is translated
    127  *	optimally by gcc m68k, much better than any ?: stuff.
    128  *	Code may vary with different architectures of course.
    129  *
    130  * I don't know what optimizer you used, but seeing divu's and
    131  * bfextu's in the m68k assembly output did not encourage me...
    132  * as well, gcc on the sparc definately generates much better
    133  * code with ?:.
    134  */
    135 
    136 static void
    137 stios2btios(st, bt)
    138 	struct sun_termios *st;
    139 	struct termios *bt;
    140 {
    141 	register u_long l, r;
    142 
    143 	l = st->c_iflag;
    144 	r = 	((l & 0x00000001) ? IGNBRK	: 0);
    145 	r |=	((l & 0x00000002) ? BRKINT	: 0);
    146 	r |=	((l & 0x00000004) ? IGNPAR	: 0);
    147 	r |=	((l & 0x00000008) ? PARMRK	: 0);
    148 	r |=	((l & 0x00000010) ? INPCK	: 0);
    149 	r |=	((l & 0x00000020) ? ISTRIP	: 0);
    150 	r |= 	((l & 0x00000040) ? INLCR	: 0);
    151 	r |=	((l & 0x00000080) ? IGNCR	: 0);
    152 	r |=	((l & 0x00000100) ? ICRNL	: 0);
    153 	/*	((l & 0x00000200) ? IUCLC	: 0) */
    154 	r |=	((l & 0x00000400) ? IXON	: 0);
    155 	r |=	((l & 0x00000800) ? IXANY	: 0);
    156 	r |=	((l & 0x00001000) ? IXOFF	: 0);
    157 	r |=	((l & 0x00002000) ? IMAXBEL	: 0);
    158 	bt->c_iflag = r;
    159 
    160 	l = st->c_oflag;
    161 	r = 	((l & 0x00000001) ? OPOST	: 0);
    162 	/*	((l & 0x00000002) ? OLCUC	: 0) */
    163 	r |=	((l & 0x00000004) ? ONLCR	: 0);
    164 	/*	((l & 0x00000008) ? OCRNL	: 0) */
    165 	/*	((l & 0x00000010) ? ONOCR	: 0) */
    166 	/*	((l & 0x00000020) ? ONLRET	: 0) */
    167 	/*	((l & 0x00000040) ? OFILL	: 0) */
    168 	/*	((l & 0x00000080) ? OFDEL	: 0) */
    169 	/*	((l & 0x00000100) ? NLDLY	: 0) */
    170 	/*	((l & 0x00000100) ? NL1		: 0) */
    171 	/*	((l & 0x00000600) ? CRDLY	: 0) */
    172 	/*	((l & 0x00000200) ? CR1		: 0) */
    173 	/*	((l & 0x00000400) ? CR2		: 0) */
    174 	/*	((l & 0x00000600) ? CR3		: 0) */
    175 	/*	((l & 0x00001800) ? TABDLY	: 0) */
    176 	/*	((l & 0x00000800) ? TAB1	: 0) */
    177 	/*	((l & 0x00001000) ? TAB2	: 0) */
    178 	r |=	((l & 0x00001800) ? OXTABS	: 0);
    179 	/*	((l & 0x00002000) ? BSDLY	: 0) */
    180 	/*	((l & 0x00002000) ? BS1		: 0) */
    181 	/*	((l & 0x00004000) ? VTDLY	: 0) */
    182 	/*	((l & 0x00004000) ? VT1		: 0) */
    183 	/*	((l & 0x00008000) ? FFDLY	: 0) */
    184 	/*	((l & 0x00008000) ? FF1		: 0) */
    185 	/*	((l & 0x00010000) ? PAGEOUT	: 0) */
    186 	/*	((l & 0x00020000) ? WRAP	: 0) */
    187 	bt->c_oflag = r;
    188 
    189 	l = st->c_cflag;
    190 	r = 	((l & 0x00000010) ? CS6		: 0);
    191 	r |=	((l & 0x00000020) ? CS7		: 0);
    192 	r |=	((l & 0x00000030) ? CS8		: 0);
    193 	r |=	((l & 0x00000040) ? CSTOPB	: 0);
    194 	r |=	((l & 0x00000080) ? CREAD	: 0);
    195 	r |= 	((l & 0x00000100) ? PARENB	: 0);
    196 	r |=	((l & 0x00000200) ? PARODD	: 0);
    197 	r |=	((l & 0x00000400) ? HUPCL	: 0);
    198 	r |=	((l & 0x00000800) ? CLOCAL	: 0);
    199 	/*	((l & 0x00001000) ? LOBLK	: 0) */
    200 	r |=	((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
    201 	bt->c_cflag = r;
    202 
    203 	bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
    204 
    205 	l = st->c_lflag;
    206 	r = 	((l & 0x00000001) ? ISIG	: 0);
    207 	r |=	((l & 0x00000002) ? ICANON	: 0);
    208 	/*	((l & 0x00000004) ? XCASE	: 0) */
    209 	r |=	((l & 0x00000008) ? ECHO	: 0);
    210 	r |=	((l & 0x00000010) ? ECHOE	: 0);
    211 	r |=	((l & 0x00000020) ? ECHOK	: 0);
    212 	r |=	((l & 0x00000040) ? ECHONL	: 0);
    213 	r |= 	((l & 0x00000080) ? NOFLSH	: 0);
    214 	r |=	((l & 0x00000100) ? TOSTOP	: 0);
    215 	r |=	((l & 0x00000200) ? ECHOCTL	: 0);
    216 	r |=	((l & 0x00000400) ? ECHOPRT	: 0);
    217 	r |=	((l & 0x00000800) ? ECHOKE	: 0);
    218 	/*	((l & 0x00001000) ? DEFECHO	: 0) */
    219 	r |=	((l & 0x00002000) ? FLUSHO	: 0);
    220 	r |=	((l & 0x00004000) ? PENDIN	: 0);
    221 	bt->c_lflag = r;
    222 
    223 	bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
    224 	bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
    225 	bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
    226 	bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
    227 	bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
    228 	bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
    229 	bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
    230     /*	bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
    231 	bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
    232 	bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
    233 	bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
    234 	bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
    235 	bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
    236 	bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
    237 	bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
    238 	bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
    239 	bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
    240 }
    241 
    242 
    243 static void
    244 btios2stios(bt, st)
    245 	struct termios *bt;
    246 	struct sun_termios *st;
    247 {
    248 	register u_long l, r;
    249 
    250 	l = bt->c_iflag;
    251 	r = 	((l &  IGNBRK) ? 0x00000001	: 0);
    252 	r |=	((l &  BRKINT) ? 0x00000002	: 0);
    253 	r |=	((l &  IGNPAR) ? 0x00000004	: 0);
    254 	r |=	((l &  PARMRK) ? 0x00000008	: 0);
    255 	r |=	((l &   INPCK) ? 0x00000010	: 0);
    256 	r |=	((l &  ISTRIP) ? 0x00000020	: 0);
    257 	r |=	((l &   INLCR) ? 0x00000040	: 0);
    258 	r |=	((l &   IGNCR) ? 0x00000080	: 0);
    259 	r |=	((l &   ICRNL) ? 0x00000100	: 0);
    260 	/*	((l &   IUCLC) ? 0x00000200	: 0) */
    261 	r |=	((l &    IXON) ? 0x00000400	: 0);
    262 	r |=	((l &   IXANY) ? 0x00000800	: 0);
    263 	r |=	((l &   IXOFF) ? 0x00001000	: 0);
    264 	r |=	((l & IMAXBEL) ? 0x00002000	: 0);
    265 	st->c_iflag = r;
    266 
    267 	l = bt->c_oflag;
    268 	r =	((l &   OPOST) ? 0x00000001	: 0);
    269 	/*	((l &   OLCUC) ? 0x00000002	: 0) */
    270 	r |=	((l &   ONLCR) ? 0x00000004	: 0);
    271 	/*	((l &   OCRNL) ? 0x00000008	: 0) */
    272 	/*	((l &   ONOCR) ? 0x00000010	: 0) */
    273 	/*	((l &  ONLRET) ? 0x00000020	: 0) */
    274 	/*	((l &   OFILL) ? 0x00000040	: 0) */
    275 	/*	((l &   OFDEL) ? 0x00000080	: 0) */
    276 	/*	((l &   NLDLY) ? 0x00000100	: 0) */
    277 	/*	((l &     NL1) ? 0x00000100	: 0) */
    278 	/*	((l &   CRDLY) ? 0x00000600	: 0) */
    279 	/*	((l &     CR1) ? 0x00000200	: 0) */
    280 	/*	((l &     CR2) ? 0x00000400	: 0) */
    281 	/*	((l &     CR3) ? 0x00000600	: 0) */
    282 	/*	((l &  TABDLY) ? 0x00001800	: 0) */
    283 	/*	((l &    TAB1) ? 0x00000800	: 0) */
    284 	/*	((l &    TAB2) ? 0x00001000	: 0) */
    285 	r |=	((l &  OXTABS) ? 0x00001800	: 0);
    286 	/*	((l &   BSDLY) ? 0x00002000	: 0) */
    287 	/*	((l &     BS1) ? 0x00002000	: 0) */
    288 	/*	((l &   VTDLY) ? 0x00004000	: 0) */
    289 	/*	((l &     VT1) ? 0x00004000	: 0) */
    290 	/*	((l &   FFDLY) ? 0x00008000	: 0) */
    291 	/*	((l &     FF1) ? 0x00008000	: 0) */
    292 	/*	((l & PAGEOUT) ? 0x00010000	: 0) */
    293 	/*	((l &    WRAP) ? 0x00020000	: 0) */
    294 	st->c_oflag = r;
    295 
    296 	l = bt->c_cflag;
    297 	r = 	((l &     CS6) ? 0x00000010	: 0);
    298 	r |=	((l &     CS7) ? 0x00000020	: 0);
    299 	r |=	((l &     CS8) ? 0x00000030	: 0);
    300 	r |=	((l &  CSTOPB) ? 0x00000040	: 0);
    301 	r |=	((l &   CREAD) ? 0x00000080	: 0);
    302 	r |=	((l &  PARENB) ? 0x00000100	: 0);
    303 	r |=	((l &  PARODD) ? 0x00000200	: 0);
    304 	r |=	((l &   HUPCL) ? 0x00000400	: 0);
    305 	r |=	((l &  CLOCAL) ? 0x00000800	: 0);
    306 	/*	((l &   LOBLK) ? 0x00001000	: 0) */
    307 	r |=	((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
    308 	st->c_cflag = r;
    309 
    310 	l = bt->c_lflag;
    311 	r =	((l &    ISIG) ? 0x00000001	: 0);
    312 	r |=	((l &  ICANON) ? 0x00000002	: 0);
    313 	/*	((l &   XCASE) ? 0x00000004	: 0) */
    314 	r |=	((l &    ECHO) ? 0x00000008	: 0);
    315 	r |=	((l &   ECHOE) ? 0x00000010	: 0);
    316 	r |=	((l &   ECHOK) ? 0x00000020	: 0);
    317 	r |=	((l &  ECHONL) ? 0x00000040	: 0);
    318 	r |=	((l &  NOFLSH) ? 0x00000080	: 0);
    319 	r |=	((l &  TOSTOP) ? 0x00000100	: 0);
    320 	r |=	((l & ECHOCTL) ? 0x00000200	: 0);
    321 	r |=	((l & ECHOPRT) ? 0x00000400	: 0);
    322 	r |=	((l &  ECHOKE) ? 0x00000800	: 0);
    323 	/*	((l & DEFECHO) ? 0x00001000	: 0) */
    324 	r |=	((l &  FLUSHO) ? 0x00002000	: 0);
    325 	r |=	((l &  PENDIN) ? 0x00004000	: 0);
    326 	st->c_lflag = r;
    327 
    328 	l = ttspeedtab(bt->c_ospeed, sptab);
    329 	if (l >= 0)
    330 		st->c_cflag |= l;
    331 
    332 	st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
    333 	st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
    334 	st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
    335 	st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
    336 	st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
    337 	st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
    338 	st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
    339 	st->c_cc[7] = 0;
    340 		/*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
    341 	st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
    342 	st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
    343 	st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
    344 	st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
    345 	st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
    346 	st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
    347 	st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
    348 	st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
    349 	st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
    350 
    351 	st->c_line = 0;
    352 }
    353 
    354 static void
    355 stios2stio(ts, t)
    356 	struct sun_termios *ts;
    357 	struct sun_termio *t;
    358 {
    359 	t->c_iflag = ts->c_iflag;
    360 	t->c_oflag = ts->c_oflag;
    361 	t->c_cflag = ts->c_cflag;
    362 	t->c_lflag = ts->c_lflag;
    363 	t->c_line  = ts->c_line;
    364 	bcopy(ts->c_cc, t->c_cc, 8);
    365 }
    366 
    367 static void
    368 stio2stios(t, ts)
    369 	struct sun_termio *t;
    370 	struct sun_termios *ts;
    371 {
    372 	ts->c_iflag = t->c_iflag;
    373 	ts->c_oflag = t->c_oflag;
    374 	ts->c_cflag = t->c_cflag;
    375 	ts->c_lflag = t->c_lflag;
    376 	ts->c_line  = t->c_line;
    377 	bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
    378 }
    379 
    380 struct sun_ioctl_args {
    381 	int	fd;
    382 	int	cmd;
    383 	caddr_t	data;
    384 };
    385 
    386 int
    387 sun_ioctl(p, uap, retval)
    388 	register struct proc *p;
    389 	register struct sun_ioctl_args *uap;
    390 	int *retval;
    391 {
    392 	register struct filedesc *fdp = p->p_fd;
    393 	register struct file *fp;
    394 	register int (*ctl)();
    395 	int error;
    396 
    397 	if ( (unsigned)uap->fd >= fdp->fd_nfiles ||
    398 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
    399 		return EBADF;
    400 
    401 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
    402 		return EBADF;
    403 
    404 	ctl = fp->f_ops->fo_ioctl;
    405 
    406 	switch (uap->cmd) {
    407 	case _IOR('t', 0, int):
    408 		uap->cmd = TIOCGETD;
    409 		break;
    410 	case _IOW('t', 1, int):
    411 	    {
    412 		int disc;
    413 
    414 		if ((error = copyin(uap->data, (caddr_t)&disc,
    415 		    sizeof disc)) != 0)
    416 			return error;
    417 
    418 		/* map SunOS NTTYDISC into our termios discipline */
    419 		if (disc == 2)
    420 			disc = 0;
    421 		/* all other disciplines are not supported by NetBSD */
    422 		if (disc)
    423 			return ENXIO;
    424 
    425 		return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
    426 	    }
    427 	case _IOW('t', 101, int):	/* sun SUN_TIOCSSOFTCAR */
    428 	    {
    429 		int x;	/* unused */
    430 
    431 		return copyin((caddr_t)&x, uap->data, sizeof x);
    432 	    }
    433 	case _IOR('t', 100, int):	/* sun SUN_TIOCSSOFTCAR */
    434 	    {
    435 		int x = 0;
    436 
    437 		return copyout((caddr_t)&x, uap->data, sizeof x);
    438 	    }
    439 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
    440 	    {
    441 		int on = 1;
    442 		return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
    443 	    }
    444 	case _IOW('t', 37, struct sun_ttysize):
    445 	    {
    446 		struct winsize ws;
    447 		struct sun_ttysize ss;
    448 
    449 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
    450 			return (error);
    451 
    452 		if ((error = copyin (uap->data, &ss, sizeof (ss))) != 0)
    453 			return error;
    454 
    455 		ws.ws_row = ss.ts_row;
    456 		ws.ws_col = ss.ts_col;
    457 
    458 		return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
    459 	    }
    460 	case _IOW('t', 38, struct sun_ttysize):
    461 	    {
    462 		struct winsize ws;
    463 		struct sun_ttysize ss;
    464 
    465 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
    466 			return (error);
    467 
    468 		ss.ts_row = ws.ws_row;
    469 		ss.ts_col = ws.ws_col;
    470 
    471 		return copyout ((caddr_t)&ss, uap->data, sizeof (ss));
    472 	    }
    473 	case _IOW('t', 130, int):
    474 		uap->cmd = TIOCSPGRP;
    475 		break;
    476 	case _IOR('t', 131, int):
    477 		uap->cmd = TIOCGPGRP;
    478 		break;
    479 	case _IO('t', 132):
    480 		uap->cmd = TIOCSCTTY;
    481 		break;
    482 	case SUN_TCGETA:
    483 	case SUN_TCGETS:
    484 	    {
    485 		struct termios bts;
    486 		struct sun_termios sts;
    487 		struct sun_termio st;
    488 
    489 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
    490 			return error;
    491 
    492 		btios2stios (&bts, &sts);
    493 		if (uap->cmd == SUN_TCGETA) {
    494 			stios2stio (&sts, &st);
    495 			return copyout((caddr_t)&st, uap->data, sizeof (st));
    496 		} else
    497 			return copyout((caddr_t)&sts, uap->data, sizeof (sts));
    498 		/*NOTREACHED*/
    499 	    }
    500 	case SUN_TCSETA:
    501 	case SUN_TCSETAW:
    502 	case SUN_TCSETAF:
    503 	    {
    504 		struct termios bts;
    505 		struct sun_termios sts;
    506 		struct sun_termio st;
    507 
    508 		if ((error = copyin(uap->data, (caddr_t)&st,
    509 		    sizeof (st))) != 0)
    510 			return error;
    511 
    512 		/* get full BSD termios so we don't lose information */
    513 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
    514 			return error;
    515 
    516 		/*
    517 		 * convert to sun termios, copy in information from
    518 		 * termio, and convert back, then set new values.
    519 		 */
    520 		btios2stios(&bts, &sts);
    521 		stio2stios(&st, &sts);
    522 		stios2btios(&sts, &bts);
    523 
    524 		return (*ctl)(fp, uap->cmd - SUN_TCSETA + TIOCSETA,
    525 		    (caddr_t)&bts, p);
    526 	    }
    527 	case SUN_TCSETS:
    528 	case SUN_TCSETSW:
    529 	case SUN_TCSETSF:
    530 	    {
    531 		struct termios bts;
    532 		struct sun_termios sts;
    533 
    534 		if ((error = copyin (uap->data, (caddr_t)&sts,
    535 		    sizeof (sts))) != 0)
    536 			return error;
    537 		stios2btios (&sts, &bts);
    538 		return (*ctl)(fp, uap->cmd - SUN_TCSETS + TIOCSETA,
    539 		    (caddr_t)&bts, p);
    540 	    }
    541 /*
    542  * Pseudo-tty ioctl translations.
    543  */
    544 	case _IOW('t', 32, int): {	/* TIOCTCNTL */
    545 		int error, on;
    546 
    547 		if (error = copyin (uap->data, (caddr_t)&on, sizeof (on)))
    548 			return error;
    549 		return (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
    550 	}
    551 	case _IOW('t', 33, int): {	/* TIOCSIGNAL */
    552 		int error, sig;
    553 
    554 		if (error = copyin (uap->data, (caddr_t)&sig, sizeof (sig)))
    555 			return error;
    556 		return (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
    557 	}
    558 
    559 /*
    560  * Socket ioctl translations.
    561  */
    562 #define IFREQ_IN(a) { \
    563 	struct ifreq ifreq; \
    564 	if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
    565 		return error; \
    566 	return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
    567 }
    568 #define IFREQ_INOUT(a) { \
    569 	struct ifreq ifreq; \
    570 	if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
    571 		return error; \
    572 	if (error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) \
    573 		return error; \
    574 	return copyout ((caddr_t)&ifreq, uap->data, sizeof (ifreq)); \
    575 }
    576 
    577 	case _IOW('i', 12, struct ifreq):
    578 		/* SIOCSIFADDR */
    579 		break;
    580 
    581 	case _IOWR('i', 13, struct ifreq):
    582 		IFREQ_INOUT(OSIOCGIFADDR);
    583 
    584 	case _IOW('i', 14, struct ifreq):
    585 		/* SIOCSIFDSTADDR */
    586 		break;
    587 
    588 	case _IOWR('i', 15, struct ifreq):
    589 		IFREQ_INOUT(OSIOCGIFDSTADDR);
    590 
    591 	case _IOW('i', 16, struct ifreq):
    592 		/* SIOCSIFFLAGS */
    593 		break;
    594 
    595 	case _IOWR('i', 17, struct ifreq):
    596 		/* SIOCGIFFLAGS */
    597 		break;
    598 
    599 	case _IOW('i', 21, struct ifreq):
    600 		IFREQ_IN(SIOCSIFMTU);
    601 
    602 	case _IOWR('i', 22, struct ifreq):
    603 		IFREQ_INOUT(SIOCGIFMTU);
    604 
    605 	case _IOWR('i', 23, struct ifreq):
    606 		IFREQ_INOUT(SIOCGIFBRDADDR);
    607 
    608 	case _IOW('i', 24, struct ifreq):
    609 		IFREQ_IN(SIOCSIFBRDADDR);
    610 
    611 	case _IOWR('i', 25, struct ifreq):
    612 		IFREQ_INOUT(OSIOCGIFNETMASK);
    613 
    614 	case _IOW('i', 26, struct ifreq):
    615 		IFREQ_IN(SIOCSIFNETMASK);
    616 
    617 	case _IOWR('i', 27, struct ifreq):
    618 		IFREQ_INOUT(SIOCGIFMETRIC);
    619 
    620 	case _IOWR('i', 28, struct ifreq):
    621 		IFREQ_IN(SIOCSIFMETRIC);
    622 
    623 	case _IOW('i', 30, struct arpreq):
    624 		/* SIOCSARP */
    625 		break;
    626 
    627 	case _IOWR('i', 31, struct arpreq):
    628 	    {
    629 		struct arpreq arpreq;
    630 
    631 		if (error = copyin (uap->data, (caddr_t)&arpreq, sizeof (arpreq)))
    632 			return error;
    633 		if (error = (*ctl)(fp, OSIOCGARP, (caddr_t)&arpreq, p))
    634 			return error;
    635 		return copyout ((caddr_t)&arpreq, uap->data, sizeof (arpreq));
    636 	    }
    637 
    638 	case _IOW('i', 32, struct arpreq):
    639 		/* SIOCDARP */
    640 		break;
    641 
    642 	case _IOW('i', 18, struct ifreq):	/* SIOCSIFMEM */
    643 	case _IOWR('i', 19, struct ifreq):	/* SIOCGIFMEM */
    644 	case _IOW('i', 40, struct ifreq):	/* SIOCUPPER */
    645 	case _IOW('i', 41, struct ifreq):	/* SIOCLOWER */
    646 	case _IOW('i', 44, struct ifreq):	/* SIOCSETSYNC */
    647 	case _IOWR('i', 45, struct ifreq):	/* SIOCGETSYNC */
    648 	case _IOWR('i', 46, struct ifreq):	/* SIOCSDSTATS */
    649 	case _IOWR('i', 47, struct ifreq):	/* SIOCSESTATS */
    650 	case _IOW('i', 48, int):		/* SIOCSPROMISC */
    651 	case _IOW('i', 49, struct ifreq):	/* SIOCADDMULTI */
    652 	case _IOW('i', 50, struct ifreq):	/* SIOCDELMULTI */
    653 		return EOPNOTSUPP;
    654 
    655 	case _IOWR('i', 20, struct ifconf):	/* SIOCGIFCONF */
    656 	    {
    657 		struct ifconf ifconf;
    658 
    659 		/*
    660 		 * XXX: two more problems
    661 		 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
    662 		 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
    663 		 */
    664 		if (error = copyin (uap->data, (caddr_t)&ifconf, sizeof (ifconf)))
    665 			return error;
    666 		if (error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p))
    667 			return error;
    668 		return copyout ((caddr_t)&ifconf, uap->data, sizeof (ifconf));
    669 	    }
    670 	}
    671 	return (ioctl(p, uap, retval));
    672 }
    673