xref: /freebsd/sys/compat/linux/linux_ioctl.c (revision 48991a368427cadb9cdac39581d1676c29619c52)
1 /*-
2  * Copyright (c) 1994-1995 S�ren Schmidt
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  *    in this position and unchanged.
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 withough 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  *  $Id: linux_ioctl.c,v 1.1 1995/06/25 17:32:35 sos Exp $
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/sysproto.h>
34 #include <sys/proc.h>
35 #include <sys/ioctl.h>
36 #include <sys/ioctl_compat.h>
37 #include <sys/file.h>
38 #include <sys/filedesc.h>
39 #include <sys/tty.h>
40 #include <sys/termios.h>
41 
42 #include <machine/console.h>
43 
44 #include <i386/linux/linux.h>
45 #include <i386/linux/sysproto.h>
46 
47 struct linux_termios {
48     unsigned long   c_iflag;
49     unsigned long   c_oflag;
50     unsigned long   c_cflag;
51     unsigned long   c_lflag;
52     unsigned char   c_line;
53     unsigned char   c_cc[LINUX_NCCS];
54 };
55 
56 struct linux_winsize {
57     unsigned short ws_row, ws_col;
58     unsigned short ws_xpixel, ws_ypixel;
59 };
60 
61 static struct speedtab sptab[] = {
62     { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 },
63     { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 },
64     { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 },
65     { 2400, 11 }, { 4800, 12 }, { 9600, 13 },
66     { 19200, 14 }, { 38400, 15 },
67     { 57600, 4097 }, { 115200, 4098 }, {-1, -1 }
68 };
69 
70 static int
71 linux_to_bsd_speed(int code, struct speedtab *table)
72 {
73     for ( ; table->sp_code != -1; table++)
74 	if (table->sp_code == code)
75 	    return (table->sp_speed);
76     return -1;
77 }
78 
79 static int
80 bsd_to_linux_speed(int speed, struct speedtab *table)
81 {
82     for ( ; table->sp_speed != -1; table++)
83 	if (table->sp_speed == speed)
84 	    return (table->sp_code);
85     return -1;
86 }
87 
88 static void
89 bsd_to_linux_termios(struct termios *bsd_termios,
90 		struct linux_termios *linux_termios)
91 {
92     int i, speed;
93 
94 #ifdef DEBUG
95     printf("LINUX: BSD termios structure (input):\n");
96     printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
97 	   bsd_termios->c_iflag, bsd_termios->c_oflag,
98 	   bsd_termios->c_cflag, bsd_termios->c_lflag,
99 	   bsd_termios->c_ispeed, bsd_termios->c_ospeed);
100     printf("c_cc ");
101     for (i=0; i<NCCS; i++)
102 	printf("%02x ", bsd_termios->c_cc[i]);
103     printf("\n");
104 #endif
105     linux_termios->c_iflag = 0;
106     if (bsd_termios->c_iflag & IGNBRK)
107 	linux_termios->c_iflag |= LINUX_IGNBRK;
108     if (bsd_termios->c_iflag & BRKINT)
109 	linux_termios->c_iflag |= LINUX_BRKINT;
110     if (bsd_termios->c_iflag & IGNPAR)
111 	linux_termios->c_iflag |= LINUX_IGNPAR;
112     if (bsd_termios->c_iflag & PARMRK)
113 	linux_termios->c_iflag |= LINUX_PARMRK;
114     if (bsd_termios->c_iflag & INPCK)
115 	linux_termios->c_iflag |= LINUX_INPCK;
116     if (bsd_termios->c_iflag & ISTRIP)
117 	linux_termios->c_iflag |= LINUX_ISTRIP;
118     if (bsd_termios->c_iflag & INLCR)
119 	linux_termios->c_iflag |= LINUX_INLCR;
120     if (bsd_termios->c_iflag & IGNCR)
121 	linux_termios->c_iflag |= LINUX_IGNCR;
122     if (bsd_termios->c_iflag & ICRNL)
123 	linux_termios->c_iflag |= LINUX_ICRNL;
124     if (bsd_termios->c_iflag & IXON)
125 	linux_termios->c_iflag |= LINUX_IXANY;
126     if (bsd_termios->c_iflag & IXON)
127 	linux_termios->c_iflag |= LINUX_IXON;
128     if (bsd_termios->c_iflag & IXOFF)
129 	linux_termios->c_iflag |= LINUX_IXOFF;
130     if (bsd_termios->c_iflag & IMAXBEL)
131 	linux_termios->c_iflag |= LINUX_IMAXBEL;
132 
133     linux_termios->c_oflag = 0;
134     if (bsd_termios->c_oflag & OPOST)
135 	linux_termios->c_oflag |= LINUX_OPOST;
136     if (bsd_termios->c_oflag & ONLCR)
137 	linux_termios->c_oflag |= LINUX_ONLCR;
138     if (bsd_termios->c_oflag & OXTABS)
139 	linux_termios->c_oflag |= LINUX_XTABS;
140 
141     linux_termios->c_cflag =
142 	bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
143     linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
144     if (bsd_termios->c_cflag & CSTOPB)
145 	linux_termios->c_cflag |= LINUX_CSTOPB;
146     if (bsd_termios->c_cflag & CREAD)
147 	linux_termios->c_cflag |= LINUX_CREAD;
148     if (bsd_termios->c_cflag & PARENB)
149 	linux_termios->c_cflag |= LINUX_PARENB;
150     if (bsd_termios->c_cflag & PARODD)
151 	linux_termios->c_cflag |= LINUX_PARODD;
152     if (bsd_termios->c_cflag & HUPCL)
153 	linux_termios->c_cflag |= LINUX_HUPCL;
154     if (bsd_termios->c_cflag & CLOCAL)
155 	linux_termios->c_cflag |= LINUX_CLOCAL;
156     if (bsd_termios->c_cflag & CRTSCTS)
157 	linux_termios->c_cflag |= LINUX_CRTSCTS;
158 
159     linux_termios->c_lflag = 0;
160     if (bsd_termios->c_lflag & ISIG)
161 	linux_termios->c_lflag |= LINUX_ISIG;
162     if (bsd_termios->c_lflag & ICANON)
163 	linux_termios->c_lflag |= LINUX_ICANON;
164     if (bsd_termios->c_lflag & ECHO)
165 	linux_termios->c_lflag |= LINUX_ECHO;
166     if (bsd_termios->c_lflag & ECHOE)
167 	linux_termios->c_lflag |= LINUX_ECHOE;
168     if (bsd_termios->c_lflag & ECHOK)
169 	linux_termios->c_lflag |= LINUX_ECHOK;
170     if (bsd_termios->c_lflag & ECHONL)
171 	linux_termios->c_lflag |= LINUX_ECHONL;
172     if (bsd_termios->c_lflag & NOFLSH)
173 	linux_termios->c_lflag |= LINUX_NOFLSH;
174     if (bsd_termios->c_lflag & TOSTOP)
175 	linux_termios->c_lflag |= LINUX_TOSTOP;
176     if (bsd_termios->c_lflag & ECHOCTL)
177 	linux_termios->c_lflag |= LINUX_ECHOCTL;
178     if (bsd_termios->c_lflag & ECHOPRT)
179 	linux_termios->c_lflag |= LINUX_ECHOPRT;
180     if (bsd_termios->c_lflag & ECHOKE)
181 	linux_termios->c_lflag |= LINUX_ECHOKE;
182     if (bsd_termios->c_lflag & FLUSHO)
183 	linux_termios->c_lflag |= LINUX_FLUSHO;
184     if (bsd_termios->c_lflag & PENDIN)
185 	linux_termios->c_lflag |= LINUX_PENDIN;
186     if (bsd_termios->c_lflag & IEXTEN)
187 	linux_termios->c_lflag |= LINUX_IEXTEN;
188 
189     for (i=0; i<LINUX_NCCS; i++)
190 	linux_termios->c_cc[i] = _POSIX_VDISABLE;
191     linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
192     linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
193     linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
194     linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
195     linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
196     linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
197     linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
198     linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
199     linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
200     linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE;
201     linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
202     linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
203     linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
204     linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
205     linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
206     linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
207     linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
208 
209     linux_termios->c_line = 0;
210 #ifdef DEBUG
211     printf("LINUX: LINUX termios structure (output):\n");
212     printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
213 	   linux_termios->c_iflag, linux_termios->c_oflag,
214 	   linux_termios->c_cflag, linux_termios->c_lflag,
215 	   linux_termios->c_line);
216     printf("c_cc ");
217     for (i=0; i<LINUX_NCCS; i++)
218 	printf("%02x ", linux_termios->c_cc[i]);
219     printf("\n");
220 #endif
221 }
222 
223 static void
224 linux_to_bsd_termios(struct linux_termios *linux_termios,
225 		struct termios *bsd_termios)
226 {
227     int i, speed;
228 #ifdef DEBUG
229     printf("LINUX: LINUX termios structure (input):\n");
230     printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
231 	   linux_termios->c_iflag, linux_termios->c_oflag,
232 	   linux_termios->c_cflag, linux_termios->c_lflag,
233 	   linux_termios->c_line);
234     printf("c_cc ");
235     for (i=0; i<LINUX_NCCS; i++)
236 	printf("%02x ", linux_termios->c_cc[i]);
237     printf("\n");
238 #endif
239     bsd_termios->c_iflag = 0;
240     if (linux_termios->c_iflag & LINUX_IGNBRK)
241 	bsd_termios->c_iflag |= IGNBRK;
242     if (linux_termios->c_iflag & LINUX_BRKINT)
243 	bsd_termios->c_iflag |= BRKINT;
244     if (linux_termios->c_iflag & LINUX_IGNPAR)
245 	bsd_termios->c_iflag |= IGNPAR;
246     if (linux_termios->c_iflag & LINUX_PARMRK)
247 	bsd_termios->c_iflag |= PARMRK;
248     if (linux_termios->c_iflag & LINUX_INPCK)
249 	bsd_termios->c_iflag |= INPCK;
250     if (linux_termios->c_iflag & LINUX_ISTRIP)
251 	bsd_termios->c_iflag |= ISTRIP;
252     if (linux_termios->c_iflag & LINUX_INLCR)
253 	bsd_termios->c_iflag |= INLCR;
254     if (linux_termios->c_iflag & LINUX_IGNCR)
255 	bsd_termios->c_iflag |= IGNCR;
256     if (linux_termios->c_iflag & LINUX_ICRNL)
257 	bsd_termios->c_iflag |= ICRNL;
258     if (linux_termios->c_iflag & LINUX_IXON)
259 	bsd_termios->c_iflag |= IXANY;
260     if (linux_termios->c_iflag & LINUX_IXON)
261 	bsd_termios->c_iflag |= IXON;
262     if (linux_termios->c_iflag & LINUX_IXOFF)
263 	bsd_termios->c_iflag |= IXOFF;
264     if (linux_termios->c_iflag & LINUX_IMAXBEL)
265 	bsd_termios->c_iflag |= IMAXBEL;
266 
267     bsd_termios->c_oflag = 0;
268     if (linux_termios->c_oflag & LINUX_OPOST)
269 	bsd_termios->c_oflag |= OPOST;
270     if (linux_termios->c_oflag & LINUX_ONLCR)
271 	bsd_termios->c_oflag |= ONLCR;
272     if (linux_termios->c_oflag & LINUX_XTABS)
273 	bsd_termios->c_oflag |= OXTABS;
274 
275     bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
276     if (linux_termios->c_cflag & LINUX_CSTOPB)
277 	bsd_termios->c_cflag |= CSTOPB;
278     if (linux_termios->c_cflag & LINUX_PARENB)
279 	bsd_termios->c_cflag |= PARENB;
280     if (linux_termios->c_cflag & LINUX_PARODD)
281 	bsd_termios->c_cflag |= PARODD;
282     if (linux_termios->c_cflag & LINUX_HUPCL)
283 	bsd_termios->c_cflag |= HUPCL;
284     if (linux_termios->c_cflag & LINUX_CLOCAL)
285 	bsd_termios->c_cflag |= CLOCAL;
286     if (linux_termios->c_cflag & LINUX_CRTSCTS)
287 	bsd_termios->c_cflag |= CRTSCTS;
288 
289     bsd_termios->c_lflag = 0;
290     if (linux_termios->c_lflag & LINUX_ISIG)
291 	bsd_termios->c_lflag |= ISIG;
292     if (linux_termios->c_lflag & LINUX_ICANON)
293 	bsd_termios->c_lflag |= ICANON;
294     if (linux_termios->c_lflag & LINUX_ECHO)
295 	bsd_termios->c_lflag |= ECHO;
296     if (linux_termios->c_lflag & LINUX_ECHOE)
297 	bsd_termios->c_lflag |= ECHOE;
298     if (linux_termios->c_lflag & LINUX_ECHOK)
299 	bsd_termios->c_lflag |= ECHOK;
300     if (linux_termios->c_lflag & LINUX_ECHONL)
301 	bsd_termios->c_lflag |= ECHONL;
302     if (linux_termios->c_lflag & LINUX_NOFLSH)
303 	bsd_termios->c_lflag |= NOFLSH;
304     if (linux_termios->c_lflag & LINUX_TOSTOP)
305 	bsd_termios->c_lflag |= TOSTOP;
306     if (linux_termios->c_lflag & LINUX_ECHOCTL)
307 	bsd_termios->c_lflag |= ECHOCTL;
308     if (linux_termios->c_lflag & LINUX_ECHOPRT)
309 	bsd_termios->c_lflag |= ECHOPRT;
310     if (linux_termios->c_lflag & LINUX_ECHOKE)
311 	bsd_termios->c_lflag |= ECHOKE;
312     if (linux_termios->c_lflag & LINUX_FLUSHO)
313 	bsd_termios->c_lflag |= FLUSHO;
314     if (linux_termios->c_lflag & LINUX_PENDIN)
315 	bsd_termios->c_lflag |= PENDIN;
316     if (linux_termios->c_lflag & IEXTEN)
317 	bsd_termios->c_lflag |= IEXTEN;
318 
319     for (i=0; i<NCCS; i++)
320 	bsd_termios->c_cc[i] = _POSIX_VDISABLE;
321     bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
322     bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
323     bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
324     bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
325     bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
326     bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
327     bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
328     bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
329     bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
330     bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
331     bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
332     bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
333     bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
334     bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
335     bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
336     bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
337 
338     bsd_termios->c_ispeed = bsd_termios->c_ospeed =
339 	linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
340 #ifdef DEBUG
341 	printf("LINUX: BSD termios structure (output):\n");
342 	printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
343 	       bsd_termios->c_iflag, bsd_termios->c_oflag,
344 	       bsd_termios->c_cflag, bsd_termios->c_lflag,
345 	       bsd_termios->c_ispeed, bsd_termios->c_ospeed);
346 	printf("c_cc ");
347 	for (i=0; i<NCCS; i++)
348 	    printf("%02x ", bsd_termios->c_cc[i]);
349 	printf("\n");
350 #endif
351 }
352 
353 
354 struct linux_ioctl_args {
355     int fd;
356     int cmd;
357     int arg;
358 };
359 
360 int
361 linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
362 {
363     struct termios bsd_termios;
364     struct winsize bsd_winsize;
365     struct linux_termios linux_termios;
366     struct linux_winsize linux_winsize;
367     struct filedesc *fdp = p->p_fd;
368     struct file *fp;
369     int (*func)(struct file *fp, int com, caddr_t data, struct proc *p);
370     int bsd_line, linux_line;
371     int error;
372 
373 #ifdef DEBUG
374     printf("Linux-emul(%d): ioctl(%d, %04x, *)\n",
375 	   p->p_pid, args->fd, args->cmd);
376 #endif
377     if ((unsigned)args->fd >= fdp->fd_nfiles
378 	|| (fp = fdp->fd_ofiles[args->fd]) == 0)
379 	return EBADF;
380 
381     if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
382 	return EBADF;
383     }
384 
385     func = fp->f_ops->fo_ioctl;
386     switch (args->cmd) {
387     case LINUX_TCGETS:
388 	if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
389 	    return error;
390 	bsd_to_linux_termios(&bsd_termios, &linux_termios);
391 	return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
392 		       sizeof(linux_termios));
393 
394     case LINUX_TCSETS:
395 	linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
396 	return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
397 
398     case LINUX_TCSETSW:
399 	linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
400 	return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
401 
402     case LINUX_TCSETSF:
403 	linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
404 	return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
405 
406     case LINUX_TIOCGPGRP:
407 	args->cmd = TIOCGPGRP;
408 	return ioctl(p, args, retval);
409 
410     case LINUX_TIOCSPGRP:
411 	args->cmd = TIOCSPGRP;
412 	return ioctl(p, args, retval);
413 
414     case LINUX_TIOCGWINSZ:
415 	args->cmd = TIOCGWINSZ;
416 	return ioctl(p, args, retval);
417 
418     case LINUX_TIOCSWINSZ:
419 	args->cmd = TIOCSWINSZ;
420 	return ioctl(p, args, retval);
421 
422     case LINUX_FIONREAD:
423 	args->cmd = FIONREAD;
424 	return ioctl(p, args, retval);
425 
426     case LINUX_FIONBIO:
427 	args->cmd = FIONBIO;
428 	return ioctl(p, args, retval);
429 
430     case LINUX_FIOASYNC:
431 	args->cmd = FIOASYNC;
432 	return ioctl(p, args, retval);
433 
434     case LINUX_FIONCLEX:
435 	args->cmd = FIONCLEX;
436 	return ioctl(p, args, retval);
437 
438     case LINUX_FIOCLEX:
439 	args->cmd = FIOCLEX;
440 	return ioctl(p, args, retval);
441 
442     case LINUX_TIOCEXCL:
443 	args->cmd = TIOCEXCL;
444 	return ioctl(p, args, retval);
445 
446     case LINUX_TIOCNXCL:
447 	args->cmd = TIOCNXCL;
448 	return ioctl(p, args, retval);
449 
450     case LINUX_TIOCCONS:
451 	args->cmd = TIOCCONS;
452 	return ioctl(p, args, retval);
453 
454     case LINUX_TIOCNOTTY:
455 	args->cmd = TIOCNOTTY;
456 	return ioctl(p, args, retval);
457 
458     case LINUX_TIOCSETD:
459 	switch (args->arg) {
460 	case LINUX_N_TTY:
461 	    bsd_line = TTYDISC;
462 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
463 	case LINUX_N_SLIP:
464 	    bsd_line = SLIPDISC;
465 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
466 	case LINUX_N_PPP:
467 	    bsd_line = PPPDISC;
468 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
469 	default:
470 	    return EINVAL;
471 	}
472 	break;
473 
474     case LINUX_TIOCGETD:
475 	bsd_line = TTYDISC;
476 	if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p))
477 	    return error;
478 	switch (bsd_line) {
479 	case TTYDISC:
480 	    linux_line = LINUX_N_TTY;
481 	    break;
482 	case SLIPDISC:
483 	    linux_line = LINUX_N_SLIP;
484 	    break;
485 	case PPPDISC:
486 	    linux_line = LINUX_N_PPP;
487 	    break;
488 	default:
489 	    return EINVAL;
490 	}
491 	return copyout(&linux_line, (caddr_t)args->arg,
492 		       sizeof(int));
493     }
494     uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
495 	    args->fd, (args->cmd&0xffff00)>>8,
496 	    (args->cmd&0xffff00)>>8, args->cmd&0xff);
497     return EINVAL;
498 }
499