]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/linux/linux_ioctl.c
This commit was generated by cvs2svn to compensate for changes in r53660,
[FreeBSD/FreeBSD.git] / sys / i386 / linux / linux_ioctl.c
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  * $FreeBSD$
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/cdio.h>
36 #include <sys/fcntl.h>
37 #include <sys/file.h>
38 #include <sys/filedesc.h>
39 #include <sys/filio.h>
40 #include <sys/tty.h>
41 #include <sys/socket.h>
42 #include <net/if.h>
43 #include <net/if_dl.h>
44 #include <net/if_types.h>
45 #include <sys/sockio.h>
46 #include <sys/soundcard.h>
47
48 #include <machine/console.h>
49
50 #include <i386/linux/linux.h>
51 #include <i386/linux/linux_proto.h>
52 #include <i386/linux/linux_util.h>
53 #include <i386/linux/linux_mib.h>
54
55 #define ISSIGVALID(sig)         ((sig) > 0 && (sig) < NSIG)
56
57 struct linux_termio {
58     unsigned short c_iflag;
59     unsigned short c_oflag;
60     unsigned short c_cflag;
61     unsigned short c_lflag;
62     unsigned char c_line;
63     unsigned char c_cc[LINUX_NCC];
64 };
65
66
67 struct linux_termios {
68     unsigned int    c_iflag;
69     unsigned int    c_oflag;
70     unsigned int    c_cflag;
71     unsigned int    c_lflag;
72     unsigned char   c_line;
73     unsigned char   c_cc[LINUX_NCCS];
74 };
75
76 struct linux_winsize {
77     unsigned short ws_row, ws_col;
78     unsigned short ws_xpixel, ws_ypixel;
79 };
80
81 static struct speedtab sptab[] = {
82     { B0, LINUX_B0 }, { B50, LINUX_B50 },
83     { B75, LINUX_B75 }, { B110, LINUX_B110 },
84     { B134, LINUX_B134 }, { B150, LINUX_B150 },
85     { B200, LINUX_B200 }, { B300, LINUX_B300 },
86     { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
87     { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
88     { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
89     { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
90     { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
91     {-1, -1 }
92 };
93
94 struct linux_serial_struct {
95         int     type;
96         int     line;
97         int     port;
98         int     irq;
99         int     flags;
100         int     xmit_fifo_size;
101         int     custom_divisor;
102         int     baud_base;
103         unsigned short  close_delay;
104         char    reserved_char[2];
105         int     hub6;
106         unsigned short  closing_wait;
107         unsigned short  closing_wait2;
108         int     reserved[4];
109 };
110
111
112 static int
113 linux_to_bsd_speed(int code, struct speedtab *table)
114 {
115     for ( ; table->sp_code != -1; table++)
116         if (table->sp_code == code)
117             return (table->sp_speed);
118     return -1;
119 }
120
121 static int
122 bsd_to_linux_speed(int speed, struct speedtab *table)
123 {
124     for ( ; table->sp_speed != -1; table++)
125         if (table->sp_speed == speed)
126             return (table->sp_code);
127     return -1;
128 }
129
130 static void
131 bsd_to_linux_termios(struct termios *bsd_termios, 
132                 struct linux_termios *linux_termios)
133 {
134     int i;
135
136 #ifdef DEBUG
137     printf("LINUX: BSD termios structure (input):\n");
138     printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
139            bsd_termios->c_iflag, bsd_termios->c_oflag,
140            bsd_termios->c_cflag, bsd_termios->c_lflag,
141            bsd_termios->c_ispeed, bsd_termios->c_ospeed);
142     printf("c_cc ");
143     for (i=0; i<NCCS; i++)
144         printf("%02x ", bsd_termios->c_cc[i]);
145     printf("\n");
146 #endif
147     linux_termios->c_iflag = 0;
148     if (bsd_termios->c_iflag & IGNBRK)
149         linux_termios->c_iflag |= LINUX_IGNBRK;
150     if (bsd_termios->c_iflag & BRKINT)
151         linux_termios->c_iflag |= LINUX_BRKINT;
152     if (bsd_termios->c_iflag & IGNPAR)
153         linux_termios->c_iflag |= LINUX_IGNPAR;
154     if (bsd_termios->c_iflag & PARMRK)
155         linux_termios->c_iflag |= LINUX_PARMRK;
156     if (bsd_termios->c_iflag & INPCK)
157         linux_termios->c_iflag |= LINUX_INPCK;
158     if (bsd_termios->c_iflag & ISTRIP)
159         linux_termios->c_iflag |= LINUX_ISTRIP;
160     if (bsd_termios->c_iflag & INLCR)
161         linux_termios->c_iflag |= LINUX_INLCR;
162     if (bsd_termios->c_iflag & IGNCR)
163         linux_termios->c_iflag |= LINUX_IGNCR;
164     if (bsd_termios->c_iflag & ICRNL)
165         linux_termios->c_iflag |= LINUX_ICRNL;
166     if (bsd_termios->c_iflag & IXON)
167         linux_termios->c_iflag |= LINUX_IXON;
168     if (bsd_termios->c_iflag & IXANY)
169         linux_termios->c_iflag |= LINUX_IXANY;
170     if (bsd_termios->c_iflag & IXOFF)
171         linux_termios->c_iflag |= LINUX_IXOFF;
172     if (bsd_termios->c_iflag & IMAXBEL)
173         linux_termios->c_iflag |= LINUX_IMAXBEL;
174
175     linux_termios->c_oflag = 0;
176     if (bsd_termios->c_oflag & OPOST)
177         linux_termios->c_oflag |= LINUX_OPOST;
178     if (bsd_termios->c_oflag & ONLCR)
179         linux_termios->c_oflag |= LINUX_ONLCR;
180     if (bsd_termios->c_oflag & OXTABS)
181         linux_termios->c_oflag |= LINUX_XTABS;
182
183     linux_termios->c_cflag =
184         bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
185     linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
186     if (bsd_termios->c_cflag & CSTOPB)
187         linux_termios->c_cflag |= LINUX_CSTOPB;
188     if (bsd_termios->c_cflag & CREAD)
189         linux_termios->c_cflag |= LINUX_CREAD;
190     if (bsd_termios->c_cflag & PARENB)
191         linux_termios->c_cflag |= LINUX_PARENB;
192     if (bsd_termios->c_cflag & PARODD)
193         linux_termios->c_cflag |= LINUX_PARODD;
194     if (bsd_termios->c_cflag & HUPCL)
195         linux_termios->c_cflag |= LINUX_HUPCL;
196     if (bsd_termios->c_cflag & CLOCAL)
197         linux_termios->c_cflag |= LINUX_CLOCAL;
198     if (bsd_termios->c_cflag & CRTSCTS)
199         linux_termios->c_cflag |= LINUX_CRTSCTS;
200
201     linux_termios->c_lflag = 0;
202     if (bsd_termios->c_lflag & ISIG)
203         linux_termios->c_lflag |= LINUX_ISIG;
204     if (bsd_termios->c_lflag & ICANON)
205         linux_termios->c_lflag |= LINUX_ICANON;
206     if (bsd_termios->c_lflag & ECHO)
207         linux_termios->c_lflag |= LINUX_ECHO;
208     if (bsd_termios->c_lflag & ECHOE)
209         linux_termios->c_lflag |= LINUX_ECHOE;
210     if (bsd_termios->c_lflag & ECHOK)
211         linux_termios->c_lflag |= LINUX_ECHOK;
212     if (bsd_termios->c_lflag & ECHONL)
213         linux_termios->c_lflag |= LINUX_ECHONL;
214     if (bsd_termios->c_lflag & NOFLSH)
215         linux_termios->c_lflag |= LINUX_NOFLSH;
216     if (bsd_termios->c_lflag & TOSTOP)
217         linux_termios->c_lflag |= LINUX_TOSTOP;
218     if (bsd_termios->c_lflag & ECHOCTL)
219         linux_termios->c_lflag |= LINUX_ECHOCTL;
220     if (bsd_termios->c_lflag & ECHOPRT)
221         linux_termios->c_lflag |= LINUX_ECHOPRT;
222     if (bsd_termios->c_lflag & ECHOKE)
223         linux_termios->c_lflag |= LINUX_ECHOKE;
224     if (bsd_termios->c_lflag & FLUSHO)
225         linux_termios->c_lflag |= LINUX_FLUSHO;
226     if (bsd_termios->c_lflag & PENDIN)
227         linux_termios->c_lflag |= LINUX_PENDIN;
228     if (bsd_termios->c_lflag & IEXTEN)
229         linux_termios->c_lflag |= LINUX_IEXTEN;
230
231     for (i=0; i<LINUX_NCCS; i++) 
232         linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE;
233     linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
234     linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
235     linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
236     linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
237     linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
238     linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
239     linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
240     linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
241     linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
242     linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
243     linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
244     linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
245     linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
246     linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
247     linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
248     linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
249
250     for (i=0; i<LINUX_NCCS; i++) {
251       if (linux_termios->c_cc[i] == _POSIX_VDISABLE)
252         linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE;
253     }
254
255     linux_termios->c_line = 0;
256 #ifdef DEBUG
257     printf("LINUX: LINUX termios structure (output):\n");
258     printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
259         linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag,
260         linux_termios->c_lflag, (int)linux_termios->c_line);
261     printf("c_cc ");
262     for (i=0; i<LINUX_NCCS; i++) 
263         printf("%02x ", linux_termios->c_cc[i]);
264     printf("\n");
265 #endif
266 }
267
268
269 static void
270 linux_to_bsd_termios(struct linux_termios *linux_termios,
271                 struct termios *bsd_termios)
272 {
273     int i;
274 #ifdef DEBUG
275     printf("LINUX: LINUX termios structure (input):\n");
276     printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
277         linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag,
278         linux_termios->c_lflag, (int)linux_termios->c_line);
279     printf("c_cc ");
280     for (i=0; i<LINUX_NCCS; i++) 
281         printf("%02x ", linux_termios->c_cc[i]);
282     printf("\n");
283 #endif
284     bsd_termios->c_iflag = 0;
285     if (linux_termios->c_iflag & LINUX_IGNBRK)
286         bsd_termios->c_iflag |= IGNBRK;
287     if (linux_termios->c_iflag & LINUX_BRKINT)
288         bsd_termios->c_iflag |= BRKINT;
289     if (linux_termios->c_iflag & LINUX_IGNPAR)
290         bsd_termios->c_iflag |= IGNPAR;
291     if (linux_termios->c_iflag & LINUX_PARMRK)
292         bsd_termios->c_iflag |= PARMRK;
293     if (linux_termios->c_iflag & LINUX_INPCK)
294         bsd_termios->c_iflag |= INPCK;
295     if (linux_termios->c_iflag & LINUX_ISTRIP)
296         bsd_termios->c_iflag |= ISTRIP;
297     if (linux_termios->c_iflag & LINUX_INLCR)
298         bsd_termios->c_iflag |= INLCR;
299     if (linux_termios->c_iflag & LINUX_IGNCR)
300         bsd_termios->c_iflag |= IGNCR;
301     if (linux_termios->c_iflag & LINUX_ICRNL)
302         bsd_termios->c_iflag |= ICRNL;
303     if (linux_termios->c_iflag & LINUX_IXON)
304         bsd_termios->c_iflag |= IXON;
305     if (linux_termios->c_iflag & LINUX_IXANY)
306         bsd_termios->c_iflag |= IXANY;
307     if (linux_termios->c_iflag & LINUX_IXOFF)
308         bsd_termios->c_iflag |= IXOFF;
309     if (linux_termios->c_iflag & LINUX_IMAXBEL)
310         bsd_termios->c_iflag |= IMAXBEL;
311
312     bsd_termios->c_oflag = 0;
313     if (linux_termios->c_oflag & LINUX_OPOST)
314         bsd_termios->c_oflag |= OPOST;
315     if (linux_termios->c_oflag & LINUX_ONLCR)
316         bsd_termios->c_oflag |= ONLCR;
317     if (linux_termios->c_oflag & LINUX_XTABS)
318         bsd_termios->c_oflag |= OXTABS;
319
320     bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
321     if (linux_termios->c_cflag & LINUX_CSTOPB)
322         bsd_termios->c_cflag |= CSTOPB;
323     if (linux_termios->c_cflag & LINUX_CREAD)
324         bsd_termios->c_cflag |= CREAD;
325     if (linux_termios->c_cflag & LINUX_PARENB)
326         bsd_termios->c_cflag |= PARENB;
327     if (linux_termios->c_cflag & LINUX_PARODD)
328         bsd_termios->c_cflag |= PARODD;
329     if (linux_termios->c_cflag & LINUX_HUPCL)
330         bsd_termios->c_cflag |= HUPCL;
331     if (linux_termios->c_cflag & LINUX_CLOCAL)
332         bsd_termios->c_cflag |= CLOCAL;
333     if (linux_termios->c_cflag & LINUX_CRTSCTS)
334         bsd_termios->c_cflag |= CRTSCTS;
335
336     bsd_termios->c_lflag = 0;
337     if (linux_termios->c_lflag & LINUX_ISIG)
338         bsd_termios->c_lflag |= ISIG;
339     if (linux_termios->c_lflag & LINUX_ICANON)
340         bsd_termios->c_lflag |= ICANON;
341     if (linux_termios->c_lflag & LINUX_ECHO)
342         bsd_termios->c_lflag |= ECHO;
343     if (linux_termios->c_lflag & LINUX_ECHOE)
344         bsd_termios->c_lflag |= ECHOE;
345     if (linux_termios->c_lflag & LINUX_ECHOK)
346         bsd_termios->c_lflag |= ECHOK;
347     if (linux_termios->c_lflag & LINUX_ECHONL)
348         bsd_termios->c_lflag |= ECHONL;
349     if (linux_termios->c_lflag & LINUX_NOFLSH)
350         bsd_termios->c_lflag |= NOFLSH;
351     if (linux_termios->c_lflag & LINUX_TOSTOP)
352         bsd_termios->c_lflag |= TOSTOP;
353     if (linux_termios->c_lflag & LINUX_ECHOCTL)
354         bsd_termios->c_lflag |= ECHOCTL;
355     if (linux_termios->c_lflag & LINUX_ECHOPRT)
356         bsd_termios->c_lflag |= ECHOPRT;
357     if (linux_termios->c_lflag & LINUX_ECHOKE)
358         bsd_termios->c_lflag |= ECHOKE;
359     if (linux_termios->c_lflag & LINUX_FLUSHO)
360         bsd_termios->c_lflag |= FLUSHO;
361     if (linux_termios->c_lflag & LINUX_PENDIN)
362         bsd_termios->c_lflag |= PENDIN;
363     if (linux_termios->c_lflag & LINUX_IEXTEN)
364         bsd_termios->c_lflag |= IEXTEN;
365
366     for (i=0; i<NCCS; i++)
367         bsd_termios->c_cc[i] = _POSIX_VDISABLE;
368     bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
369     bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
370     bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
371     bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
372     bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
373     bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
374     bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
375     bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
376     bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
377     bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
378     bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
379     bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
380     bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
381     bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
382     bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
383     bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
384
385     for (i=0; i<NCCS; i++) {
386       if (bsd_termios->c_cc[i] == LINUX_POSIX_VDISABLE)
387         bsd_termios->c_cc[i] = _POSIX_VDISABLE;
388     }
389
390     bsd_termios->c_ispeed = bsd_termios->c_ospeed =
391         linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
392 #ifdef DEBUG
393         printf("LINUX: BSD termios structure (output):\n");
394         printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
395                bsd_termios->c_iflag, bsd_termios->c_oflag,
396                bsd_termios->c_cflag, bsd_termios->c_lflag,
397                bsd_termios->c_ispeed, bsd_termios->c_ospeed);
398         printf("c_cc ");
399         for (i=0; i<NCCS; i++) 
400             printf("%02x ", bsd_termios->c_cc[i]);
401         printf("\n");
402 #endif
403 }
404
405
406 static void
407 bsd_to_linux_termio(struct termios *bsd_termios, 
408                 struct linux_termio *linux_termio)
409 {
410   struct linux_termios tmios;
411
412   bsd_to_linux_termios(bsd_termios, &tmios);
413   linux_termio->c_iflag = tmios.c_iflag;
414   linux_termio->c_oflag = tmios.c_oflag;
415   linux_termio->c_cflag = tmios.c_cflag;
416   linux_termio->c_lflag = tmios.c_lflag;
417   linux_termio->c_line  = tmios.c_line;
418   memcpy(linux_termio->c_cc, tmios.c_cc, LINUX_NCC);
419 }
420
421 static void
422 linux_to_bsd_termio(struct linux_termio *linux_termio,
423                 struct termios *bsd_termios)
424 {
425   struct linux_termios tmios;
426   int i;
427
428   tmios.c_iflag = linux_termio->c_iflag;
429   tmios.c_oflag = linux_termio->c_oflag;
430   tmios.c_cflag = linux_termio->c_cflag;
431   tmios.c_lflag = linux_termio->c_lflag;
432
433   for (i=LINUX_NCC; i<LINUX_NCCS; i++)
434     tmios.c_cc[i] = LINUX_POSIX_VDISABLE;
435   memcpy(tmios.c_cc, linux_termio->c_cc, LINUX_NCC);
436
437   linux_to_bsd_termios(&tmios, bsd_termios);
438 }
439
440 struct linux_cdrom_msf
441 {
442     u_char      cdmsf_min0;
443     u_char      cdmsf_sec0;
444     u_char      cdmsf_frame0;
445     u_char      cdmsf_min1;
446     u_char      cdmsf_sec1;
447     u_char      cdmsf_frame1;
448 };
449
450 struct linux_cdrom_tochdr
451 {
452     u_char      cdth_trk0;
453     u_char      cdth_trk1;
454 };
455
456 union linux_cdrom_addr
457 {
458     struct {
459         u_char  minute;
460         u_char  second;
461         u_char  frame;
462     } msf;
463     int         lba;
464 };
465
466 struct linux_cdrom_tocentry
467 {
468     u_char      cdte_track;     
469     u_char      cdte_adr:4;
470     u_char      cdte_ctrl:4;
471     u_char      cdte_format;    
472     union linux_cdrom_addr cdte_addr;
473     u_char      cdte_datamode;  
474 };
475
476 struct linux_cdrom_subchnl
477 {
478     u_char      cdsc_format;
479     u_char      cdsc_audiostatus;
480     u_char      cdsc_adr:4;
481     u_char      cdsc_ctrl:4;
482     u_char      cdsc_trk;
483     u_char      cdsc_ind;
484     union linux_cdrom_addr cdsc_absaddr;
485     union linux_cdrom_addr cdsc_reladdr;
486 };
487
488 #if 0
489 static void
490 linux_to_bsd_msf_lba(u_char address_format,
491     union linux_cdrom_addr *lp, union msf_lba *bp)
492 {
493     if (address_format == CD_LBA_FORMAT)
494         bp->lba = lp->lba;
495     else {
496         bp->msf.minute = lp->msf.minute;
497         bp->msf.second = lp->msf.second;
498         bp->msf.frame = lp->msf.frame;
499     }
500 }
501 #endif
502
503 static void
504 bsd_to_linux_msf_lba(u_char address_format,
505     union msf_lba *bp, union linux_cdrom_addr *lp)
506 {
507     if (address_format == CD_LBA_FORMAT)
508         lp->lba = bp->lba;
509     else {
510         lp->msf.minute = bp->msf.minute;
511         lp->msf.second = bp->msf.second;
512         lp->msf.frame = bp->msf.frame;
513     }
514 }
515
516 static void
517 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
518 {
519     if (format == LINUX_CDROM_MSF) {
520         addr->msf.frame = lba % 75;
521         lba /= 75;
522         lba += 2;
523         addr->msf.second = lba % 60;
524         addr->msf.minute = lba / 60;
525     }
526     else
527         addr->lba = lba;
528 }
529
530 static unsigned dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
531
532 #define SETDIR(c)       (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
533
534 int
535 linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
536 {
537     struct termios bsd_termios;
538     struct linux_termios linux_termios;
539     struct linux_termio linux_termio;
540     struct filedesc *fdp = p->p_fd;
541     struct file *fp;
542     int bsd_line, linux_line;
543     int error;
544
545 #ifdef DEBUG
546     printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", 
547         (long)p->p_pid, args->fd, args->cmd);
548 #endif
549     if ((unsigned)args->fd >= fdp->fd_nfiles 
550         || (fp = fdp->fd_ofiles[args->fd]) == 0)
551         return EBADF;
552
553     if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
554         return EBADF;
555     }
556
557     switch (args->cmd & 0xffff) {
558
559     case LINUX_TCGETA:
560         if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
561             return error;
562         bsd_to_linux_termio(&bsd_termios, &linux_termio);
563         return copyout((caddr_t)&linux_termio, (caddr_t)args->arg,
564                        sizeof(linux_termio));
565
566     case LINUX_TCSETA:
567         error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
568         if (error)
569             return error;
570         linux_to_bsd_termio(&linux_termio, &bsd_termios);
571         return fo_ioctl(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
572
573     case LINUX_TCSETAW:
574         error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
575         if (error)
576             return error;
577         linux_to_bsd_termio(&linux_termio, &bsd_termios);
578         return fo_ioctl(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
579
580     case LINUX_TCSETAF:
581         error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
582         if (error)
583             return error;
584         linux_to_bsd_termio(&linux_termio, &bsd_termios);
585         return fo_ioctl(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
586
587     case LINUX_TCGETS:
588         if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
589             return error;
590         bsd_to_linux_termios(&bsd_termios, &linux_termios);
591         return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
592                        sizeof(linux_termios));
593
594     case LINUX_TCSETS:
595         error = copyin((caddr_t)args->arg, &linux_termios,
596                        sizeof(linux_termios));
597         if (error)
598             return error;
599         linux_to_bsd_termios(&linux_termios, &bsd_termios);
600         return fo_ioctl(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
601
602     case LINUX_TCSETSW:
603         error = copyin((caddr_t)args->arg, &linux_termios,
604                        sizeof(linux_termios));
605         if (error)
606             return error;
607         linux_to_bsd_termios(&linux_termios, &bsd_termios);
608         return fo_ioctl(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
609
610     case LINUX_TCSETSF:
611         error = copyin((caddr_t)args->arg, &linux_termios,
612                        sizeof(linux_termios));
613         if (error)
614             return error;
615         linux_to_bsd_termios(&linux_termios, &bsd_termios);
616         return fo_ioctl(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
617             
618     case LINUX_TIOCGPGRP:
619         args->cmd = TIOCGPGRP;
620         return ioctl(p, (struct ioctl_args *)args);
621
622     case LINUX_TIOCSPGRP:
623         args->cmd = TIOCSPGRP;
624         return ioctl(p, (struct ioctl_args *)args);
625
626     case LINUX_TIOCGWINSZ:
627         args->cmd = TIOCGWINSZ;
628         return ioctl(p, (struct ioctl_args *)args);
629
630     case LINUX_TIOCSWINSZ:
631         args->cmd = TIOCSWINSZ;
632         return ioctl(p, (struct ioctl_args *)args);
633
634     case LINUX_TIOCMGET:
635         args->cmd = TIOCMGET;
636         return ioctl(p, (struct ioctl_args *)args);
637
638     case LINUX_TIOCMBIS:
639         args->cmd = TIOCMBIS;
640         return ioctl(p, (struct ioctl_args *)args);
641
642     case LINUX_TIOCMBIC:
643         args->cmd = TIOCMBIC;
644         return ioctl(p, (struct ioctl_args *)args);
645
646     case LINUX_TIOCMSET:
647         args->cmd = TIOCMSET;
648         return ioctl(p, (struct ioctl_args *)args);
649
650     case LINUX_FIONREAD:
651         args->cmd = FIONREAD;
652         return ioctl(p, (struct ioctl_args *)args);
653
654     case LINUX_FIONBIO:
655         args->cmd = FIONBIO;
656         return ioctl(p, (struct ioctl_args *)args);
657
658     case LINUX_FIOASYNC:
659         args->cmd = FIOASYNC;
660         return ioctl(p, (struct ioctl_args *)args);
661
662     case LINUX_FIONCLEX:
663         args->cmd = FIONCLEX;
664         return ioctl(p, (struct ioctl_args *)args);
665
666     case LINUX_FIOCLEX:
667         args->cmd = FIOCLEX;
668         return ioctl(p, (struct ioctl_args *)args);
669
670     case LINUX_TIOCEXCL:
671         args->cmd = TIOCEXCL;
672         return ioctl(p, (struct ioctl_args *)args);
673
674     case LINUX_TIOCNXCL:
675         args->cmd = TIOCNXCL;
676         return ioctl(p, (struct ioctl_args *)args);
677
678     case LINUX_TIOCCONS:
679         args->cmd = TIOCCONS;
680         return ioctl(p, (struct ioctl_args *)args);
681
682     case LINUX_TIOCNOTTY:
683         args->cmd = TIOCNOTTY;
684         return ioctl(p, (struct ioctl_args *)args);
685
686     case LINUX_SIOCGIFCONF:
687         args->cmd = OSIOCGIFCONF;
688         return ioctl(p, (struct ioctl_args *)args);
689
690     case LINUX_SIOCGIFFLAGS:
691         args->cmd = SIOCGIFFLAGS;
692         return ioctl(p, (struct ioctl_args *)args);
693
694     case LINUX_SIOCGIFADDR:
695         args->cmd = OSIOCGIFADDR;
696         return ioctl(p, (struct ioctl_args *)args);
697
698     case LINUX_SIOCGIFDSTADDR:
699         args->cmd = OSIOCGIFDSTADDR;
700         return ioctl(p, (struct ioctl_args *)args);
701
702     case LINUX_SIOCGIFBRDADDR:
703         args->cmd = OSIOCGIFBRDADDR;
704         return ioctl(p, (struct ioctl_args *)args);
705
706     case LINUX_SIOCGIFNETMASK:
707         args->cmd = OSIOCGIFNETMASK;
708         return ioctl(p, (struct ioctl_args *)args);
709
710         /* get hardware address */
711     case LINUX_SIOCGIFHWADDR:
712     {
713         int                     ifn;
714         struct ifnet            *ifp;
715         struct ifaddr           *ifa;
716         struct sockaddr_dl      *sdl;
717         struct linux_ifreq      *ifr = (struct linux_ifreq *)args->arg;
718
719         /* 
720          * Note that we don't actually respect the name in the ifreq structure, as
721          * Linux interface names are all different
722          */
723
724         for (ifn = 0; ifn < if_index; ifn++) {
725
726             ifp = ifnet_addrs[ifn]->ifa_ifp;    /* pointer to interface */
727             if (ifp->if_type == IFT_ETHER) {    /* looks good */
728                 /* walk the address list */
729                 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) {
730                     if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&  /* we have an address structure */
731                         (sdl->sdl_family == AF_LINK) &&                 /* it's a link address */
732                         (sdl->sdl_type == IFT_ETHER)) {                 /* for an ethernet link */
733
734                         return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN));
735                     }
736                 }
737             }
738         }
739         return(ENOENT);         /* ??? */
740     }
741
742     case LINUX_SIOCADDMULTI:
743         args->cmd = SIOCADDMULTI;
744         return ioctl(p, (struct ioctl_args *)args);
745
746     case LINUX_SIOCDELMULTI:
747         args->cmd = SIOCDELMULTI;
748         return ioctl(p, (struct ioctl_args *)args);
749
750     case LINUX_FIOSETOWN:
751         args->cmd = FIOSETOWN;
752         return ioctl(p, (struct ioctl_args *)args);
753
754     case LINUX_SIOCSPGRP:
755         args->cmd = SIOCSPGRP;
756         return ioctl(p, (struct ioctl_args *)args);
757
758     case LINUX_FIOGETOWN:
759         args->cmd = FIOGETOWN;
760         return ioctl(p, (struct ioctl_args *)args);
761
762     case LINUX_SIOCGPGRP:
763         args->cmd = SIOCGPGRP;
764         return ioctl(p, (struct ioctl_args *)args);
765
766     case LINUX_SIOCATMARK:
767         args->cmd = SIOCATMARK;
768         return ioctl(p, (struct ioctl_args *)args);
769
770     case LINUX_TIOCSETD:
771         switch (args->arg) {
772         case LINUX_N_TTY:
773             bsd_line = TTYDISC;
774             return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p);
775         case LINUX_N_SLIP:
776             bsd_line = SLIPDISC;
777             return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p);
778         case LINUX_N_PPP:
779             bsd_line = PPPDISC;
780             return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p);
781         default:
782             return EINVAL;
783         }
784
785     case LINUX_TIOCGETD:
786         bsd_line = TTYDISC;
787         error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, p);
788         if (error)
789             return error;
790         switch (bsd_line) {
791         case TTYDISC:
792             linux_line = LINUX_N_TTY;
793             break;
794         case SLIPDISC:
795             linux_line = LINUX_N_SLIP;
796             break;
797         case PPPDISC:
798             linux_line = LINUX_N_PPP;
799             break;
800         default:
801             return EINVAL;
802         }
803         return copyout(&linux_line, (caddr_t)args->arg, 
804                        sizeof(int));
805
806     case LINUX_SNDCTL_SEQ_RESET:
807         args->cmd = SNDCTL_SEQ_RESET;
808         return ioctl(p, (struct ioctl_args *)args);
809
810     case LINUX_SNDCTL_SEQ_SYNC:
811         args->cmd = SNDCTL_SEQ_SYNC;
812         return ioctl(p, (struct ioctl_args *)args);
813
814     case LINUX_SNDCTL_SYNTH_INFO:
815         args->cmd = SNDCTL_SYNTH_INFO;
816         return ioctl(p, (struct ioctl_args *)args);
817
818     case LINUX_SNDCTL_SEQ_CTRLRATE:
819         args->cmd = SNDCTL_SEQ_CTRLRATE;
820         return ioctl(p, (struct ioctl_args *)args);
821
822     case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
823         args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
824         return ioctl(p, (struct ioctl_args *)args);
825
826     case LINUX_SNDCTL_SEQ_GETINCOUNT:
827         args->cmd = SNDCTL_SEQ_GETINCOUNT;
828         return ioctl(p, (struct ioctl_args *)args);
829
830     case LINUX_SNDCTL_SEQ_PERCMODE:
831         args->cmd = SNDCTL_SEQ_PERCMODE;
832         return ioctl(p, (struct ioctl_args *)args);
833
834     case LINUX_SNDCTL_FM_LOAD_INSTR:
835         args->cmd = SNDCTL_FM_LOAD_INSTR;
836         return ioctl(p, (struct ioctl_args *)args);
837
838     case LINUX_SNDCTL_SEQ_TESTMIDI:
839         args->cmd = SNDCTL_SEQ_TESTMIDI;
840         return ioctl(p, (struct ioctl_args *)args);
841
842     case LINUX_SNDCTL_SEQ_RESETSAMPLES:
843         args->cmd = SNDCTL_SEQ_RESETSAMPLES;
844         return ioctl(p, (struct ioctl_args *)args);
845
846     case LINUX_SNDCTL_SEQ_NRSYNTHS:
847         args->cmd = SNDCTL_SEQ_NRSYNTHS;
848         return ioctl(p, (struct ioctl_args *)args);
849
850     case LINUX_SNDCTL_SEQ_NRMIDIS:
851         args->cmd = SNDCTL_SEQ_NRMIDIS;
852         return ioctl(p, (struct ioctl_args *)args);
853
854     case LINUX_SNDCTL_MIDI_INFO:
855         args->cmd = SNDCTL_MIDI_INFO;
856         return ioctl(p, (struct ioctl_args *)args);
857
858     case LINUX_SNDCTL_SEQ_TRESHOLD:
859         args->cmd = SNDCTL_SEQ_TRESHOLD;
860         return ioctl(p, (struct ioctl_args *)args);
861
862     case LINUX_SNDCTL_SYNTH_MEMAVL:
863         args->cmd = SNDCTL_SYNTH_MEMAVL;
864         return ioctl(p, (struct ioctl_args *)args);
865
866     case LINUX_SNDCTL_DSP_GETOPTR :
867         args->cmd = SNDCTL_DSP_GETOPTR;
868         return ioctl(p, (struct ioctl_args *)args);
869
870     case LINUX_SNDCTL_DSP_GETIPTR :
871         args->cmd = SNDCTL_DSP_GETIPTR;
872         return ioctl(p, (struct ioctl_args *)args);
873
874     case LINUX_SNDCTL_DSP_SETTRIGGER:
875         args->cmd = SNDCTL_DSP_SETTRIGGER;
876         return ioctl(p, (struct ioctl_args *)args);
877
878     case LINUX_SNDCTL_DSP_GETCAPS:
879         args->cmd = SNDCTL_DSP_GETCAPS;
880         return ioctl(p, (struct ioctl_args *)args);
881
882     case LINUX_SNDCTL_DSP_RESET:
883         args->cmd = SNDCTL_DSP_RESET;
884         return ioctl(p, (struct ioctl_args *)args);
885
886     case LINUX_SNDCTL_DSP_SYNC:
887         args->cmd = SNDCTL_DSP_SYNC;
888         return ioctl(p, (struct ioctl_args *)args);
889
890     case LINUX_SNDCTL_DSP_SPEED:
891         args->cmd = SNDCTL_DSP_SPEED;
892         return ioctl(p, (struct ioctl_args *)args);
893
894     case LINUX_SNDCTL_DSP_STEREO:
895         args->cmd = SNDCTL_DSP_STEREO;
896         return ioctl(p, (struct ioctl_args *)args);
897
898     case LINUX_SNDCTL_DSP_GETBLKSIZE:
899       /* LINUX_SNDCTL_DSP_SETBLKSIZE */
900         args->cmd = SNDCTL_DSP_GETBLKSIZE;
901         return ioctl(p, (struct ioctl_args *)args);
902
903     case LINUX_SNDCTL_DSP_SETFMT:
904         args->cmd = SNDCTL_DSP_SETFMT;
905         return ioctl(p, (struct ioctl_args *)args);
906
907     case LINUX_SOUND_PCM_WRITE_CHANNELS:
908         args->cmd = SOUND_PCM_WRITE_CHANNELS;
909         return ioctl(p, (struct ioctl_args *)args);
910
911     case LINUX_SOUND_PCM_WRITE_FILTER:
912         args->cmd = SOUND_PCM_WRITE_FILTER;
913         return ioctl(p, (struct ioctl_args *)args);
914
915     case LINUX_SNDCTL_DSP_POST:
916         args->cmd = SNDCTL_DSP_POST;
917         return ioctl(p, (struct ioctl_args *)args);
918
919     case LINUX_SNDCTL_DSP_SUBDIVIDE:
920         args->cmd = SNDCTL_DSP_SUBDIVIDE;
921         return ioctl(p, (struct ioctl_args *)args);
922
923     case LINUX_SNDCTL_DSP_SETFRAGMENT:
924         args->cmd = SNDCTL_DSP_SETFRAGMENT;
925         return ioctl(p, (struct ioctl_args *)args);
926
927     case LINUX_SNDCTL_DSP_GETFMTS:
928         args->cmd = SNDCTL_DSP_GETFMTS;
929         return ioctl(p, (struct ioctl_args *)args);
930
931     case LINUX_SNDCTL_DSP_GETOSPACE:
932         args->cmd = SNDCTL_DSP_GETOSPACE;
933         return ioctl(p, (struct ioctl_args *)args);
934
935     case LINUX_SNDCTL_DSP_GETISPACE:
936         args->cmd = SNDCTL_DSP_GETISPACE;
937         return ioctl(p, (struct ioctl_args *)args);
938
939     case LINUX_SNDCTL_DSP_NONBLOCK:
940         args->cmd = SNDCTL_DSP_NONBLOCK;
941         return ioctl(p, (struct ioctl_args *)args);
942
943     case LINUX_SOUND_MIXER_WRITE_VOLUME:
944         args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
945         return ioctl(p, (struct ioctl_args *)args);
946
947     case LINUX_SOUND_MIXER_WRITE_BASS:
948         args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
949         return ioctl(p, (struct ioctl_args *)args);
950
951     case LINUX_SOUND_MIXER_WRITE_TREBLE:
952         args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
953         return ioctl(p, (struct ioctl_args *)args);
954
955     case LINUX_SOUND_MIXER_WRITE_SYNTH:
956         args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
957         return ioctl(p, (struct ioctl_args *)args);
958
959     case LINUX_SOUND_MIXER_WRITE_PCM:
960         args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
961         return ioctl(p, (struct ioctl_args *)args);
962
963     case LINUX_SOUND_MIXER_WRITE_SPEAKER:
964         args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
965         return ioctl(p, (struct ioctl_args *)args);
966
967     case LINUX_SOUND_MIXER_WRITE_LINE:
968         args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
969         return ioctl(p, (struct ioctl_args *)args);
970
971     case LINUX_SOUND_MIXER_WRITE_MIC:
972         args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
973         return ioctl(p, (struct ioctl_args *)args);
974
975     case LINUX_SOUND_MIXER_WRITE_CD:
976         args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
977         return ioctl(p, (struct ioctl_args *)args);
978
979     case LINUX_SOUND_MIXER_WRITE_IMIX:
980         args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
981         return ioctl(p, (struct ioctl_args *)args);
982
983     case LINUX_SOUND_MIXER_WRITE_ALTPCM:
984         args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
985         return ioctl(p, (struct ioctl_args *)args);
986
987     case LINUX_SOUND_MIXER_WRITE_RECLEV:
988         args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
989         return ioctl(p, (struct ioctl_args *)args);
990
991     case LINUX_SOUND_MIXER_WRITE_IGAIN:
992         args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
993         return ioctl(p, (struct ioctl_args *)args);
994
995     case LINUX_SOUND_MIXER_WRITE_OGAIN:
996         args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
997         return ioctl(p, (struct ioctl_args *)args);
998
999     case LINUX_SOUND_MIXER_WRITE_LINE1:
1000         args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
1001         return ioctl(p, (struct ioctl_args *)args);
1002
1003     case LINUX_SOUND_MIXER_WRITE_LINE2:
1004         args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
1005         return ioctl(p, (struct ioctl_args *)args);
1006
1007     case LINUX_SOUND_MIXER_WRITE_LINE3:
1008         args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
1009         return ioctl(p, (struct ioctl_args *)args);
1010
1011     case LINUX_SOUND_MIXER_READ_DEVMASK:
1012         args->cmd = SOUND_MIXER_READ_DEVMASK;
1013         return ioctl(p, (struct ioctl_args *)args);
1014
1015     case LINUX_TIOCGSERIAL: {
1016         struct linux_serial_struct lss;
1017
1018         lss.type = LINUX_PORT_16550A;
1019         lss.flags = 0;
1020         lss.close_delay = 0;
1021         return copyout((caddr_t)&lss, (caddr_t)args->arg, sizeof(lss));
1022     }
1023
1024     case LINUX_TIOCSSERIAL: {
1025         struct linux_serial_struct lss;
1026
1027         error = copyin((caddr_t)args->arg, (caddr_t)&lss, sizeof(lss));
1028         if (error)
1029             return error;
1030         /*
1031          * XXX - It really helps to have an implementation that does nothing.
1032          *       NOT!
1033          */
1034         return 0;
1035     }
1036
1037     case LINUX_TCXONC:
1038       switch (args->arg) {
1039       case LINUX_TCOOFF:
1040               args->cmd = TIOCSTOP;
1041               break;
1042       case LINUX_TCOON:
1043               args->cmd = TIOCSTART;
1044               break;
1045       case LINUX_TCIOFF:
1046       case LINUX_TCION: {
1047               u_char c;
1048               struct write_args wr;
1049               error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p);
1050               if (error != 0)
1051                       return error;
1052               c = bsd_termios.c_cc[args->arg == LINUX_TCIOFF ? VSTOP : VSTART];
1053               if (c != _POSIX_VDISABLE) {
1054                       wr.fd = args->fd;
1055                       wr.buf = &c;
1056                       wr.nbyte = sizeof(c);
1057                       return write(p, &wr);
1058               }
1059               else
1060                       return (0);
1061       }
1062       default:
1063               return EINVAL;
1064       }
1065       args->arg = 0;
1066       return ioctl(p, (struct ioctl_args *)args);
1067       
1068     case LINUX_TCFLSH:
1069       args->cmd = TIOCFLUSH;
1070       switch (args->arg) {
1071         case LINUX_TCIFLUSH:
1072                 args->arg = FREAD;
1073                 break;
1074         case LINUX_TCOFLUSH:
1075                 args->arg = FWRITE;
1076                 break;
1077         case LINUX_TCIOFLUSH:
1078                 args->arg = FREAD | FWRITE;
1079                 break;
1080         default:
1081                 return EINVAL;
1082       }
1083       return ioctl(p, (struct ioctl_args *)args);
1084
1085    case LINUX_VT_OPENQRY:
1086
1087         args->cmd = VT_OPENQRY;
1088         return  ioctl(p, (struct ioctl_args *)args);
1089
1090     case LINUX_VT_GETMODE:
1091
1092         args->cmd = VT_GETMODE;
1093         return  ioctl(p, (struct ioctl_args *)args);
1094
1095     case LINUX_VT_SETMODE: 
1096       {
1097         struct vt_mode *mode;
1098         args->cmd = VT_SETMODE;
1099         mode = (struct vt_mode *)args->arg;
1100         if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig))
1101             mode->frsig = mode->acqsig;
1102         return ioctl(p, (struct ioctl_args *)args);
1103       }
1104
1105     case LINUX_VT_GETSTATE:
1106
1107         args->cmd = VT_GETACTIVE;
1108         return  ioctl(p, (struct ioctl_args *)args);
1109
1110     case LINUX_VT_RELDISP:
1111
1112        args->cmd = VT_RELDISP;
1113        return  ioctl(p, (struct ioctl_args *)args);
1114
1115     case LINUX_VT_ACTIVATE:
1116
1117         args->cmd = VT_ACTIVATE;
1118         return  ioctl(p, (struct ioctl_args *)args);
1119
1120     case LINUX_VT_WAITACTIVE:
1121
1122         args->cmd = VT_WAITACTIVE;
1123         return  ioctl(p, (struct ioctl_args *)args);
1124
1125     case LINUX_KDGKBMODE:
1126
1127         args->cmd = KDGKBMODE;
1128         return ioctl(p, (struct ioctl_args *)args);
1129
1130     case LINUX_KDSKBMODE:
1131       {
1132         int kbdmode;
1133         switch (args->arg) {
1134         case LINUX_KBD_RAW:
1135             kbdmode = K_RAW;
1136             return fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, p);
1137         case LINUX_KBD_XLATE:  
1138             kbdmode = K_XLATE;
1139             return fo_ioctl(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
1140         case LINUX_KBD_MEDIUMRAW:
1141             kbdmode = K_RAW;
1142             return fo_ioctl(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
1143         default:
1144             return EINVAL;
1145         }
1146       }
1147
1148     case LINUX_KDGETMODE:
1149         args->cmd = KDGETMODE;
1150         return  ioctl(p, (struct ioctl_args *)args);
1151
1152     case LINUX_KDSETMODE:
1153         args->cmd = KDSETMODE;
1154         return  ioctl(p, (struct ioctl_args *)args);
1155
1156     case LINUX_KDSETLED:
1157         args->cmd = KDSETLED;
1158         return  ioctl(p, (struct ioctl_args *)args);
1159
1160     case LINUX_KDGETLED:
1161         args->cmd = KDGETLED;
1162         return  ioctl(p, (struct ioctl_args *)args);
1163
1164     case LINUX_KIOCSOUND:
1165         args->cmd = KIOCSOUND;
1166         return  ioctl(p, (struct ioctl_args *)args);
1167
1168     case LINUX_KDMKTONE:
1169         args->cmd = KDMKTONE;
1170         return  ioctl(p, (struct ioctl_args *)args);
1171
1172
1173     case LINUX_CDROMPAUSE:
1174         args->cmd = CDIOCPAUSE;
1175         return  ioctl(p, (struct ioctl_args *)args);
1176
1177     case LINUX_CDROMRESUME:
1178         args->cmd = CDIOCRESUME;
1179         return  ioctl(p, (struct ioctl_args *)args);
1180
1181     case LINUX_CDROMPLAYMSF:
1182         args->cmd = CDIOCPLAYMSF;
1183         return  ioctl(p, (struct ioctl_args *)args);
1184
1185     case LINUX_CDROMPLAYTRKIND:
1186         args->cmd = CDIOCPLAYTRACKS;
1187         return  ioctl(p, (struct ioctl_args *)args);
1188
1189     case LINUX_CDROMSTART:
1190         args->cmd = CDIOCSTART;
1191         return  ioctl(p, (struct ioctl_args *)args);
1192
1193     case LINUX_CDROMSTOP:
1194         args->cmd = CDIOCSTOP;
1195         return  ioctl(p, (struct ioctl_args *)args);
1196
1197     case LINUX_CDROMEJECT:
1198         args->cmd = CDIOCEJECT;
1199         return  ioctl(p, (struct ioctl_args *)args);
1200
1201     case LINUX_CDROMRESET:
1202         args->cmd = CDIOCRESET;
1203         return  ioctl(p, (struct ioctl_args *)args);
1204
1205     case LINUX_CDROMREADTOCHDR: {
1206         struct ioc_toc_header th;
1207         struct linux_cdrom_tochdr lth;
1208         error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, p);
1209         if (!error) {
1210             lth.cdth_trk0 = th.starting_track;
1211             lth.cdth_trk1 = th.ending_track;
1212             copyout((caddr_t)&lth, (caddr_t)args->arg, sizeof(lth));
1213         }
1214         return error;
1215     }
1216
1217     case LINUX_CDROMREADTOCENTRY: {
1218         struct linux_cdrom_tocentry lte, *ltep =
1219             (struct linux_cdrom_tocentry *)args->arg;
1220         struct ioc_read_toc_single_entry irtse;
1221         irtse.address_format = ltep->cdte_format;
1222         irtse.track = ltep->cdte_track;
1223         error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p);
1224         if (!error) {
1225             lte = *ltep;
1226             lte.cdte_ctrl = irtse.entry.control;
1227             lte.cdte_adr = irtse.entry.addr_type;
1228             bsd_to_linux_msf_lba(irtse.address_format,
1229                 &irtse.entry.addr, &lte.cdte_addr);
1230             copyout((caddr_t)&lte, (caddr_t)args->arg, sizeof(lte));
1231         }
1232         return error;
1233     }
1234
1235     case LINUX_CDROMSUBCHNL: {
1236         caddr_t sg;
1237         struct linux_cdrom_subchnl sc;
1238         struct ioc_read_subchannel bsdsc;
1239         struct cd_sub_channel_info *bsdinfo;
1240
1241         sg = stackgap_init();
1242         bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg,
1243                         sizeof(struct cd_sub_channel_info));
1244
1245         bsdsc.address_format = CD_LBA_FORMAT;
1246         bsdsc.data_format = CD_CURRENT_POSITION;
1247         bsdsc.data_len = sizeof(struct cd_sub_channel_info);
1248         bsdsc.data = bsdinfo;
1249         error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, p);
1250         if (error)
1251             return error;
1252
1253         error = copyin((caddr_t)args->arg, (caddr_t)&sc,
1254                         sizeof(struct linux_cdrom_subchnl));
1255         if (error)
1256             return error;
1257
1258         sc.cdsc_audiostatus = bsdinfo->header.audio_status;
1259         sc.cdsc_adr = bsdinfo->what.position.addr_type;
1260         sc.cdsc_ctrl = bsdinfo->what.position.control;
1261         sc.cdsc_trk = bsdinfo->what.position.track_number;
1262         sc.cdsc_ind = bsdinfo->what.position.index_number;
1263         set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
1264                         bsdinfo->what.position.absaddr.lba);
1265         set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
1266                         bsdinfo->what.position.reladdr.lba);
1267         error = copyout((caddr_t)&sc, (caddr_t)args->arg,
1268                         sizeof(struct linux_cdrom_subchnl));
1269         return error;
1270     }
1271
1272     case LINUX_OSS_GETVERSION: {
1273         int version;
1274
1275         version = linux_get_oss_version(p);
1276         return copyout((caddr_t)&version, (caddr_t)args->arg, sizeof(int));
1277     }
1278
1279     }
1280
1281     uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
1282         args->fd, (u_int)((args->cmd & 0xffff00) >> 8),
1283         (int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff));
1284     return EINVAL;
1285 }