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