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