proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / emulation / svr4 / svr4_termios.c
1 /*
2  * Copyright (c) 1998 Mark Newton
3  * Copyright (c) 1994 Christos Zoulas
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. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  * 
28  * $FreeBSD: src/sys/svr4/svr4_termios.c,v 1.5 1999/12/08 12:00:48 newton Exp $
29  * $DragonFly: src/sys/emulation/svr4/Attic/svr4_termios.c,v 1.3 2003/06/25 03:56:10 dillon Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <sys/systm.h>
35 #include <sys/file.h>
36 #include <sys/filedesc.h>
37 #include <sys/termios.h>
38
39 #include <sys/sysproto.h>
40 #include <sys/file2.h>
41
42 #include <svr4/svr4.h>
43 #include <svr4/svr4_util.h>
44 #include <svr4/svr4_ioctl.h>
45 #include <svr4/svr4_termios.h>
46
47 #ifndef __CONCAT3
48 # if __STDC__
49 #  define __CONCAT3(a,b,c)      a ## b ## c
50 # else
51 #  define __CONCAT3(a,b,c)      a/**/b/**/c
52 # endif
53 #endif
54
55 static u_long bsd_to_svr4_speed __P((u_long, u_long));
56 static u_long svr4_to_bsd_speed __P((u_long, u_long));
57 static void svr4_to_bsd_termios __P((const struct svr4_termios *, 
58                                      struct termios *, int));
59 static void bsd_to_svr4_termios __P((const struct termios *, 
60                                      struct svr4_termios *));
61 static void svr4_termio_to_termios __P((const struct svr4_termio *,
62                                         struct svr4_termios *));
63 static void svr4_termios_to_termio __P((const struct svr4_termios *,
64                                         struct svr4_termio *));
65 #ifdef DEBUG_SVR4
66 static void print_svr4_termios __P((const struct svr4_termios *));
67 static void print_bsd_termios __P((const struct termios *));
68 #endif /* DEBUG_SVR4 */
69
70 #define undefined_char(a,b)                             /**/
71 #define undefined_flag1(f,a,b)                          /**/
72 #define undefined_flag2(f,a,b,c1,t1,c2,t2)              /**/
73 #define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4)  /**/
74
75 #define svr4_to_bsd_char(a,b) \
76         if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
77                 if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
78                         bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
79                 else \
80                         bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
81         }
82
83 #define svr4_to_bsd_flag1(f,a,b) \
84         if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
85                 if (st->f & __CONCAT3(SVR4_,a,b)) \
86                         bt->f |= __CONCAT(a,b); \
87                 else \
88                         bt->f &= ~__CONCAT(a,b); \
89         }
90
91 #define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
92         if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
93                 bt->f &= ~__CONCAT(a,b); \
94                 switch (st->f & __CONCAT3(SVR4_,a,b)) { \
95                 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
96                 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
97                 } \
98         }
99
100 #define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
101         if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
102                 bt->f &= ~__CONCAT(a,b); \
103                 switch (st->f & __CONCAT3(SVR4_,a,b)) { \
104                 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
105                 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
106                 case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
107                 case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
108                 } \
109         }
110
111
112 #define bsd_to_svr4_char(a,b) \
113         if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
114                 st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
115         else \
116                 st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
117
118 #define bsd_to_svr4_flag1(f,a,b) \
119         if (bt->f & __CONCAT(a,b)) \
120                 st->f |= __CONCAT3(SVR4_,a,b); \
121         else \
122                 st->f &= ~__CONCAT3(SVR4_,a,b)
123
124 #define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
125         st->f &= ~__CONCAT(a,b); \
126         switch (bt->f & __CONCAT(a,b)) { \
127         case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
128         case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
129         }
130
131 #define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
132         st->f &= ~__CONCAT(a,b); \
133         switch (bt->f & __CONCAT(a,b)) { \
134         case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
135         case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
136         case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
137         case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
138         }
139
140 #ifdef DEBUG_SVR4
141 static void
142 print_svr4_termios(st)
143         const struct svr4_termios *st;
144 {
145         int i;
146         DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
147             st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
148         DPRINTF(("cc: "));
149         for (i = 0; i < SVR4_NCCS; i++)
150                 DPRINTF(("%o ", st->c_cc[i]));
151         DPRINTF(("\n"));
152 }
153
154
155 static void
156 print_bsd_termios(bt)
157         const struct termios *bt;
158 {
159         int i;
160         uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
161             bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
162         uprintf("cc: ");
163         for (i = 0; i < NCCS; i++)
164                 uprintf("%o ", bt->c_cc[i]);
165         uprintf("\n");
166 }
167 #endif /* DEBUG_SVR4 */
168
169 static u_long
170 bsd_to_svr4_speed(sp, mask)
171         u_long sp;
172         u_long mask;
173 {
174         switch (sp) {
175 #undef getval
176 #define getval(a,b)     case __CONCAT(a,b):     sp = __CONCAT3(SVR4_,a,b)
177         getval(B,0);
178         getval(B,50);
179         getval(B,75);
180         getval(B,110);
181         getval(B,134);
182         getval(B,150);
183         getval(B,200);
184         getval(B,300);
185         getval(B,600);
186         getval(B,1200);
187         getval(B,1800);
188         getval(B,2400);
189         getval(B,4800);
190         getval(B,9600);
191         getval(B,19200);
192         getval(B,38400);
193         getval(B,57600);
194         getval(B,115200);
195         default: sp = SVR4_B9600;       /* XXX */
196         }
197
198         while ((mask & 1) == 0) {
199                 mask >>= 1;
200                 sp <<= 1;
201         }
202
203         return sp;
204 }
205
206
207 static u_long
208 svr4_to_bsd_speed(sp, mask)
209         u_long sp;
210         u_long mask;
211 {
212         while ((mask & 1) == 0) {
213                 mask >>= 1;
214                 sp >>= 1;
215         }
216
217         switch (sp & mask) {
218 #undef getval
219 #define getval(a,b)     case __CONCAT3(SVR4_,a,b):      return __CONCAT(a,b)
220         getval(B,0);
221         getval(B,50);
222         getval(B,75);
223         getval(B,110);
224         getval(B,134);
225         getval(B,150);
226         getval(B,200);
227         getval(B,300);
228         getval(B,600);
229         getval(B,1200);
230         getval(B,1800);
231         getval(B,2400);
232         getval(B,4800);
233         getval(B,9600);
234         getval(B,19200);
235         getval(B,38400);
236         getval(B,57600);
237         getval(B,115200);
238         default: return B9600;  /* XXX */
239         }
240 }
241
242
243 static void
244 svr4_to_bsd_termios(st, bt, new)
245         const struct svr4_termios       *st;
246         struct termios                  *bt;
247         int                              new;
248 {
249         /* control characters */
250         /*
251          * We process VMIN and VTIME first,
252          * because they are shared with VEOF and VEOL
253          */
254         svr4_to_bsd_char(V,MIN);
255         svr4_to_bsd_char(V,TIME);
256
257         svr4_to_bsd_char(V,INTR);
258         svr4_to_bsd_char(V,QUIT);
259         svr4_to_bsd_char(V,ERASE);
260         svr4_to_bsd_char(V,KILL);
261         svr4_to_bsd_char(V,EOF);
262         svr4_to_bsd_char(V,EOL);
263         svr4_to_bsd_char(V,EOL2);
264         undefined_char(V,SWTCH);
265         svr4_to_bsd_char(V,START);
266         svr4_to_bsd_char(V,STOP);
267         svr4_to_bsd_char(V,SUSP);
268         svr4_to_bsd_char(V,DSUSP);
269         svr4_to_bsd_char(V,REPRINT);
270         svr4_to_bsd_char(V,DISCARD);
271         svr4_to_bsd_char(V,WERASE);
272         svr4_to_bsd_char(V,LNEXT);
273
274         /* Input modes */
275         svr4_to_bsd_flag1(c_iflag,I,GNBRK);
276         svr4_to_bsd_flag1(c_iflag,B,RKINT);
277         svr4_to_bsd_flag1(c_iflag,I,GNPAR);
278         svr4_to_bsd_flag1(c_iflag,P,ARMRK);
279         svr4_to_bsd_flag1(c_iflag,I,NPCK);
280         svr4_to_bsd_flag1(c_iflag,I,STRIP);
281         svr4_to_bsd_flag1(c_iflag,I,NLCR);
282         svr4_to_bsd_flag1(c_iflag,I,GNCR);
283         svr4_to_bsd_flag1(c_iflag,I,CRNL);
284         undefined_flag1(c_iflag,I,UCLC);
285         svr4_to_bsd_flag1(c_iflag,I,XON);
286         svr4_to_bsd_flag1(c_iflag,I,XANY);
287         svr4_to_bsd_flag1(c_iflag,I,XOFF);
288         svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
289         undefined_flag1(c_iflag,D,OSMODE);
290
291         /* Output modes */
292         svr4_to_bsd_flag1(c_oflag,O,POST);
293         undefined_flag1(c_oflag,O,LCUC);
294         svr4_to_bsd_flag1(c_oflag,O,NLCR);
295         undefined_flag1(c_oflag,O,CRNL);
296         undefined_flag1(c_oflag,O,NOCR);
297         undefined_flag1(c_oflag,O,NLRET);
298         undefined_flag1(c_oflag,O,FILL);
299         undefined_flag1(c_oflag,O,FDEL);
300         undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
301         undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
302         undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
303         undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
304         undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
305         undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
306         undefined_flag1(c_oflag,P,AGEOUT);
307         undefined_flag1(c_oflag,W,RAP);
308
309         /* Control modes */
310         bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
311         svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
312         svr4_to_bsd_flag1(c_cflag,C,STOPB);
313         svr4_to_bsd_flag1(c_cflag,C,READ);
314         svr4_to_bsd_flag1(c_cflag,P,ARENB);
315         svr4_to_bsd_flag1(c_cflag,P,ARODD);
316         svr4_to_bsd_flag1(c_cflag,H,UPCL);
317         svr4_to_bsd_flag1(c_cflag,C,LOCAL);
318         undefined_flag1(c_cflag,R,CV1EN);
319         undefined_flag1(c_cflag,X,MT1EN);
320         undefined_flag1(c_cflag,L,OBLK);
321         undefined_flag1(c_cflag,X,CLUDE);
322         bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
323         undefined_flag1(c_cflag,P,AREXT);
324
325         /* line discipline modes */
326         svr4_to_bsd_flag1(c_lflag,I,SIG);
327         svr4_to_bsd_flag1(c_lflag,I,CANON);
328         undefined_flag1(c_lflag,X,CASE);
329         svr4_to_bsd_flag1(c_lflag,E,CHO);
330         svr4_to_bsd_flag1(c_lflag,E,CHOE);
331         svr4_to_bsd_flag1(c_lflag,E,CHOK);
332         svr4_to_bsd_flag1(c_lflag,E,CHONL);
333         svr4_to_bsd_flag1(c_lflag,N,OFLSH);
334         svr4_to_bsd_flag1(c_lflag,T,OSTOP);
335         svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
336         svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
337         svr4_to_bsd_flag1(c_lflag,E,CHOKE);
338         undefined_flag1(c_lflag,D,EFECHO);
339         svr4_to_bsd_flag1(c_lflag,F,LUSHO);
340         svr4_to_bsd_flag1(c_lflag,P,ENDIN);
341         svr4_to_bsd_flag1(c_lflag,I,EXTEN);
342 }
343
344
345 static void
346 bsd_to_svr4_termios(bt, st)
347         const struct termios    *bt;
348         struct svr4_termios     *st;
349 {
350         /* control characters */
351         /*
352          * We process VMIN and VTIME first,
353          * because they are shared with VEOF and VEOL
354          */
355         bsd_to_svr4_char(V,MIN);
356         bsd_to_svr4_char(V,TIME);
357         bsd_to_svr4_char(V,INTR);
358         bsd_to_svr4_char(V,QUIT);
359         bsd_to_svr4_char(V,ERASE);
360         bsd_to_svr4_char(V,KILL);
361         bsd_to_svr4_char(V,EOF);
362         bsd_to_svr4_char(V,EOL);
363         bsd_to_svr4_char(V,EOL2);
364         undefined_char(V,SWTCH);
365         bsd_to_svr4_char(V,START);
366         bsd_to_svr4_char(V,STOP);
367         bsd_to_svr4_char(V,SUSP);
368         bsd_to_svr4_char(V,DSUSP);
369         bsd_to_svr4_char(V,REPRINT);
370         bsd_to_svr4_char(V,DISCARD);
371         bsd_to_svr4_char(V,WERASE);
372         bsd_to_svr4_char(V,LNEXT);
373
374         /* Input modes */
375         bsd_to_svr4_flag1(c_iflag,I,GNBRK);
376         bsd_to_svr4_flag1(c_iflag,B,RKINT);
377         bsd_to_svr4_flag1(c_iflag,I,GNPAR);
378         bsd_to_svr4_flag1(c_iflag,P,ARMRK);
379         bsd_to_svr4_flag1(c_iflag,I,NPCK);
380         bsd_to_svr4_flag1(c_iflag,I,STRIP);
381         bsd_to_svr4_flag1(c_iflag,I,NLCR);
382         bsd_to_svr4_flag1(c_iflag,I,GNCR);
383         bsd_to_svr4_flag1(c_iflag,I,CRNL);
384         undefined_flag1(c_iflag,I,UCLC);
385         bsd_to_svr4_flag1(c_iflag,I,XON);
386         bsd_to_svr4_flag1(c_iflag,I,XANY);
387         bsd_to_svr4_flag1(c_iflag,I,XOFF);
388         bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
389         undefined_flag1(c_iflag,D,OSMODE);
390
391         /* Output modes */
392         bsd_to_svr4_flag1(c_oflag,O,POST);
393         undefined_flag1(c_oflag,O,LCUC);
394         bsd_to_svr4_flag1(c_oflag,O,NLCR);
395         undefined_flag1(c_oflag,O,CRNL);
396         undefined_flag1(c_oflag,O,NOCR);
397         undefined_flag1(c_oflag,O,NLRET);
398         undefined_flag1(c_oflag,O,FILL);
399         undefined_flag1(c_oflag,O,FDEL);
400         undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
401         undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
402         undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
403         undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
404         undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
405         undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
406         undefined_flag1(c_oflag,P,AGEOUT);
407         undefined_flag1(c_oflag,W,RAP);
408
409         /* Control modes */
410         st->c_cflag &= ~SVR4_CBAUD;
411         st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
412         bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
413         bsd_to_svr4_flag1(c_cflag,C,STOPB);
414         bsd_to_svr4_flag1(c_cflag,C,READ);
415         bsd_to_svr4_flag1(c_cflag,P,ARENB);
416         bsd_to_svr4_flag1(c_cflag,P,ARODD);
417         bsd_to_svr4_flag1(c_cflag,H,UPCL);
418         bsd_to_svr4_flag1(c_cflag,C,LOCAL);
419         undefined_flag1(c_cflag,R,CV1EN);
420         undefined_flag1(c_cflag,X,MT1EN);
421         undefined_flag1(c_cflag,L,OBLK);
422         undefined_flag1(c_cflag,X,CLUDE);
423         st->c_cflag &= ~SVR4_CIBAUD;
424         st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
425
426         undefined_flag1(c_oflag,P,AREXT);
427
428         /* line discipline modes */
429         bsd_to_svr4_flag1(c_lflag,I,SIG);
430         bsd_to_svr4_flag1(c_lflag,I,CANON);
431         undefined_flag1(c_lflag,X,CASE);
432         bsd_to_svr4_flag1(c_lflag,E,CHO);
433         bsd_to_svr4_flag1(c_lflag,E,CHOE);
434         bsd_to_svr4_flag1(c_lflag,E,CHOK);
435         bsd_to_svr4_flag1(c_lflag,E,CHONL);
436         bsd_to_svr4_flag1(c_lflag,N,OFLSH);
437         bsd_to_svr4_flag1(c_lflag,T,OSTOP);
438         bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
439         bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
440         bsd_to_svr4_flag1(c_lflag,E,CHOKE);
441         undefined_flag1(c_lflag,D,EFECHO);
442         bsd_to_svr4_flag1(c_lflag,F,LUSHO);
443         bsd_to_svr4_flag1(c_lflag,P,ENDIN);
444         bsd_to_svr4_flag1(c_lflag,I,EXTEN);
445 }
446
447
448 static void
449 svr4_termio_to_termios(t, ts)
450         const struct svr4_termio        *t;
451         struct svr4_termios             *ts;
452 {
453         int i;
454
455         ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
456         ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
457         ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
458         ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
459
460         for (i = 0; i < SVR4_NCC; i++)
461                 ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
462 }
463
464
465 static void
466 svr4_termios_to_termio(ts, t)
467         const struct svr4_termios       *ts;
468         struct svr4_termio              *t;
469 {
470         int i;
471
472         t->c_iflag = (u_short) ts->c_iflag;
473         t->c_oflag = (u_short) ts->c_oflag;
474         t->c_cflag = (u_short) ts->c_cflag;
475         t->c_lflag = (u_short) ts->c_lflag;
476         t->c_line = 0;  /* XXX */
477
478         for (i = 0; i < SVR4_NCC; i++)
479                 t->c_cc[i] = (u_char) ts->c_cc[i];
480 }
481
482 int
483 svr4_term_ioctl(fp, td, retval, fd, cmd, data)
484         struct file *fp;
485         struct thread *td;
486         register_t *retval;
487         int fd;
488         u_long cmd;
489         caddr_t data;
490 {
491         struct termios          bt;
492         struct svr4_termios     st;
493         struct svr4_termio      t;
494         int                     error, new;
495
496         *retval = 0;
497
498         DPRINTF(("TERM ioctl %lx\n", cmd));
499
500         switch (cmd) {
501         case SVR4_TCGETA:
502         case SVR4_TCGETS:
503                 DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
504                 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
505                         return error;
506
507                 memset(&st, 0, sizeof(st));
508                 bsd_to_svr4_termios(&bt, &st);
509
510 #ifdef DEBUG_SVR4
511                 print_bsd_termios(&bt);
512                 print_svr4_termios(&st);
513 #endif /* DEBUG_SVR4 */
514
515                 if (cmd == SVR4_TCGETA) {
516                     svr4_termios_to_termio(&st, &t);
517                     return copyout(&t, data, sizeof(t));
518                 }
519                 else  {
520                     return copyout(&st, data, sizeof(st));
521                 }
522
523         case SVR4_TCSETA:
524         case SVR4_TCSETS:
525         case SVR4_TCSETAW:
526         case SVR4_TCSETSW:
527         case SVR4_TCSETAF:
528         case SVR4_TCSETSF:
529                 DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
530                 /* get full BSD termios so we don't lose information */
531                 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
532                         return error;
533
534                 switch (cmd) {
535                 case SVR4_TCSETS:
536                 case SVR4_TCSETSW:
537                 case SVR4_TCSETSF:
538                         if ((error = copyin(data, &st, sizeof(st))) != 0)
539                                 return error;
540                         new = 1;
541                         break;
542
543                 case SVR4_TCSETA:
544                 case SVR4_TCSETAW:
545                 case SVR4_TCSETAF:
546                         if ((error = copyin(data, &t, sizeof(t))) != 0)
547                                 return error;
548
549                         svr4_termio_to_termios(&t, &st);
550                         new = 0;
551                         break;
552
553                 default:
554                         return EINVAL;
555                 }
556
557                 svr4_to_bsd_termios(&st, &bt, new);
558
559                 switch (cmd) {
560                 case SVR4_TCSETA:
561                 case SVR4_TCSETS:
562                         DPRINTF(("ioctl(TCSET[A|S]);\n"));
563                         cmd = TIOCSETA;
564                         break;
565                 case SVR4_TCSETAW:
566                 case SVR4_TCSETSW:
567                         DPRINTF(("ioctl(TCSET[A|S]W);\n"));
568                         cmd = TIOCSETAW;
569                         break;
570                 case SVR4_TCSETAF:
571                 case SVR4_TCSETSF:
572                         DPRINTF(("ioctl(TCSET[A|S]F);\n"));
573                         cmd = TIOCSETAF;
574                         break;
575                 }
576
577 #ifdef DEBUG_SVR4
578                 print_bsd_termios(&bt);
579                 print_svr4_termios(&st);
580 #endif /* DEBUG_SVR4 */
581
582                 return fo_ioctl(fp, cmd, (caddr_t) &bt, td);
583
584         case SVR4_TIOCGWINSZ:
585                 DPRINTF(("TIOCGWINSZ\n"));
586                 {
587                         struct svr4_winsize ws;
588
589                         error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, td);
590                         if (error)
591                                 return error;
592                         return copyout(&ws, data, sizeof(ws));
593                 }
594
595         case SVR4_TIOCSWINSZ:
596                 DPRINTF(("TIOCSWINSZ\n"));
597                 {
598                         struct svr4_winsize ws;
599
600                         if ((error = copyin(data, &ws, sizeof(ws))) != 0)
601                                 return error;
602                         return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, td);
603                 }
604
605         default:
606                 DPRINTF(("teleport to STREAMS ioctls...\n"));
607                 return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data);
608         }
609 }