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