Home | History | Annotate | Line # | Download | only in sunos
sunos_ioctl.c revision 1.3
      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 withough 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.3 1993/11/14 14:46:54 deraadt 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 
     36 /*
     37  * SunOS ioctl calls.
     38  * This file is something of a hodge-podge.
     39  * Support gets added as things turn up....
     40  */
     41 
     42 struct sun_ttysize {
     43 	int	ts_row;
     44 	int	ts_col;
     45 };
     46 
     47 struct sun_termio {
     48 	u_short	c_iflag;
     49 	u_short	c_oflag;
     50 	u_short	c_cflag;
     51 	u_short	c_lflag;
     52 	char	c_line;
     53 	unsigned char c_cc[8];
     54 };
     55 #define SUN_TCGETA	_IOR('T', 1, struct sun_termio)
     56 #define SUN_TCSETA	_IOW('T', 2, struct sun_termio)
     57 #define SUN_TCSETAW	_IOW('T', 3, struct sun_termio)
     58 #define SUN_TCSETAF	_IOW('T', 4, struct sun_termio)
     59 #define SUN_TCSBRK	_IO('T', 5)
     60 
     61 struct sun_termios {
     62 	u_long	c_iflag;
     63 	u_long	c_oflag;
     64 	u_long	c_cflag;
     65 	u_long	c_lflag;
     66 	char	c_line;
     67 	u_char	c_cc[17];
     68 };
     69 #define SUN_TCXONC	_IO('T', 6)
     70 #define SUN_TCFLSH	_IO('T', 7)
     71 #define SUN_TCGETS	_IOR('T', 8, struct sun_termios)
     72 #define SUN_TCSETS	_IOW('T', 9, struct sun_termios)
     73 #define SUN_TCSETSW	_IOW('T', 10, struct sun_termios)
     74 #define SUN_TCSETSF	_IOW('T', 11, struct sun_termios)
     75 #define SUN_TCSNDBRK	_IO('T', 12)
     76 #define SUN_TCDRAIN	_IO('T', 13)
     77 
     78 static struct speedtab sptab[] = {
     79 	{ 0, 0 },
     80 	{ 50, 1 },
     81 	{ 75, 2 },
     82 	{ 110, 3 },
     83 	{ 134, 4 },
     84 	{ 135, 4 },
     85 	{ 150, 5 },
     86 	{ 200, 6 },
     87 	{ 300, 7 },
     88 	{ 600, 8 },
     89 	{ 1200, 9 },
     90 	{ 1800, 10 },
     91 	{ 2400, 11 },
     92 	{ 4800, 12 },
     93 	{ 9600, 13 },
     94 	{ 19200, 14 },
     95 	{ 38400, 15 },
     96 	{ -1, -1 }
     97 };
     98 
     99 static u_long s2btab[] = {
    100 	0,
    101 	50,
    102 	75,
    103 	110,
    104 	134,
    105 	150,
    106 	200,
    107 	300,
    108 	600,
    109 	1200,
    110 	1800,
    111 	2400,
    112 	4800,
    113 	9600,
    114 	19200,
    115 	38400,
    116 };
    117 
    118 /*
    119  * these two conversion functions have mostly been done
    120  * with some perl cut&paste, then handedited to comment
    121  * out what doesn't exist under NetBSD.
    122  * A note from Markus's code:
    123  *	(l & BITMASK1) / BITMASK1 * BITMASK2  is translated
    124  *	optimally by gcc m68k, much better than any ?: stuff.
    125  *	Code may vary with different architectures of course.
    126  *
    127  * I don't know what optimizer you used, but seeing divu's and
    128  * bfextu's in the m68k assembly output did not encourage me...
    129  * as well, gcc on the sparc definately generates much better
    130  * code with ?:.
    131  */
    132 
    133 static void
    134 stios2btios(st, bt)
    135 	struct sun_termios *st;
    136 	struct termios *bt;
    137 {
    138 	register u_long l, r;
    139 
    140 	l = st->c_iflag;
    141 	r = 	((l & 0x00000001) ? IGNBRK	: 0);
    142 	r |=	((l & 0x00000002) ? BRKINT	: 0);
    143 	r |=	((l & 0x00000004) ? IGNPAR	: 0);
    144 	r |=	((l & 0x00000008) ? PARMRK	: 0);
    145 	r |=	((l & 0x00000010) ? INPCK	: 0);
    146 	r |=	((l & 0x00000020) ? ISTRIP	: 0);
    147 	r |= 	((l & 0x00000040) ? INLCR	: 0);
    148 	r |=	((l & 0x00000080) ? IGNCR	: 0);
    149 	r |=	((l & 0x00000100) ? ICRNL	: 0);
    150 	/*	((l & 0x00000200) ? IUCLC	: 0) */
    151 	r |=	((l & 0x00000400) ? IXON	: 0);
    152 	r |=	((l & 0x00000800) ? IXANY	: 0);
    153 	r |=	((l & 0x00001000) ? IXOFF	: 0);
    154 	r |=	((l & 0x00002000) ? IMAXBEL	: 0);
    155 	bt->c_iflag = r;
    156 
    157 	l = st->c_oflag;
    158 	r = 	((l & 0x00000001) ? OPOST	: 0);
    159 	/*	((l & 0x00000002) ? OLCUC	: 0) */
    160 	r |=	((l & 0x00000004) ? ONLCR	: 0);
    161 	/*	((l & 0x00000008) ? OCRNL	: 0) */
    162 	/*	((l & 0x00000010) ? ONOCR	: 0) */
    163 	/*	((l & 0x00000020) ? ONLRET	: 0) */
    164 	/*	((l & 0x00000040) ? OFILL	: 0) */
    165 	/*	((l & 0x00000080) ? OFDEL	: 0) */
    166 	/*	((l & 0x00000100) ? NLDLY	: 0) */
    167 	/*	((l & 0x00000100) ? NL1		: 0) */
    168 	/*	((l & 0x00000600) ? CRDLY	: 0) */
    169 	/*	((l & 0x00000200) ? CR1		: 0) */
    170 	/*	((l & 0x00000400) ? CR2		: 0) */
    171 	/*	((l & 0x00000600) ? CR3		: 0) */
    172 	/*	((l & 0x00001800) ? TABDLY	: 0) */
    173 	/*	((l & 0x00000800) ? TAB1	: 0) */
    174 	/*	((l & 0x00001000) ? TAB2	: 0) */
    175 	r |=	((l & 0x00001800) ? OXTABS	: 0);
    176 	/*	((l & 0x00002000) ? BSDLY	: 0) */
    177 	/*	((l & 0x00002000) ? BS1		: 0) */
    178 	/*	((l & 0x00004000) ? VTDLY	: 0) */
    179 	/*	((l & 0x00004000) ? VT1		: 0) */
    180 	/*	((l & 0x00008000) ? FFDLY	: 0) */
    181 	/*	((l & 0x00008000) ? FF1		: 0) */
    182 	/*	((l & 0x00010000) ? PAGEOUT	: 0) */
    183 	/*	((l & 0x00020000) ? WRAP	: 0) */
    184 	bt->c_oflag = r;
    185 
    186 	l = st->c_cflag;
    187 	r = 	((l & 0x00000010) ? CS6		: 0);
    188 	r |=	((l & 0x00000020) ? CS7		: 0);
    189 	r |=	((l & 0x00000030) ? CS8		: 0);
    190 	r |=	((l & 0x00000040) ? CSTOPB	: 0);
    191 	r |=	((l & 0x00000080) ? CREAD	: 0);
    192 	r |= 	((l & 0x00000100) ? PARENB	: 0);
    193 	r |=	((l & 0x00000200) ? PARODD	: 0);
    194 	r |=	((l & 0x00000400) ? HUPCL	: 0);
    195 	r |=	((l & 0x00000800) ? CLOCAL	: 0);
    196 	/*	((l & 0x00001000) ? LOBLK	: 0) */
    197 	r |=	((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
    198 	bt->c_cflag = r;
    199 
    200 	bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
    201 
    202 	l = st->c_lflag;
    203 	r = 	((l & 0x00000001) ? ISIG	: 0);
    204 	r |=	((l & 0x00000002) ? ICANON	: 0);
    205 	/*	((l & 0x00000004) ? XCASE	: 0) */
    206 	r |=	((l & 0x00000008) ? ECHO	: 0);
    207 	r |=	((l & 0x00000010) ? ECHOE	: 0);
    208 	r |=	((l & 0x00000020) ? ECHOK	: 0);
    209 	r |=	((l & 0x00000040) ? ECHONL	: 0);
    210 	r |= 	((l & 0x00000080) ? NOFLSH	: 0);
    211 	r |=	((l & 0x00000100) ? TOSTOP	: 0);
    212 	r |=	((l & 0x00000200) ? ECHOCTL	: 0);
    213 	r |=	((l & 0x00000400) ? ECHOPRT	: 0);
    214 	r |=	((l & 0x00000800) ? ECHOKE	: 0);
    215 	/*	((l & 0x00001000) ? DEFECHO	: 0) */
    216 	r |=	((l & 0x00002000) ? FLUSHO	: 0);
    217 	r |=	((l & 0x00004000) ? PENDIN	: 0);
    218 	bt->c_lflag = r;
    219 
    220 	bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
    221 	bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
    222 	bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
    223 	bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
    224 	bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
    225 	bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
    226 	bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
    227     /*	bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
    228 	bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
    229 	bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
    230 	bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
    231 	bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
    232 	bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
    233 	bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
    234 	bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
    235 	bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
    236 	bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
    237 }
    238 
    239 
    240 static void
    241 btios2stios(bt, st)
    242 	struct termios *bt;
    243 	struct sun_termios *st;
    244 {
    245 	register u_long l, r;
    246 
    247 	l = bt->c_iflag;
    248 	r = 	((l &  IGNBRK) ? 0x00000001	: 0);
    249 	r |=	((l &  BRKINT) ? 0x00000002	: 0);
    250 	r |=	((l &  IGNPAR) ? 0x00000004	: 0);
    251 	r |=	((l &  PARMRK) ? 0x00000008	: 0);
    252 	r |=	((l &   INPCK) ? 0x00000010	: 0);
    253 	r |=	((l &  ISTRIP) ? 0x00000020	: 0);
    254 	r |=	((l &   INLCR) ? 0x00000040	: 0);
    255 	r |=	((l &   IGNCR) ? 0x00000080	: 0);
    256 	r |=	((l &   ICRNL) ? 0x00000100	: 0);
    257 	/*	((l &   IUCLC) ? 0x00000200	: 0) */
    258 	r |=	((l &    IXON) ? 0x00000400	: 0);
    259 	r |=	((l &   IXANY) ? 0x00000800	: 0);
    260 	r |=	((l &   IXOFF) ? 0x00001000	: 0);
    261 	r |=	((l & IMAXBEL) ? 0x00002000	: 0);
    262 	st->c_iflag = r;
    263 
    264 	l = bt->c_oflag;
    265 	r =	((l &   OPOST) ? 0x00000001	: 0);
    266 	/*	((l &   OLCUC) ? 0x00000002	: 0) */
    267 	r |=	((l &   ONLCR) ? 0x00000004	: 0);
    268 	/*	((l &   OCRNL) ? 0x00000008	: 0) */
    269 	/*	((l &   ONOCR) ? 0x00000010	: 0) */
    270 	/*	((l &  ONLRET) ? 0x00000020	: 0) */
    271 	/*	((l &   OFILL) ? 0x00000040	: 0) */
    272 	/*	((l &   OFDEL) ? 0x00000080	: 0) */
    273 	/*	((l &   NLDLY) ? 0x00000100	: 0) */
    274 	/*	((l &     NL1) ? 0x00000100	: 0) */
    275 	/*	((l &   CRDLY) ? 0x00000600	: 0) */
    276 	/*	((l &     CR1) ? 0x00000200	: 0) */
    277 	/*	((l &     CR2) ? 0x00000400	: 0) */
    278 	/*	((l &     CR3) ? 0x00000600	: 0) */
    279 	/*	((l &  TABDLY) ? 0x00001800	: 0) */
    280 	/*	((l &    TAB1) ? 0x00000800	: 0) */
    281 	/*	((l &    TAB2) ? 0x00001000	: 0) */
    282 	r |=	((l &  OXTABS) ? 0x00001800	: 0);
    283 	/*	((l &   BSDLY) ? 0x00002000	: 0) */
    284 	/*	((l &     BS1) ? 0x00002000	: 0) */
    285 	/*	((l &   VTDLY) ? 0x00004000	: 0) */
    286 	/*	((l &     VT1) ? 0x00004000	: 0) */
    287 	/*	((l &   FFDLY) ? 0x00008000	: 0) */
    288 	/*	((l &     FF1) ? 0x00008000	: 0) */
    289 	/*	((l & PAGEOUT) ? 0x00010000	: 0) */
    290 	/*	((l &    WRAP) ? 0x00020000	: 0) */
    291 	st->c_oflag = r;
    292 
    293 	l = bt->c_cflag;
    294 	r = 	((l &     CS6) ? 0x00000010	: 0);
    295 	r |=	((l &     CS7) ? 0x00000020	: 0);
    296 	r |=	((l &     CS8) ? 0x00000030	: 0);
    297 	r |=	((l &  CSTOPB) ? 0x00000040	: 0);
    298 	r |=	((l &   CREAD) ? 0x00000080	: 0);
    299 	r |=	((l &  PARENB) ? 0x00000100	: 0);
    300 	r |=	((l &  PARODD) ? 0x00000200	: 0);
    301 	r |=	((l &   HUPCL) ? 0x00000400	: 0);
    302 	r |=	((l &  CLOCAL) ? 0x00000800	: 0);
    303 	/*	((l &   LOBLK) ? 0x00001000	: 0) */
    304 	r |=	((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
    305 	st->c_cflag = r;
    306 
    307 	l = bt->c_lflag;
    308 	r =	((l &    ISIG) ? 0x00000001	: 0);
    309 	r |=	((l &  ICANON) ? 0x00000002	: 0);
    310 	/*	((l &   XCASE) ? 0x00000004	: 0) */
    311 	r |=	((l &    ECHO) ? 0x00000008	: 0);
    312 	r |=	((l &   ECHOE) ? 0x00000010	: 0);
    313 	r |=	((l &   ECHOK) ? 0x00000020	: 0);
    314 	r |=	((l &  ECHONL) ? 0x00000040	: 0);
    315 	r |=	((l &  NOFLSH) ? 0x00000080	: 0);
    316 	r |=	((l &  TOSTOP) ? 0x00000100	: 0);
    317 	r |=	((l & ECHOCTL) ? 0x00000200	: 0);
    318 	r |=	((l & ECHOPRT) ? 0x00000400	: 0);
    319 	r |=	((l &  ECHOKE) ? 0x00000800	: 0);
    320 	/*	((l & DEFECHO) ? 0x00001000	: 0) */
    321 	r |=	((l &  FLUSHO) ? 0x00002000	: 0);
    322 	r |=	((l &  PENDIN) ? 0x00004000	: 0);
    323 	st->c_lflag = r;
    324 
    325 	l = ttspeedtab(bt->c_ospeed, sptab);
    326 	if (l >= 0)
    327 		st->c_cflag |= l;
    328 
    329 	st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
    330 	st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
    331 	st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
    332 	st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
    333 	st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
    334 	st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
    335 	st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
    336 	st->c_cc[7] = 0;
    337 		/*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
    338 	st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
    339 	st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
    340 	st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
    341 	st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
    342 	st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
    343 	st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
    344 	st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
    345 	st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
    346 	st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
    347 
    348 	st->c_line = 0;
    349 }
    350 
    351 static void
    352 stios2stio(ts, t)
    353 	struct sun_termios *ts;
    354 	struct sun_termio *t;
    355 {
    356 	t->c_iflag = ts->c_iflag;
    357 	t->c_oflag = ts->c_oflag;
    358 	t->c_cflag = ts->c_cflag;
    359 	t->c_lflag = ts->c_lflag;
    360 	t->c_line  = ts->c_line;
    361 	bcopy(ts->c_cc, t->c_cc, 8);
    362 }
    363 
    364 static void
    365 stio2stios(t, ts)
    366 	struct sun_termio *t;
    367 	struct sun_termios *ts;
    368 {
    369 	ts->c_iflag = t->c_iflag;
    370 	ts->c_oflag = t->c_oflag;
    371 	ts->c_cflag = t->c_cflag;
    372 	ts->c_lflag = t->c_lflag;
    373 	ts->c_line  = t->c_line;
    374 	bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
    375 }
    376 
    377 struct sun_ioctl_args {
    378 	int	fd;
    379 	int	cmd;
    380 	caddr_t	data;
    381 };
    382 
    383 int
    384 sun_ioctl(p, uap, retval)
    385 	register struct proc *p;
    386 	register struct sun_ioctl_args *uap;
    387 	int *retval;
    388 {
    389 	register struct filedesc *fdp = p->p_fd;
    390 	register struct file *fp;
    391 	register int (*ctl)();
    392 	int error;
    393 
    394 	if ( (unsigned)uap->fd >= fdp->fd_nfiles ||
    395 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
    396 		return EBADF;
    397 
    398 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
    399 		return EBADF;
    400 
    401 	ctl = fp->f_ops->fo_ioctl;
    402 
    403 	switch (uap->cmd) {
    404 	case _IOR('t', 0, int):
    405 		uap->cmd = TIOCGETD;
    406 		break;
    407 	case _IOW('t', 1, int):
    408 	    {
    409 		int disc;
    410 
    411 		if ((error = copyin(uap->data, (caddr_t)&disc,
    412 		    sizeof disc)) != 0)
    413 			return error;
    414 
    415 		/* map SunOS NTTYDISC into our termios discipline */
    416 		if (disc == 2)
    417 			disc = 0;
    418 		/* all other disciplines are not supported by NetBSD */
    419 		if (disc)
    420 			return ENXIO;
    421 
    422 		return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
    423 	    }
    424 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
    425 	    {
    426 		int on = 1;
    427 		return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
    428 	    }
    429 	case _IOW('t', 37, struct sun_ttysize):
    430 	    {
    431 		struct winsize ws;
    432 		struct sun_ttysize ss;
    433 
    434 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
    435 			return (error);
    436 
    437 		if ((error = copyin (uap->data, &ss, sizeof (ss))) != 0)
    438 			return error;
    439 
    440 		ws.ws_row = ss.ts_row;
    441 		ws.ws_col = ss.ts_col;
    442 
    443 		return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
    444 	    }
    445 	case _IOW('t', 38, 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 		ss.ts_row = ws.ws_row;
    454 		ss.ts_col = ws.ws_col;
    455 
    456 		return copyout ((caddr_t)&ss, uap->data, sizeof (ss));
    457 	    }
    458 	case _IOR('t', 130, int):
    459 		uap->cmd = TIOCSPGRP;
    460 		break;
    461 	case _IOR('t', 131, int):
    462 		uap->cmd = TIOCGPGRP;
    463 		break;
    464 	case _IO('t', 132):
    465 		uap->cmd = TIOCSCTTY;
    466 		break;
    467 	case SUN_TCGETA:
    468 	case SUN_TCGETS:
    469 	    {
    470 		struct termios bts;
    471 		struct sun_termios sts;
    472 		struct sun_termio st;
    473 
    474 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
    475 			return error;
    476 
    477 		btios2stios (&bts, &sts);
    478 		if (uap->cmd == SUN_TCGETA) {
    479 			stios2stio (&sts, &st);
    480 			return copyout((caddr_t)&st, uap->data, sizeof (st));
    481 		} else
    482 			return copyout((caddr_t)&sts, uap->data, sizeof (sts));
    483 		/*NOTREACHED*/
    484 	    }
    485 	case SUN_TCSETA:
    486 	case SUN_TCSETAW:
    487 	case SUN_TCSETAF:
    488 	    {
    489 		struct termios bts;
    490 		struct sun_termios sts;
    491 		struct sun_termio st;
    492 
    493 		if ((error = copyin(uap->data, (caddr_t)&st,
    494 		    sizeof (st))) != 0)
    495 			return error;
    496 
    497 		/* get full BSD termios so we don't lose information */
    498 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
    499 			return error;
    500 
    501 		/*
    502 		 * convert to sun termios, copy in information from
    503 		 * termio, and convert back, then set new values.
    504 		 */
    505 		btios2stios(&bts, &sts);
    506 		stio2stios(&st, &sts);
    507 		stios2btios(&sts, &bts);
    508 
    509 		return (*ctl)(fp, uap->cmd - SUN_TCSETA + TIOCSETA,
    510 		    (caddr_t)&bts, p);
    511 	    }
    512 	case SUN_TCSETS:
    513 	case SUN_TCSETSW:
    514 	case SUN_TCSETSF:
    515 	    {
    516 		struct termios bts;
    517 		struct sun_termios sts;
    518 
    519 		if ((error = copyin (uap->data, (caddr_t)&sts,
    520 		    sizeof (sts))) != 0)
    521 			return error;
    522 		stios2btios (&sts, &bts);
    523 		return (*ctl)(fp, uap->cmd - SUN_TCSETS + TIOCSETA,
    524 		    (caddr_t)&bts, p);
    525 	    }
    526 	}
    527 	return (ioctl(p, uap, retval));
    528 }
    529