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