xref: /freebsd/sys/compat/linux/linux_ioctl.c (revision f35e5d0ef0a10ebda81a076bbd838d12b916dab5)
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_OUT, IOC_IN, 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 (*func)(struct file *fp, u_long com, caddr_t data, struct proc *p);
543     int bsd_line, linux_line;
544     int error;
545 
546 #ifdef DEBUG
547     printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n",
548 	(long)p->p_pid, args->fd, args->cmd);
549 #endif
550     if ((unsigned)args->fd >= fdp->fd_nfiles
551 	|| (fp = fdp->fd_ofiles[args->fd]) == 0)
552 	return EBADF;
553 
554     if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
555 	return EBADF;
556     }
557 
558     func = fp->f_ops->fo_ioctl;
559     switch (args->cmd & 0xffff) {
560 
561     case LINUX_TCGETA:
562 	if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
563 	    return error;
564 	bsd_to_linux_termio(&bsd_termios, &linux_termio);
565 	return copyout((caddr_t)&linux_termio, (caddr_t)args->arg,
566 		       sizeof(linux_termio));
567 
568     case LINUX_TCSETA:
569 	error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
570 	if (error)
571 	    return error;
572 	linux_to_bsd_termio(&linux_termio, &bsd_termios);
573 	return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
574 
575     case LINUX_TCSETAW:
576 	error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
577 	if (error)
578 	    return error;
579 	linux_to_bsd_termio(&linux_termio, &bsd_termios);
580 	return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
581 
582     case LINUX_TCSETAF:
583 	error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio));
584 	if (error)
585 	    return error;
586 	linux_to_bsd_termio(&linux_termio, &bsd_termios);
587 	return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
588 
589     case LINUX_TCGETS:
590 	if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
591 	    return error;
592 	bsd_to_linux_termios(&bsd_termios, &linux_termios);
593 	return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
594 		       sizeof(linux_termios));
595 
596     case LINUX_TCSETS:
597 	error = copyin((caddr_t)args->arg, &linux_termios,
598 		       sizeof(linux_termios));
599 	if (error)
600 	    return error;
601 	linux_to_bsd_termios(&linux_termios, &bsd_termios);
602 	return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
603 
604     case LINUX_TCSETSW:
605 	error = copyin((caddr_t)args->arg, &linux_termios,
606 		       sizeof(linux_termios));
607 	if (error)
608 	    return error;
609 	linux_to_bsd_termios(&linux_termios, &bsd_termios);
610 	return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
611 
612     case LINUX_TCSETSF:
613 	error = copyin((caddr_t)args->arg, &linux_termios,
614 		       sizeof(linux_termios));
615 	if (error)
616 	    return error;
617 	linux_to_bsd_termios(&linux_termios, &bsd_termios);
618 	return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
619 
620     case LINUX_TIOCGPGRP:
621 	args->cmd = TIOCGPGRP;
622 	return ioctl(p, (struct ioctl_args *)args);
623 
624     case LINUX_TIOCSPGRP:
625 	args->cmd = TIOCSPGRP;
626 	return ioctl(p, (struct ioctl_args *)args);
627 
628     case LINUX_TIOCGWINSZ:
629 	args->cmd = TIOCGWINSZ;
630 	return ioctl(p, (struct ioctl_args *)args);
631 
632     case LINUX_TIOCSWINSZ:
633 	args->cmd = TIOCSWINSZ;
634 	return ioctl(p, (struct ioctl_args *)args);
635 
636     case LINUX_TIOCMGET:
637 	args->cmd = TIOCMGET;
638 	return ioctl(p, (struct ioctl_args *)args);
639 
640     case LINUX_TIOCMBIS:
641 	args->cmd = TIOCMBIS;
642 	return ioctl(p, (struct ioctl_args *)args);
643 
644     case LINUX_TIOCMBIC:
645 	args->cmd = TIOCMBIC;
646 	return ioctl(p, (struct ioctl_args *)args);
647 
648     case LINUX_TIOCMSET:
649 	args->cmd = TIOCMSET;
650 	return ioctl(p, (struct ioctl_args *)args);
651 
652     case LINUX_FIONREAD:
653 	args->cmd = FIONREAD;
654 	return ioctl(p, (struct ioctl_args *)args);
655 
656     case LINUX_FIONBIO:
657 	args->cmd = FIONBIO;
658 	return ioctl(p, (struct ioctl_args *)args);
659 
660     case LINUX_FIOASYNC:
661 	args->cmd = FIOASYNC;
662 	return ioctl(p, (struct ioctl_args *)args);
663 
664     case LINUX_FIONCLEX:
665 	args->cmd = FIONCLEX;
666 	return ioctl(p, (struct ioctl_args *)args);
667 
668     case LINUX_FIOCLEX:
669 	args->cmd = FIOCLEX;
670 	return ioctl(p, (struct ioctl_args *)args);
671 
672     case LINUX_TIOCEXCL:
673 	args->cmd = TIOCEXCL;
674 	return ioctl(p, (struct ioctl_args *)args);
675 
676     case LINUX_TIOCNXCL:
677 	args->cmd = TIOCNXCL;
678 	return ioctl(p, (struct ioctl_args *)args);
679 
680     case LINUX_TIOCCONS:
681 	args->cmd = TIOCCONS;
682 	return ioctl(p, (struct ioctl_args *)args);
683 
684     case LINUX_TIOCNOTTY:
685 	args->cmd = TIOCNOTTY;
686 	return ioctl(p, (struct ioctl_args *)args);
687 
688     case LINUX_SIOCGIFCONF:
689 	args->cmd = OSIOCGIFCONF;
690 	return ioctl(p, (struct ioctl_args *)args);
691 
692     case LINUX_SIOCGIFFLAGS:
693 	args->cmd = SIOCGIFFLAGS;
694 	return ioctl(p, (struct ioctl_args *)args);
695 
696     case LINUX_SIOCGIFADDR:
697 	args->cmd = OSIOCGIFADDR;
698 	return ioctl(p, (struct ioctl_args *)args);
699 
700     case LINUX_SIOCGIFDSTADDR:
701 	args->cmd = OSIOCGIFDSTADDR;
702 	return ioctl(p, (struct ioctl_args *)args);
703 
704     case LINUX_SIOCGIFBRDADDR:
705 	args->cmd = OSIOCGIFBRDADDR;
706 	return ioctl(p, (struct ioctl_args *)args);
707 
708     case LINUX_SIOCGIFNETMASK:
709 	args->cmd = OSIOCGIFNETMASK;
710 	return ioctl(p, (struct ioctl_args *)args);
711 
712 	/* get hardware address */
713     case LINUX_SIOCGIFHWADDR:
714     {
715 	int			ifn;
716 	struct ifnet		*ifp;
717 	struct ifaddr		*ifa;
718 	struct sockaddr_dl	*sdl;
719 	struct linux_ifreq	*ifr = (struct linux_ifreq *)args->arg;
720 
721 	/*
722 	 * Note that we don't actually respect the name in the ifreq structure, as
723 	 * Linux interface names are all different
724 	 */
725 
726 	for (ifn = 0; ifn < if_index; ifn++) {
727 
728 	    ifp = ifnet_addrs[ifn]->ifa_ifp;	/* pointer to interface */
729 	    if (ifp->if_type == IFT_ETHER) {	/* looks good */
730 		/* walk the address list */
731 		for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) {
732 		    if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&	/* we have an address structure */
733 			(sdl->sdl_family == AF_LINK) &&			/* it's a link address */
734 			(sdl->sdl_type == IFT_ETHER)) {			/* for an ethernet link */
735 
736 			return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN));
737 		    }
738 		}
739 	    }
740 	}
741 	return(ENOENT);		/* ??? */
742     }
743 
744     case LINUX_SIOCADDMULTI:
745 	args->cmd = SIOCADDMULTI;
746 	return ioctl(p, (struct ioctl_args *)args);
747 
748     case LINUX_SIOCDELMULTI:
749 	args->cmd = SIOCDELMULTI;
750 	return ioctl(p, (struct ioctl_args *)args);
751 
752     case LINUX_FIOSETOWN:
753 	args->cmd = FIOSETOWN;
754 	return ioctl(p, (struct ioctl_args *)args);
755 
756     case LINUX_SIOCSPGRP:
757 	args->cmd = SIOCSPGRP;
758 	return ioctl(p, (struct ioctl_args *)args);
759 
760     case LINUX_FIOGETOWN:
761 	args->cmd = FIOGETOWN;
762 	return ioctl(p, (struct ioctl_args *)args);
763 
764     case LINUX_SIOCGPGRP:
765 	args->cmd = SIOCGPGRP;
766 	return ioctl(p, (struct ioctl_args *)args);
767 
768     case LINUX_SIOCATMARK:
769 	args->cmd = SIOCATMARK;
770 	return ioctl(p, (struct ioctl_args *)args);
771 
772     case LINUX_TIOCSETD:
773 	switch (args->arg) {
774 	case LINUX_N_TTY:
775 	    bsd_line = TTYDISC;
776 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
777 	case LINUX_N_SLIP:
778 	    bsd_line = SLIPDISC;
779 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
780 	case LINUX_N_PPP:
781 	    bsd_line = PPPDISC;
782 	    return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
783 	default:
784 	    return EINVAL;
785 	}
786 
787     case LINUX_TIOCGETD:
788 	bsd_line = TTYDISC;
789 	error =(*func)(fp, TIOCGETD, (caddr_t)&bsd_line, p);
790 	if (error)
791 	    return error;
792 	switch (bsd_line) {
793 	case TTYDISC:
794 	    linux_line = LINUX_N_TTY;
795 	    break;
796 	case SLIPDISC:
797 	    linux_line = LINUX_N_SLIP;
798 	    break;
799 	case PPPDISC:
800 	    linux_line = LINUX_N_PPP;
801 	    break;
802 	default:
803 	    return EINVAL;
804 	}
805 	return copyout(&linux_line, (caddr_t)args->arg,
806 		       sizeof(int));
807 
808     case LINUX_SNDCTL_SEQ_RESET:
809 	args->cmd = SNDCTL_SEQ_RESET;
810 	return ioctl(p, (struct ioctl_args *)args);
811 
812     case LINUX_SNDCTL_SEQ_SYNC:
813 	args->cmd = SNDCTL_SEQ_SYNC;
814 	return ioctl(p, (struct ioctl_args *)args);
815 
816     case LINUX_SNDCTL_SYNTH_INFO:
817 	args->cmd = SNDCTL_SYNTH_INFO;
818 	return ioctl(p, (struct ioctl_args *)args);
819 
820     case LINUX_SNDCTL_SEQ_CTRLRATE:
821 	args->cmd = SNDCTL_SEQ_CTRLRATE;
822 	return ioctl(p, (struct ioctl_args *)args);
823 
824     case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
825 	args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
826 	return ioctl(p, (struct ioctl_args *)args);
827 
828     case LINUX_SNDCTL_SEQ_GETINCOUNT:
829 	args->cmd = SNDCTL_SEQ_GETINCOUNT;
830 	return ioctl(p, (struct ioctl_args *)args);
831 
832     case LINUX_SNDCTL_SEQ_PERCMODE:
833 	args->cmd = SNDCTL_SEQ_PERCMODE;
834 	return ioctl(p, (struct ioctl_args *)args);
835 
836     case LINUX_SNDCTL_FM_LOAD_INSTR:
837 	args->cmd = SNDCTL_FM_LOAD_INSTR;
838 	return ioctl(p, (struct ioctl_args *)args);
839 
840     case LINUX_SNDCTL_SEQ_TESTMIDI:
841 	args->cmd = SNDCTL_SEQ_TESTMIDI;
842 	return ioctl(p, (struct ioctl_args *)args);
843 
844     case LINUX_SNDCTL_SEQ_RESETSAMPLES:
845 	args->cmd = SNDCTL_SEQ_RESETSAMPLES;
846 	return ioctl(p, (struct ioctl_args *)args);
847 
848     case LINUX_SNDCTL_SEQ_NRSYNTHS:
849 	args->cmd = SNDCTL_SEQ_NRSYNTHS;
850 	return ioctl(p, (struct ioctl_args *)args);
851 
852     case LINUX_SNDCTL_SEQ_NRMIDIS:
853 	args->cmd = SNDCTL_SEQ_NRMIDIS;
854 	return ioctl(p, (struct ioctl_args *)args);
855 
856     case LINUX_SNDCTL_MIDI_INFO:
857 	args->cmd = SNDCTL_MIDI_INFO;
858 	return ioctl(p, (struct ioctl_args *)args);
859 
860     case LINUX_SNDCTL_SEQ_TRESHOLD:
861 	args->cmd = SNDCTL_SEQ_TRESHOLD;
862 	return ioctl(p, (struct ioctl_args *)args);
863 
864     case LINUX_SNDCTL_SYNTH_MEMAVL:
865 	args->cmd = SNDCTL_SYNTH_MEMAVL;
866 	return ioctl(p, (struct ioctl_args *)args);
867 
868     case LINUX_SNDCTL_DSP_GETOPTR :
869 	args->cmd = SNDCTL_DSP_GETOPTR;
870 	return ioctl(p, (struct ioctl_args *)args);
871 
872     case LINUX_SNDCTL_DSP_GETIPTR :
873 	args->cmd = SNDCTL_DSP_GETIPTR;
874 	return ioctl(p, (struct ioctl_args *)args);
875 
876     case LINUX_SNDCTL_DSP_SETTRIGGER:
877 	args->cmd = SNDCTL_DSP_SETTRIGGER;
878 	return ioctl(p, (struct ioctl_args *)args);
879 
880     case LINUX_SNDCTL_DSP_GETCAPS:
881 	args->cmd = SNDCTL_DSP_GETCAPS;
882 	return ioctl(p, (struct ioctl_args *)args);
883 
884     case LINUX_SNDCTL_DSP_RESET:
885 	args->cmd = SNDCTL_DSP_RESET;
886 	return ioctl(p, (struct ioctl_args *)args);
887 
888     case LINUX_SNDCTL_DSP_SYNC:
889 	args->cmd = SNDCTL_DSP_SYNC;
890 	return ioctl(p, (struct ioctl_args *)args);
891 
892     case LINUX_SNDCTL_DSP_SPEED:
893 	args->cmd = SNDCTL_DSP_SPEED;
894 	return ioctl(p, (struct ioctl_args *)args);
895 
896     case LINUX_SNDCTL_DSP_STEREO:
897 	args->cmd = SNDCTL_DSP_STEREO;
898 	return ioctl(p, (struct ioctl_args *)args);
899 
900     case LINUX_SNDCTL_DSP_GETBLKSIZE:
901       /* LINUX_SNDCTL_DSP_SETBLKSIZE */
902 	args->cmd = SNDCTL_DSP_GETBLKSIZE;
903 	return ioctl(p, (struct ioctl_args *)args);
904 
905     case LINUX_SNDCTL_DSP_SETFMT:
906 	args->cmd = SNDCTL_DSP_SETFMT;
907 	return ioctl(p, (struct ioctl_args *)args);
908 
909     case LINUX_SOUND_PCM_WRITE_CHANNELS:
910 	args->cmd = SOUND_PCM_WRITE_CHANNELS;
911 	return ioctl(p, (struct ioctl_args *)args);
912 
913     case LINUX_SOUND_PCM_WRITE_FILTER:
914 	args->cmd = SOUND_PCM_WRITE_FILTER;
915 	return ioctl(p, (struct ioctl_args *)args);
916 
917     case LINUX_SNDCTL_DSP_POST:
918 	args->cmd = SNDCTL_DSP_POST;
919 	return ioctl(p, (struct ioctl_args *)args);
920 
921     case LINUX_SNDCTL_DSP_SUBDIVIDE:
922 	args->cmd = SNDCTL_DSP_SUBDIVIDE;
923 	return ioctl(p, (struct ioctl_args *)args);
924 
925     case LINUX_SNDCTL_DSP_SETFRAGMENT:
926 	args->cmd = SNDCTL_DSP_SETFRAGMENT;
927 	return ioctl(p, (struct ioctl_args *)args);
928 
929     case LINUX_SNDCTL_DSP_GETFMTS:
930 	args->cmd = SNDCTL_DSP_GETFMTS;
931 	return ioctl(p, (struct ioctl_args *)args);
932 
933     case LINUX_SNDCTL_DSP_GETOSPACE:
934 	args->cmd = SNDCTL_DSP_GETOSPACE;
935 	return ioctl(p, (struct ioctl_args *)args);
936 
937     case LINUX_SNDCTL_DSP_GETISPACE:
938 	args->cmd = SNDCTL_DSP_GETISPACE;
939 	return ioctl(p, (struct ioctl_args *)args);
940 
941     case LINUX_SNDCTL_DSP_NONBLOCK:
942 	args->cmd = SNDCTL_DSP_NONBLOCK;
943 	return ioctl(p, (struct ioctl_args *)args);
944 
945     case LINUX_SOUND_MIXER_WRITE_VOLUME:
946 	args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
947 	return ioctl(p, (struct ioctl_args *)args);
948 
949     case LINUX_SOUND_MIXER_WRITE_BASS:
950 	args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
951 	return ioctl(p, (struct ioctl_args *)args);
952 
953     case LINUX_SOUND_MIXER_WRITE_TREBLE:
954 	args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
955 	return ioctl(p, (struct ioctl_args *)args);
956 
957     case LINUX_SOUND_MIXER_WRITE_SYNTH:
958 	args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
959 	return ioctl(p, (struct ioctl_args *)args);
960 
961     case LINUX_SOUND_MIXER_WRITE_PCM:
962 	args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
963 	return ioctl(p, (struct ioctl_args *)args);
964 
965     case LINUX_SOUND_MIXER_WRITE_SPEAKER:
966 	args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
967 	return ioctl(p, (struct ioctl_args *)args);
968 
969     case LINUX_SOUND_MIXER_WRITE_LINE:
970 	args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
971 	return ioctl(p, (struct ioctl_args *)args);
972 
973     case LINUX_SOUND_MIXER_WRITE_MIC:
974 	args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
975 	return ioctl(p, (struct ioctl_args *)args);
976 
977     case LINUX_SOUND_MIXER_WRITE_CD:
978 	args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
979 	return ioctl(p, (struct ioctl_args *)args);
980 
981     case LINUX_SOUND_MIXER_WRITE_IMIX:
982 	args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
983 	return ioctl(p, (struct ioctl_args *)args);
984 
985     case LINUX_SOUND_MIXER_WRITE_ALTPCM:
986 	args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
987 	return ioctl(p, (struct ioctl_args *)args);
988 
989     case LINUX_SOUND_MIXER_WRITE_RECLEV:
990 	args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
991 	return ioctl(p, (struct ioctl_args *)args);
992 
993     case LINUX_SOUND_MIXER_WRITE_IGAIN:
994 	args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
995 	return ioctl(p, (struct ioctl_args *)args);
996 
997     case LINUX_SOUND_MIXER_WRITE_OGAIN:
998 	args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
999 	return ioctl(p, (struct ioctl_args *)args);
1000 
1001     case LINUX_SOUND_MIXER_WRITE_LINE1:
1002 	args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
1003 	return ioctl(p, (struct ioctl_args *)args);
1004 
1005     case LINUX_SOUND_MIXER_WRITE_LINE2:
1006 	args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
1007 	return ioctl(p, (struct ioctl_args *)args);
1008 
1009     case LINUX_SOUND_MIXER_WRITE_LINE3:
1010 	args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
1011 	return ioctl(p, (struct ioctl_args *)args);
1012 
1013     case LINUX_SOUND_MIXER_READ_DEVMASK:
1014 	args->cmd = SOUND_MIXER_READ_DEVMASK;
1015 	return ioctl(p, (struct ioctl_args *)args);
1016 
1017     case LINUX_TIOCGSERIAL: {
1018 	struct linux_serial_struct lss;
1019 
1020 	lss.type = LINUX_PORT_16550A;
1021 	lss.flags = 0;
1022 	lss.close_delay = 0;
1023 	return copyout((caddr_t)&lss, (caddr_t)args->arg, sizeof(lss));
1024     }
1025 
1026     case LINUX_TIOCSSERIAL: {
1027         struct linux_serial_struct lss;
1028 
1029 	error = copyin((caddr_t)args->arg, (caddr_t)&lss, sizeof(lss));
1030 	if (error)
1031 	    return error;
1032 	/*
1033 	 * XXX - It really helps to have an implementation that does nothing.
1034 	 *       NOT!
1035 	 */
1036 	return 0;
1037     }
1038 
1039     case LINUX_TCXONC:
1040       switch (args->arg) {
1041       case LINUX_TCOOFF:
1042 	      args->cmd = TIOCSTOP;
1043 	      break;
1044       case LINUX_TCOON:
1045 	      args->cmd = TIOCSTART;
1046 	      break;
1047       case LINUX_TCIOFF:
1048       case LINUX_TCION: {
1049 	      u_char c;
1050 	      struct write_args wr;
1051 	      error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p);
1052               if (error != 0)
1053 		      return error;
1054 	      c = bsd_termios.c_cc[args->arg == LINUX_TCIOFF ? VSTOP : VSTART];
1055 	      if (c != _POSIX_VDISABLE) {
1056 		      wr.fd = args->fd;
1057 		      wr.buf = &c;
1058 		      wr.nbyte = sizeof(c);
1059 		      return write(p, &wr);
1060 	      }
1061 	      else
1062 		      return (0);
1063       }
1064       default:
1065 	      return EINVAL;
1066       }
1067       args->arg = 0;
1068       return ioctl(p, (struct ioctl_args *)args);
1069 
1070     case LINUX_TCFLSH:
1071       args->cmd = TIOCFLUSH;
1072       switch (args->arg) {
1073         case LINUX_TCIFLUSH:
1074                 args->arg = FREAD;
1075                 break;
1076         case LINUX_TCOFLUSH:
1077                 args->arg = FWRITE;
1078                 break;
1079         case LINUX_TCIOFLUSH:
1080                 args->arg = FREAD | FWRITE;
1081                 break;
1082         default:
1083 	        return EINVAL;
1084       }
1085       return ioctl(p, (struct ioctl_args *)args);
1086 
1087    case LINUX_VT_OPENQRY:
1088 
1089 	args->cmd = VT_OPENQRY;
1090 	return  ioctl(p, (struct ioctl_args *)args);
1091 
1092     case LINUX_VT_GETMODE:
1093 
1094 	args->cmd = VT_GETMODE;
1095 	return  ioctl(p, (struct ioctl_args *)args);
1096 
1097     case LINUX_VT_SETMODE:
1098       {
1099 	struct vt_mode *mode;
1100 	args->cmd = VT_SETMODE;
1101 	mode = (struct vt_mode *)args->arg;
1102 	if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig))
1103 	    mode->frsig = mode->acqsig;
1104 	return ioctl(p, (struct ioctl_args *)args);
1105       }
1106 
1107     case LINUX_VT_GETSTATE:
1108 
1109 	args->cmd = VT_GETACTIVE;
1110 	return  ioctl(p, (struct ioctl_args *)args);
1111 
1112     case LINUX_VT_RELDISP:
1113 
1114        args->cmd = VT_RELDISP;
1115        return  ioctl(p, (struct ioctl_args *)args);
1116 
1117     case LINUX_VT_ACTIVATE:
1118 
1119 	args->cmd = VT_ACTIVATE;
1120 	return  ioctl(p, (struct ioctl_args *)args);
1121 
1122     case LINUX_VT_WAITACTIVE:
1123 
1124 	args->cmd = VT_WAITACTIVE;
1125 	return  ioctl(p, (struct ioctl_args *)args);
1126 
1127     case LINUX_KDGKBMODE:
1128 
1129 	args->cmd = KDGKBMODE;
1130 	return ioctl(p, (struct ioctl_args *)args);
1131 
1132     case LINUX_KDSKBMODE:
1133       {
1134         int kbdmode;
1135 	switch (args->arg) {
1136 	case LINUX_KBD_RAW:
1137 	    kbdmode = K_RAW;
1138 	    return (*func)(fp, KDSKBMODE, (caddr_t)&kbdmode, p);
1139 	case LINUX_KBD_XLATE:
1140 	    kbdmode = K_XLATE;
1141 	    return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
1142 	case LINUX_KBD_MEDIUMRAW:
1143 	    kbdmode = K_RAW;
1144 	    return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
1145 	default:
1146 	    return EINVAL;
1147 	}
1148       }
1149 
1150     case LINUX_KDGETMODE:
1151 	args->cmd = KDGETMODE;
1152 	return	ioctl(p, (struct ioctl_args *)args);
1153 
1154     case LINUX_KDSETMODE:
1155 	args->cmd = KDSETMODE;
1156 	return	ioctl(p, (struct ioctl_args *)args);
1157 
1158     case LINUX_KDSETLED:
1159 	args->cmd = KDSETLED;
1160 	return  ioctl(p, (struct ioctl_args *)args);
1161 
1162     case LINUX_KDGETLED:
1163 	args->cmd = KDGETLED;
1164 	return  ioctl(p, (struct ioctl_args *)args);
1165 
1166     case LINUX_KIOCSOUND:
1167 	args->cmd = KIOCSOUND;
1168 	return  ioctl(p, (struct ioctl_args *)args);
1169 
1170     case LINUX_KDMKTONE:
1171 	args->cmd = KDMKTONE;
1172 	return  ioctl(p, (struct ioctl_args *)args);
1173 
1174 
1175     case LINUX_CDROMPAUSE:
1176 	args->cmd = CDIOCPAUSE;
1177 	return	ioctl(p, (struct ioctl_args *)args);
1178 
1179     case LINUX_CDROMRESUME:
1180 	args->cmd = CDIOCRESUME;
1181 	return	ioctl(p, (struct ioctl_args *)args);
1182 
1183     case LINUX_CDROMPLAYMSF:
1184 	args->cmd = CDIOCPLAYMSF;
1185 	return	ioctl(p, (struct ioctl_args *)args);
1186 
1187     case LINUX_CDROMPLAYTRKIND:
1188 	args->cmd = CDIOCPLAYTRACKS;
1189 	return	ioctl(p, (struct ioctl_args *)args);
1190 
1191     case LINUX_CDROMSTART:
1192 	args->cmd = CDIOCSTART;
1193 	return	ioctl(p, (struct ioctl_args *)args);
1194 
1195     case LINUX_CDROMSTOP:
1196 	args->cmd = CDIOCSTOP;
1197 	return	ioctl(p, (struct ioctl_args *)args);
1198 
1199     case LINUX_CDROMEJECT:
1200 	args->cmd = CDIOCEJECT;
1201 	return	ioctl(p, (struct ioctl_args *)args);
1202 
1203     case LINUX_CDROMRESET:
1204 	args->cmd = CDIOCRESET;
1205 	return	ioctl(p, (struct ioctl_args *)args);
1206 
1207     case LINUX_CDROMREADTOCHDR: {
1208 	struct ioc_toc_header th;
1209 	struct linux_cdrom_tochdr lth;
1210 	error = (*func)(fp, CDIOREADTOCHEADER, (caddr_t)&th, p);
1211 	if (!error) {
1212 	    lth.cdth_trk0 = th.starting_track;
1213 	    lth.cdth_trk1 = th.ending_track;
1214 	    copyout((caddr_t)&lth, (caddr_t)args->arg, sizeof(lth));
1215 	}
1216 	return error;
1217     }
1218 
1219     case LINUX_CDROMREADTOCENTRY: {
1220 	struct linux_cdrom_tocentry lte, *ltep =
1221 	    (struct linux_cdrom_tocentry *)args->arg;
1222 	struct ioc_read_toc_single_entry irtse;
1223 	irtse.address_format = ltep->cdte_format;
1224 	irtse.track = ltep->cdte_track;
1225 	error = (*func)(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p);
1226 	if (!error) {
1227 	    lte = *ltep;
1228 	    lte.cdte_ctrl = irtse.entry.control;
1229 	    lte.cdte_adr = irtse.entry.addr_type;
1230 	    bsd_to_linux_msf_lba(irtse.address_format,
1231 		&irtse.entry.addr, &lte.cdte_addr);
1232 	    copyout((caddr_t)&lte, (caddr_t)args->arg, sizeof(lte));
1233 	}
1234 	return error;
1235     }
1236 
1237     case LINUX_CDROMSUBCHNL: {
1238 	caddr_t sg;
1239 	struct linux_cdrom_subchnl sc;
1240 	struct ioc_read_subchannel bsdsc;
1241 	struct cd_sub_channel_info *bsdinfo;
1242 
1243 	sg = stackgap_init();
1244 	bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg,
1245 			sizeof(struct cd_sub_channel_info));
1246 
1247 	bsdsc.address_format = CD_LBA_FORMAT;
1248 	bsdsc.data_format = CD_CURRENT_POSITION;
1249 	bsdsc.data_len = sizeof(struct cd_sub_channel_info);
1250 	bsdsc.data = bsdinfo;
1251 	error = (*func)(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, p);
1252 	if (error)
1253 	    return error;
1254 
1255 	error = copyin((caddr_t)args->arg, (caddr_t)&sc,
1256 			sizeof(struct linux_cdrom_subchnl));
1257 	if (error)
1258 	    return error;
1259 
1260 	sc.cdsc_audiostatus = bsdinfo->header.audio_status;
1261 	sc.cdsc_adr = bsdinfo->what.position.addr_type;
1262 	sc.cdsc_ctrl = bsdinfo->what.position.control;
1263 	sc.cdsc_trk = bsdinfo->what.position.track_number;
1264 	sc.cdsc_ind = bsdinfo->what.position.index_number;
1265 	set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
1266 			bsdinfo->what.position.absaddr.lba);
1267 	set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
1268 			bsdinfo->what.position.reladdr.lba);
1269 	error = copyout((caddr_t)&sc, (caddr_t)args->arg,
1270 			sizeof(struct linux_cdrom_subchnl));
1271 	return error;
1272     }
1273 
1274     case LINUX_OSS_GETVERSION: {
1275 	int version;
1276 
1277 	version = linux_get_oss_version(p);
1278 	return copyout((caddr_t)&version, (caddr_t)args->arg, sizeof(int));
1279     }
1280 
1281     }
1282 
1283     uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
1284 	args->fd, (u_int)((args->cmd & 0xffff00) >> 8),
1285 	(int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff));
1286     return EINVAL;
1287 }
1288