xref: /freebsd/sys/compat/linux/linux_ioctl.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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 }
1286