initial commit
[freebsd-arm:freebsd-arm.git] / compat / 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 without 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
29 #include "opt_compat.h"
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/sysproto.h>
37 #include <sys/cdio.h>
38 #include <sys/dvdio.h>
39 #include <sys/conf.h>
40 #include <sys/disk.h>
41 #include <sys/consio.h>
42 #include <sys/ctype.h>
43 #include <sys/fcntl.h>
44 #include <sys/file.h>
45 #include <sys/filedesc.h>
46 #include <sys/filio.h>
47 #include <sys/jail.h>
48 #include <sys/kbio.h>
49 #include <sys/kernel.h>
50 #include <sys/linker_set.h>
51 #include <sys/lock.h>
52 #include <sys/malloc.h>
53 #include <sys/proc.h>
54 #include <sys/sbuf.h>
55 #include <sys/socket.h>
56 #include <sys/sockio.h>
57 #include <sys/soundcard.h>
58 #include <sys/stdint.h>
59 #include <sys/sx.h>
60 #include <sys/tty.h>
61 #include <sys/uio.h>
62
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_types.h>
66 #include <net/vnet.h>
67
68 #ifdef COMPAT_LINUX32
69 #include <machine/../linux32/linux.h>
70 #include <machine/../linux32/linux32_proto.h>
71 #else
72 #include <machine/../linux/linux.h>
73 #include <machine/../linux/linux_proto.h>
74 #endif
75
76 #include <compat/linux/linux_ioctl.h>
77 #include <compat/linux/linux_mib.h>
78 #include <compat/linux/linux_socket.h>
79 #include <compat/linux/linux_util.h>
80
81 #include <compat/linux/linux_videodev.h>
82 #include <compat/linux/linux_videodev_compat.h>
83
84 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ);
85
86 static linux_ioctl_function_t linux_ioctl_cdrom;
87 static linux_ioctl_function_t linux_ioctl_vfat;
88 static linux_ioctl_function_t linux_ioctl_console;
89 static linux_ioctl_function_t linux_ioctl_hdio;
90 static linux_ioctl_function_t linux_ioctl_disk;
91 static linux_ioctl_function_t linux_ioctl_socket;
92 static linux_ioctl_function_t linux_ioctl_sound;
93 static linux_ioctl_function_t linux_ioctl_termio;
94 static linux_ioctl_function_t linux_ioctl_private;
95 static linux_ioctl_function_t linux_ioctl_drm;
96 static linux_ioctl_function_t linux_ioctl_sg;
97 static linux_ioctl_function_t linux_ioctl_v4l;
98 static linux_ioctl_function_t linux_ioctl_special;
99 static linux_ioctl_function_t linux_ioctl_fbsd_usb;
100
101 static struct linux_ioctl_handler cdrom_handler =
102 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
103 static struct linux_ioctl_handler vfat_handler =
104 { linux_ioctl_vfat, LINUX_IOCTL_VFAT_MIN, LINUX_IOCTL_VFAT_MAX };
105 static struct linux_ioctl_handler console_handler =
106 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX };
107 static struct linux_ioctl_handler hdio_handler =
108 { linux_ioctl_hdio, LINUX_IOCTL_HDIO_MIN, LINUX_IOCTL_HDIO_MAX };
109 static struct linux_ioctl_handler disk_handler =
110 { linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX };
111 static struct linux_ioctl_handler socket_handler =
112 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX };
113 static struct linux_ioctl_handler sound_handler =
114 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
115 static struct linux_ioctl_handler termio_handler =
116 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
117 static struct linux_ioctl_handler private_handler =
118 { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
119 static struct linux_ioctl_handler drm_handler =
120 { linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX };
121 static struct linux_ioctl_handler sg_handler =
122 { linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX };
123 static struct linux_ioctl_handler video_handler =
124 { linux_ioctl_v4l, LINUX_IOCTL_VIDEO_MIN, LINUX_IOCTL_VIDEO_MAX };
125 static struct linux_ioctl_handler fbsd_usb =
126 { linux_ioctl_fbsd_usb, LINUX_FBSD_USB_MIN, LINUX_FBSD_USB_MAX };
127
128 DATA_SET(linux_ioctl_handler_set, cdrom_handler);
129 DATA_SET(linux_ioctl_handler_set, vfat_handler);
130 DATA_SET(linux_ioctl_handler_set, console_handler);
131 DATA_SET(linux_ioctl_handler_set, hdio_handler);
132 DATA_SET(linux_ioctl_handler_set, disk_handler);
133 DATA_SET(linux_ioctl_handler_set, socket_handler);
134 DATA_SET(linux_ioctl_handler_set, sound_handler);
135 DATA_SET(linux_ioctl_handler_set, termio_handler);
136 DATA_SET(linux_ioctl_handler_set, private_handler);
137 DATA_SET(linux_ioctl_handler_set, drm_handler);
138 DATA_SET(linux_ioctl_handler_set, sg_handler);
139 DATA_SET(linux_ioctl_handler_set, video_handler);
140 DATA_SET(linux_ioctl_handler_set, fbsd_usb);
141
142 struct handler_element
143 {
144         TAILQ_ENTRY(handler_element) list;
145         int     (*func)(struct thread *, struct linux_ioctl_args *);
146         int     low, high, span;
147 };
148
149 static TAILQ_HEAD(, handler_element) handlers =
150     TAILQ_HEAD_INITIALIZER(handlers);
151 static struct sx linux_ioctl_sx;
152 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "linux ioctl handlers");
153
154 /*
155  * hdio related ioctls for VMWare support
156  */
157
158 struct linux_hd_geometry {
159         u_int8_t        heads;
160         u_int8_t        sectors;
161         u_int16_t       cylinders;
162         u_int32_t       start;
163 };
164
165 struct linux_hd_big_geometry {
166         u_int8_t        heads;
167         u_int8_t        sectors;
168         u_int32_t       cylinders;
169         u_int32_t       start;
170 };
171
172 static int
173 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
174 {
175         struct file *fp;
176         int error;
177         u_int sectorsize, fwcylinders, fwheads, fwsectors;
178         off_t mediasize, bytespercyl;
179
180         if ((error = fget(td, args->fd, &fp)) != 0)
181                 return (error);
182         switch (args->cmd & 0xffff) {
183         case LINUX_HDIO_GET_GEO:
184         case LINUX_HDIO_GET_GEO_BIG:
185                 error = fo_ioctl(fp, DIOCGMEDIASIZE,
186                         (caddr_t)&mediasize, td->td_ucred, td);
187                 if (!error)
188                         error = fo_ioctl(fp, DIOCGSECTORSIZE,
189                                 (caddr_t)&sectorsize, td->td_ucred, td);
190                 if (!error)
191                         error = fo_ioctl(fp, DIOCGFWHEADS,
192                                 (caddr_t)&fwheads, td->td_ucred, td);
193                 if (!error)
194                         error = fo_ioctl(fp, DIOCGFWSECTORS,
195                                 (caddr_t)&fwsectors, td->td_ucred, td);
196                 /*
197                  * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
198                  * so pretend that GEOM always says 0. This is NOT VALID
199                  * for slices or partitions, only the per-disk raw devices.
200                  */
201
202                 fdrop(fp, td);
203                 if (error)
204                         return (error);
205                 /*
206                  * 1. Calculate the number of bytes in a cylinder,
207                  *    given the firmware's notion of heads and sectors
208                  *    per cylinder.
209                  * 2. Calculate the number of cylinders, given the total
210                  *    size of the media.
211                  * All internal calculations should have 64-bit precision.
212                  */
213                 bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
214                 fwcylinders = mediasize / bytespercyl;
215 #if defined(DEBUG)
216                 linux_msg(td, "HDIO_GET_GEO: mediasize %jd, c/h/s %d/%d/%d, "
217                           "bpc %jd",
218                           (intmax_t)mediasize, fwcylinders, fwheads, fwsectors, 
219                           (intmax_t)bytespercyl);
220 #endif
221                 if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
222                         struct linux_hd_geometry hdg;
223
224                         hdg.cylinders = fwcylinders;
225                         hdg.heads = fwheads;
226                         hdg.sectors = fwsectors;
227                         hdg.start = 0;
228                         error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
229                 } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
230                         struct linux_hd_big_geometry hdbg;
231
232                         hdbg.cylinders = fwcylinders;
233                         hdbg.heads = fwheads;
234                         hdbg.sectors = fwsectors;
235                         hdbg.start = 0;
236                         error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
237                 }
238                 return (error);
239                 break;
240         default:
241                 /* XXX */
242                 linux_msg(td,
243                         "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
244                         args->fd, (int)(args->cmd & 0xffff),
245                         (int)(args->cmd & 0xff00) >> 8,
246                         (int)(args->cmd & 0xff));
247                 break;
248         }
249         fdrop(fp, td);
250         return (ENOIOCTL);
251 }
252
253 static int
254 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
255 {
256         struct file *fp;
257         int error;
258         u_int sectorsize;
259         off_t mediasize;
260
261         if ((error = fget(td, args->fd, &fp)) != 0)
262                 return (error);
263         switch (args->cmd & 0xffff) {
264         case LINUX_BLKGETSIZE:
265                 error = fo_ioctl(fp, DIOCGSECTORSIZE,
266                     (caddr_t)&sectorsize, td->td_ucred, td);
267                 if (!error)
268                         error = fo_ioctl(fp, DIOCGMEDIASIZE,
269                             (caddr_t)&mediasize, td->td_ucred, td);
270                 fdrop(fp, td);
271                 if (error)
272                         return (error);
273                 sectorsize = mediasize / sectorsize;
274                 /*
275                  * XXX: How do we know we return the right size of integer ?
276                  */
277                 return (copyout(&sectorsize, (void *)args->arg,
278                     sizeof(sectorsize)));
279                 break;
280         }
281         fdrop(fp, td);
282         return (ENOIOCTL);
283 }
284
285 /*
286  * termio related ioctls
287  */
288
289 struct linux_termio {
290         unsigned short c_iflag;
291         unsigned short c_oflag;
292         unsigned short c_cflag;
293         unsigned short c_lflag;
294         unsigned char c_line;
295         unsigned char c_cc[LINUX_NCC];
296 };
297
298 struct linux_termios {
299         unsigned int c_iflag;
300         unsigned int c_oflag;
301         unsigned int c_cflag;
302         unsigned int c_lflag;
303         unsigned char c_line;
304         unsigned char c_cc[LINUX_NCCS];
305 };
306
307 struct linux_winsize {
308         unsigned short ws_row, ws_col;
309         unsigned short ws_xpixel, ws_ypixel;
310 };
311
312 struct speedtab {
313         int sp_speed;                   /* Speed. */
314         int sp_code;                    /* Code. */
315 };
316
317 static struct speedtab sptab[] = {
318         { B0, LINUX_B0 }, { B50, LINUX_B50 },
319         { B75, LINUX_B75 }, { B110, LINUX_B110 },
320         { B134, LINUX_B134 }, { B150, LINUX_B150 },
321         { B200, LINUX_B200 }, { B300, LINUX_B300 },
322         { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
323         { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
324         { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
325         { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
326         { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
327         {-1, -1 }
328 };
329
330 struct linux_serial_struct {
331         int     type;
332         int     line;
333         int     port;
334         int     irq;
335         int     flags;
336         int     xmit_fifo_size;
337         int     custom_divisor;
338         int     baud_base;
339         unsigned short close_delay;
340         char    reserved_char[2];
341         int     hub6;
342         unsigned short closing_wait;
343         unsigned short closing_wait2;
344         int     reserved[4];
345 };
346
347 static int
348 linux_to_bsd_speed(int code, struct speedtab *table)
349 {
350         for ( ; table->sp_code != -1; table++)
351                 if (table->sp_code == code)
352                         return (table->sp_speed);
353         return -1;
354 }
355
356 static int
357 bsd_to_linux_speed(int speed, struct speedtab *table)
358 {
359         for ( ; table->sp_speed != -1; table++)
360                 if (table->sp_speed == speed)
361                         return (table->sp_code);
362         return -1;
363 }
364
365 static void
366 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
367 {
368         int i;
369
370 #ifdef DEBUG
371         if (ldebug(ioctl)) {
372                 printf("LINUX: BSD termios structure (input):\n");
373                 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
374                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
375                     bios->c_ispeed, bios->c_ospeed);
376                 printf("c_cc ");
377                 for (i=0; i<NCCS; i++)
378                         printf("%02x ", bios->c_cc[i]);
379                 printf("\n");
380         }
381 #endif
382
383         lios->c_iflag = 0;
384         if (bios->c_iflag & IGNBRK)
385                 lios->c_iflag |= LINUX_IGNBRK;
386         if (bios->c_iflag & BRKINT)
387                 lios->c_iflag |= LINUX_BRKINT;
388         if (bios->c_iflag & IGNPAR)
389                 lios->c_iflag |= LINUX_IGNPAR;
390         if (bios->c_iflag & PARMRK)
391                 lios->c_iflag |= LINUX_PARMRK;
392         if (bios->c_iflag & INPCK)
393                 lios->c_iflag |= LINUX_INPCK;
394         if (bios->c_iflag & ISTRIP)
395                 lios->c_iflag |= LINUX_ISTRIP;
396         if (bios->c_iflag & INLCR)
397                 lios->c_iflag |= LINUX_INLCR;
398         if (bios->c_iflag & IGNCR)
399                 lios->c_iflag |= LINUX_IGNCR;
400         if (bios->c_iflag & ICRNL)
401                 lios->c_iflag |= LINUX_ICRNL;
402         if (bios->c_iflag & IXON)
403                 lios->c_iflag |= LINUX_IXON;
404         if (bios->c_iflag & IXANY)
405                 lios->c_iflag |= LINUX_IXANY;
406         if (bios->c_iflag & IXOFF)
407                 lios->c_iflag |= LINUX_IXOFF;
408         if (bios->c_iflag & IMAXBEL)
409                 lios->c_iflag |= LINUX_IMAXBEL;
410
411         lios->c_oflag = 0;
412         if (bios->c_oflag & OPOST)
413                 lios->c_oflag |= LINUX_OPOST;
414         if (bios->c_oflag & ONLCR)
415                 lios->c_oflag |= LINUX_ONLCR;
416         if (bios->c_oflag & TAB3)
417                 lios->c_oflag |= LINUX_XTABS;
418
419         lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
420         lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
421         if (bios->c_cflag & CSTOPB)
422                 lios->c_cflag |= LINUX_CSTOPB;
423         if (bios->c_cflag & CREAD)
424                 lios->c_cflag |= LINUX_CREAD;
425         if (bios->c_cflag & PARENB)
426                 lios->c_cflag |= LINUX_PARENB;
427         if (bios->c_cflag & PARODD)
428                 lios->c_cflag |= LINUX_PARODD;
429         if (bios->c_cflag & HUPCL)
430                 lios->c_cflag |= LINUX_HUPCL;
431         if (bios->c_cflag & CLOCAL)
432                 lios->c_cflag |= LINUX_CLOCAL;
433         if (bios->c_cflag & CRTSCTS)
434                 lios->c_cflag |= LINUX_CRTSCTS;
435
436         lios->c_lflag = 0;
437         if (bios->c_lflag & ISIG)
438                 lios->c_lflag |= LINUX_ISIG;
439         if (bios->c_lflag & ICANON)
440                 lios->c_lflag |= LINUX_ICANON;
441         if (bios->c_lflag & ECHO)
442                 lios->c_lflag |= LINUX_ECHO;
443         if (bios->c_lflag & ECHOE)
444                 lios->c_lflag |= LINUX_ECHOE;
445         if (bios->c_lflag & ECHOK)
446                 lios->c_lflag |= LINUX_ECHOK;
447         if (bios->c_lflag & ECHONL)
448                 lios->c_lflag |= LINUX_ECHONL;
449         if (bios->c_lflag & NOFLSH)
450                 lios->c_lflag |= LINUX_NOFLSH;
451         if (bios->c_lflag & TOSTOP)
452                 lios->c_lflag |= LINUX_TOSTOP;
453         if (bios->c_lflag & ECHOCTL)
454                 lios->c_lflag |= LINUX_ECHOCTL;
455         if (bios->c_lflag & ECHOPRT)
456                 lios->c_lflag |= LINUX_ECHOPRT;
457         if (bios->c_lflag & ECHOKE)
458                 lios->c_lflag |= LINUX_ECHOKE;
459         if (bios->c_lflag & FLUSHO)
460                 lios->c_lflag |= LINUX_FLUSHO;
461         if (bios->c_lflag & PENDIN)
462                 lios->c_lflag |= LINUX_PENDIN;
463         if (bios->c_lflag & IEXTEN)
464                 lios->c_lflag |= LINUX_IEXTEN;
465
466         for (i=0; i<LINUX_NCCS; i++)
467                 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
468         lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
469         lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
470         lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
471         lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
472         lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
473         lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
474         lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
475         lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
476         lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
477         lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
478         lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
479         lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
480         lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
481         lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
482         lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
483         lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
484
485         for (i=0; i<LINUX_NCCS; i++) {
486                 if (i != LINUX_VMIN && i != LINUX_VTIME &&
487                     lios->c_cc[i] == _POSIX_VDISABLE)
488                         lios->c_cc[i] = LINUX_POSIX_VDISABLE;
489         }
490         lios->c_line = 0;
491
492 #ifdef DEBUG
493         if (ldebug(ioctl)) {
494                 printf("LINUX: LINUX termios structure (output):\n");
495                 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
496                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
497                     lios->c_lflag, (int)lios->c_line);
498                 printf("c_cc ");
499                 for (i=0; i<LINUX_NCCS; i++)
500                         printf("%02x ", lios->c_cc[i]);
501                 printf("\n");
502         }
503 #endif
504 }
505
506 static void
507 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
508 {
509         int i;
510
511 #ifdef DEBUG
512         if (ldebug(ioctl)) {
513                 printf("LINUX: LINUX termios structure (input):\n");
514                 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
515                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
516                     lios->c_lflag, (int)lios->c_line);
517                 printf("c_cc ");
518                 for (i=0; i<LINUX_NCCS; i++)
519                         printf("%02x ", lios->c_cc[i]);
520                 printf("\n");
521         }
522 #endif
523
524         bios->c_iflag = 0;
525         if (lios->c_iflag & LINUX_IGNBRK)
526                 bios->c_iflag |= IGNBRK;
527         if (lios->c_iflag & LINUX_BRKINT)
528                 bios->c_iflag |= BRKINT;
529         if (lios->c_iflag & LINUX_IGNPAR)
530                 bios->c_iflag |= IGNPAR;
531         if (lios->c_iflag & LINUX_PARMRK)
532                 bios->c_iflag |= PARMRK;
533         if (lios->c_iflag & LINUX_INPCK)
534                 bios->c_iflag |= INPCK;
535         if (lios->c_iflag & LINUX_ISTRIP)
536                 bios->c_iflag |= ISTRIP;
537         if (lios->c_iflag & LINUX_INLCR)
538                 bios->c_iflag |= INLCR;
539         if (lios->c_iflag & LINUX_IGNCR)
540                 bios->c_iflag |= IGNCR;
541         if (lios->c_iflag & LINUX_ICRNL)
542                 bios->c_iflag |= ICRNL;
543         if (lios->c_iflag & LINUX_IXON)
544                 bios->c_iflag |= IXON;
545         if (lios->c_iflag & LINUX_IXANY)
546                 bios->c_iflag |= IXANY;
547         if (lios->c_iflag & LINUX_IXOFF)
548                 bios->c_iflag |= IXOFF;
549         if (lios->c_iflag & LINUX_IMAXBEL)
550                 bios->c_iflag |= IMAXBEL;
551
552         bios->c_oflag = 0;
553         if (lios->c_oflag & LINUX_OPOST)
554                 bios->c_oflag |= OPOST;
555         if (lios->c_oflag & LINUX_ONLCR)
556                 bios->c_oflag |= ONLCR;
557         if (lios->c_oflag & LINUX_XTABS)
558                 bios->c_oflag |= TAB3;
559
560         bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
561         if (lios->c_cflag & LINUX_CSTOPB)
562                 bios->c_cflag |= CSTOPB;
563         if (lios->c_cflag & LINUX_CREAD)
564                 bios->c_cflag |= CREAD;
565         if (lios->c_cflag & LINUX_PARENB)
566                 bios->c_cflag |= PARENB;
567         if (lios->c_cflag & LINUX_PARODD)
568                 bios->c_cflag |= PARODD;
569         if (lios->c_cflag & LINUX_HUPCL)
570                 bios->c_cflag |= HUPCL;
571         if (lios->c_cflag & LINUX_CLOCAL)
572                 bios->c_cflag |= CLOCAL;
573         if (lios->c_cflag & LINUX_CRTSCTS)
574                 bios->c_cflag |= CRTSCTS;
575
576         bios->c_lflag = 0;
577         if (lios->c_lflag & LINUX_ISIG)
578                 bios->c_lflag |= ISIG;
579         if (lios->c_lflag & LINUX_ICANON)
580                 bios->c_lflag |= ICANON;
581         if (lios->c_lflag & LINUX_ECHO)
582                 bios->c_lflag |= ECHO;
583         if (lios->c_lflag & LINUX_ECHOE)
584                 bios->c_lflag |= ECHOE;
585         if (lios->c_lflag & LINUX_ECHOK)
586                 bios->c_lflag |= ECHOK;
587         if (lios->c_lflag & LINUX_ECHONL)
588                 bios->c_lflag |= ECHONL;
589         if (lios->c_lflag & LINUX_NOFLSH)
590                 bios->c_lflag |= NOFLSH;
591         if (lios->c_lflag & LINUX_TOSTOP)
592                 bios->c_lflag |= TOSTOP;
593         if (lios->c_lflag & LINUX_ECHOCTL)
594                 bios->c_lflag |= ECHOCTL;
595         if (lios->c_lflag & LINUX_ECHOPRT)
596                 bios->c_lflag |= ECHOPRT;
597         if (lios->c_lflag & LINUX_ECHOKE)
598                 bios->c_lflag |= ECHOKE;
599         if (lios->c_lflag & LINUX_FLUSHO)
600                 bios->c_lflag |= FLUSHO;
601         if (lios->c_lflag & LINUX_PENDIN)
602                 bios->c_lflag |= PENDIN;
603         if (lios->c_lflag & LINUX_IEXTEN)
604                 bios->c_lflag |= IEXTEN;
605
606         for (i=0; i<NCCS; i++)
607                 bios->c_cc[i] = _POSIX_VDISABLE;
608         bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
609         bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
610         bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
611         bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
612         bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
613         bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
614         bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
615         bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
616         bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
617         bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
618         bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
619         bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
620         bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
621         bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
622         bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
623         bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
624
625         for (i=0; i<NCCS; i++) {
626                 if (i != VMIN && i != VTIME &&
627                     bios->c_cc[i] == LINUX_POSIX_VDISABLE)
628                         bios->c_cc[i] = _POSIX_VDISABLE;
629         }
630
631         bios->c_ispeed = bios->c_ospeed =
632             linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
633
634 #ifdef DEBUG
635         if (ldebug(ioctl)) {
636                 printf("LINUX: BSD termios structure (output):\n");
637                 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
638                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
639                     bios->c_ispeed, bios->c_ospeed);
640                 printf("c_cc ");
641                 for (i=0; i<NCCS; i++)
642                         printf("%02x ", bios->c_cc[i]);
643                 printf("\n");
644         }
645 #endif
646 }
647
648 static void
649 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
650 {
651         struct linux_termios lios;
652
653         bsd_to_linux_termios(bios, &lios);
654         lio->c_iflag = lios.c_iflag;
655         lio->c_oflag = lios.c_oflag;
656         lio->c_cflag = lios.c_cflag;
657         lio->c_lflag = lios.c_lflag;
658         lio->c_line  = lios.c_line;
659         memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
660 }
661
662 static void
663 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
664 {
665         struct linux_termios lios;
666         int i;
667
668         lios.c_iflag = lio->c_iflag;
669         lios.c_oflag = lio->c_oflag;
670         lios.c_cflag = lio->c_cflag;
671         lios.c_lflag = lio->c_lflag;
672         for (i=LINUX_NCC; i<LINUX_NCCS; i++)
673                 lios.c_cc[i] = LINUX_POSIX_VDISABLE;
674         memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
675         linux_to_bsd_termios(&lios, bios);
676 }
677
678 static int
679 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
680 {
681         struct termios bios;
682         struct linux_termios lios;
683         struct linux_termio lio;
684         struct file *fp;
685         int error;
686
687         if ((error = fget(td, args->fd, &fp)) != 0)
688                 return (error);
689
690         switch (args->cmd & 0xffff) {
691
692         case LINUX_TCGETS:
693                 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
694                     td);
695                 if (error)
696                         break;
697                 bsd_to_linux_termios(&bios, &lios);
698                 error = copyout(&lios, (void *)args->arg, sizeof(lios));
699                 break;
700
701         case LINUX_TCSETS:
702                 error = copyin((void *)args->arg, &lios, sizeof(lios));
703                 if (error)
704                         break;
705                 linux_to_bsd_termios(&lios, &bios);
706                 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
707                     td));
708                 break;
709
710         case LINUX_TCSETSW:
711                 error = copyin((void *)args->arg, &lios, sizeof(lios));
712                 if (error)
713                         break;
714                 linux_to_bsd_termios(&lios, &bios);
715                 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
716                     td));
717                 break;
718
719         case LINUX_TCSETSF:
720                 error = copyin((void *)args->arg, &lios, sizeof(lios));
721                 if (error)
722                         break;
723                 linux_to_bsd_termios(&lios, &bios);
724                 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
725                     td));
726                 break;
727
728         case LINUX_TCGETA:
729                 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
730                     td);
731                 if (error)
732                         break;
733                 bsd_to_linux_termio(&bios, &lio);
734                 error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
735                 break;
736
737         case LINUX_TCSETA:
738                 error = copyin((void *)args->arg, &lio, sizeof(lio));
739                 if (error)
740                         break;
741                 linux_to_bsd_termio(&lio, &bios);
742                 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
743                     td));
744                 break;
745
746         case LINUX_TCSETAW:
747                 error = copyin((void *)args->arg, &lio, sizeof(lio));
748                 if (error)
749                         break;
750                 linux_to_bsd_termio(&lio, &bios);
751                 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
752                     td));
753                 break;
754
755         case LINUX_TCSETAF:
756                 error = copyin((void *)args->arg, &lio, sizeof(lio));
757                 if (error)
758                         break;
759                 linux_to_bsd_termio(&lio, &bios);
760                 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
761                     td));
762                 break;
763
764         /* LINUX_TCSBRK */
765
766         case LINUX_TCXONC: {
767                 switch (args->arg) {
768                 case LINUX_TCOOFF:
769                         args->cmd = TIOCSTOP;
770                         break;
771                 case LINUX_TCOON:
772                         args->cmd = TIOCSTART;
773                         break;
774                 case LINUX_TCIOFF:
775                 case LINUX_TCION: {
776                         int c;
777                         struct write_args wr;
778                         error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
779                             td->td_ucred, td);
780                         if (error)
781                                 break;
782                         fdrop(fp, td);
783                         c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
784                         c = bios.c_cc[c];
785                         if (c != _POSIX_VDISABLE) {
786                                 wr.fd = args->fd;
787                                 wr.buf = &c;
788                                 wr.nbyte = sizeof(c);
789                                 return (write(td, &wr));
790                         } else
791                                 return (0);
792                 }
793                 default:
794                         fdrop(fp, td);
795                         return (EINVAL);
796                 }
797                 args->arg = 0;
798                 error = (ioctl(td, (struct ioctl_args *)args));
799                 break;
800         }
801
802         case LINUX_TCFLSH: {
803                 int val;
804                 switch (args->arg) {
805                 case LINUX_TCIFLUSH:
806                         val = FREAD;
807                         break;
808                 case LINUX_TCOFLUSH:
809                         val = FWRITE;
810                         break;
811                 case LINUX_TCIOFLUSH:
812                         val = FREAD | FWRITE;
813                         break;
814                 default:
815                         fdrop(fp, td);
816                         return (EINVAL);
817                 }
818                 error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
819                 break;
820         }
821
822         case LINUX_TIOCEXCL:
823                 args->cmd = TIOCEXCL;
824                 error = (ioctl(td, (struct ioctl_args *)args));
825                 break;
826
827         case LINUX_TIOCNXCL:
828                 args->cmd = TIOCNXCL;
829                 error = (ioctl(td, (struct ioctl_args *)args));
830                 break;
831
832         case LINUX_TIOCSCTTY:
833                 args->cmd = TIOCSCTTY;
834                 error = (ioctl(td, (struct ioctl_args *)args));
835                 break;
836
837         case LINUX_TIOCGPGRP:
838                 args->cmd = TIOCGPGRP;
839                 error = (ioctl(td, (struct ioctl_args *)args));
840                 break;
841
842         case LINUX_TIOCSPGRP:
843                 args->cmd = TIOCSPGRP;
844                 error = (ioctl(td, (struct ioctl_args *)args));
845                 break;
846
847         /* LINUX_TIOCOUTQ */
848         /* LINUX_TIOCSTI */
849
850         case LINUX_TIOCGWINSZ:
851                 args->cmd = TIOCGWINSZ;
852                 error = (ioctl(td, (struct ioctl_args *)args));
853                 break;
854
855         case LINUX_TIOCSWINSZ:
856                 args->cmd = TIOCSWINSZ;
857                 error = (ioctl(td, (struct ioctl_args *)args));
858                 break;
859
860         case LINUX_TIOCMGET:
861                 args->cmd = TIOCMGET;
862                 error = (ioctl(td, (struct ioctl_args *)args));
863                 break;
864
865         case LINUX_TIOCMBIS:
866                 args->cmd = TIOCMBIS;
867                 error = (ioctl(td, (struct ioctl_args *)args));
868                 break;
869
870         case LINUX_TIOCMBIC:
871                 args->cmd = TIOCMBIC;
872                 error = (ioctl(td, (struct ioctl_args *)args));
873                 break;
874
875         case LINUX_TIOCMSET:
876                 args->cmd = TIOCMSET;
877                 error = (ioctl(td, (struct ioctl_args *)args));
878                 break;
879
880         /* TIOCGSOFTCAR */
881         /* TIOCSSOFTCAR */
882
883         case LINUX_FIONREAD: /* LINUX_TIOCINQ */
884                 args->cmd = FIONREAD;
885                 error = (ioctl(td, (struct ioctl_args *)args));
886                 break;
887
888         /* LINUX_TIOCLINUX */
889
890         case LINUX_TIOCCONS:
891                 args->cmd = TIOCCONS;
892                 error = (ioctl(td, (struct ioctl_args *)args));
893                 break;
894
895         case LINUX_TIOCGSERIAL: {
896                 struct linux_serial_struct lss;
897                 lss.type = LINUX_PORT_16550A;
898                 lss.flags = 0;
899                 lss.close_delay = 0;
900                 error = copyout(&lss, (void *)args->arg, sizeof(lss));
901                 break;
902         }
903
904         case LINUX_TIOCSSERIAL: {
905                 struct linux_serial_struct lss;
906                 error = copyin((void *)args->arg, &lss, sizeof(lss));
907                 if (error)
908                         break;
909                 /* XXX - It really helps to have an implementation that
910                  * does nothing. NOT!
911                  */
912                 error = 0;
913                 break;
914         }
915
916         case LINUX_TIOCPKT:
917                 args->cmd = TIOCPKT;
918                 error = (ioctl(td, (struct ioctl_args *)args));
919                 break;
920
921         case LINUX_FIONBIO:
922                 args->cmd = FIONBIO;
923                 error = (ioctl(td, (struct ioctl_args *)args));
924                 break;
925
926         case LINUX_TIOCNOTTY:
927                 args->cmd = TIOCNOTTY;
928                 error = (ioctl(td, (struct ioctl_args *)args));
929                 break;
930
931         case LINUX_TIOCSETD: {
932                 int line;
933                 switch (args->arg) {
934                 case LINUX_N_TTY:
935                         line = TTYDISC;
936                         break;
937                 case LINUX_N_SLIP:
938                         line = SLIPDISC;
939                         break;
940                 case LINUX_N_PPP:
941                         line = PPPDISC;
942                         break;
943                 default:
944                         fdrop(fp, td);
945                         return (EINVAL);
946                 }
947                 error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
948                     td));
949                 break;
950         }
951
952         case LINUX_TIOCGETD: {
953                 int linux_line;
954                 int bsd_line = TTYDISC;
955                 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
956                     td->td_ucred, td);
957                 if (error)
958                         return (error);
959                 switch (bsd_line) {
960                 case TTYDISC:
961                         linux_line = LINUX_N_TTY;
962                         break;
963                 case SLIPDISC:
964                         linux_line = LINUX_N_SLIP;
965                         break;
966                 case PPPDISC:
967                         linux_line = LINUX_N_PPP;
968                         break;
969                 default:
970                         fdrop(fp, td);
971                         return (EINVAL);
972                 }
973                 error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
974                 break;
975         }
976
977         /* LINUX_TCSBRKP */
978         /* LINUX_TIOCTTYGSTRUCT */
979
980         case LINUX_FIONCLEX:
981                 args->cmd = FIONCLEX;
982                 error = (ioctl(td, (struct ioctl_args *)args));
983                 break;
984
985         case LINUX_FIOCLEX:
986                 args->cmd = FIOCLEX;
987                 error = (ioctl(td, (struct ioctl_args *)args));
988                 break;
989
990         case LINUX_FIOASYNC:
991                 args->cmd = FIOASYNC;
992                 error = (ioctl(td, (struct ioctl_args *)args));
993                 break;
994
995         /* LINUX_TIOCSERCONFIG */
996         /* LINUX_TIOCSERGWILD */
997         /* LINUX_TIOCSERSWILD */
998         /* LINUX_TIOCGLCKTRMIOS */
999         /* LINUX_TIOCSLCKTRMIOS */
1000
1001         case LINUX_TIOCSBRK:
1002                 args->cmd = TIOCSBRK;
1003                 error = (ioctl(td, (struct ioctl_args *)args));
1004                 break;
1005
1006         case LINUX_TIOCCBRK:
1007                 args->cmd = TIOCCBRK;
1008                 error = (ioctl(td, (struct ioctl_args *)args));
1009                 break;
1010         case LINUX_TIOCGPTN: {
1011                 int nb;
1012                 
1013                 error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
1014                 if (!error)
1015                         error = copyout(&nb, (void *)args->arg,
1016                             sizeof(int));
1017                 break;
1018         }
1019         case LINUX_TIOCSPTLCK:
1020                 /* Our unlockpt() does nothing. */
1021                 error = 0;
1022                 break;
1023         default:
1024                 error = ENOIOCTL;
1025                 break;
1026         }
1027
1028         fdrop(fp, td);
1029         return (error);
1030 }
1031
1032 /*
1033  * CDROM related ioctls
1034  */
1035
1036 struct linux_cdrom_msf
1037 {
1038         u_char  cdmsf_min0;
1039         u_char  cdmsf_sec0;
1040         u_char  cdmsf_frame0;
1041         u_char  cdmsf_min1;
1042         u_char  cdmsf_sec1;
1043         u_char  cdmsf_frame1;
1044 };
1045
1046 struct linux_cdrom_tochdr
1047 {
1048         u_char  cdth_trk0;
1049         u_char  cdth_trk1;
1050 };
1051
1052 union linux_cdrom_addr
1053 {
1054         struct {
1055                 u_char  minute;
1056                 u_char  second;
1057                 u_char  frame;
1058         } msf;
1059         int     lba;
1060 };
1061
1062 struct linux_cdrom_tocentry
1063 {
1064         u_char  cdte_track;
1065         u_char  cdte_adr:4;
1066         u_char  cdte_ctrl:4;
1067         u_char  cdte_format;
1068         union linux_cdrom_addr cdte_addr;
1069         u_char  cdte_datamode;
1070 };
1071
1072 struct linux_cdrom_subchnl
1073 {
1074         u_char  cdsc_format;
1075         u_char  cdsc_audiostatus;
1076         u_char  cdsc_adr:4;
1077         u_char  cdsc_ctrl:4;
1078         u_char  cdsc_trk;
1079         u_char  cdsc_ind;
1080         union linux_cdrom_addr cdsc_absaddr;
1081         union linux_cdrom_addr cdsc_reladdr;
1082 };
1083
1084 struct l_cdrom_read_audio {
1085         union linux_cdrom_addr addr;
1086         u_char          addr_format;
1087         l_int           nframes;
1088         u_char          *buf;
1089 };
1090
1091 struct l_dvd_layer {
1092         u_char          book_version:4;
1093         u_char          book_type:4;
1094         u_char          min_rate:4;
1095         u_char          disc_size:4;
1096         u_char          layer_type:4;
1097         u_char          track_path:1;
1098         u_char          nlayers:2;
1099         u_char          track_density:4;
1100         u_char          linear_density:4;
1101         u_char          bca:1;
1102         u_int32_t       start_sector;
1103         u_int32_t       end_sector;
1104         u_int32_t       end_sector_l0;
1105 };
1106
1107 struct l_dvd_physical {
1108         u_char          type;
1109         u_char          layer_num;
1110         struct l_dvd_layer layer[4];
1111 };
1112
1113 struct l_dvd_copyright {
1114         u_char          type;
1115         u_char          layer_num;
1116         u_char          cpst;
1117         u_char          rmi;
1118 };
1119
1120 struct l_dvd_disckey {
1121         u_char          type;
1122         l_uint          agid:2;
1123         u_char          value[2048];
1124 };
1125
1126 struct l_dvd_bca {
1127         u_char          type;
1128         l_int           len;
1129         u_char          value[188];
1130 };
1131
1132 struct l_dvd_manufact {
1133         u_char          type;
1134         u_char          layer_num;
1135         l_int           len;
1136         u_char          value[2048];
1137 };
1138
1139 typedef union {
1140         u_char                  type;
1141         struct l_dvd_physical   physical;
1142         struct l_dvd_copyright  copyright;
1143         struct l_dvd_disckey    disckey;
1144         struct l_dvd_bca        bca;
1145         struct l_dvd_manufact   manufact;
1146 } l_dvd_struct;
1147
1148 typedef u_char l_dvd_key[5];
1149 typedef u_char l_dvd_challenge[10];
1150
1151 struct l_dvd_lu_send_agid {
1152         u_char          type;
1153         l_uint          agid:2;
1154 };
1155
1156 struct l_dvd_host_send_challenge {
1157         u_char          type;
1158         l_uint          agid:2;
1159         l_dvd_challenge chal;
1160 };
1161
1162 struct l_dvd_send_key {
1163         u_char          type;
1164         l_uint          agid:2;
1165         l_dvd_key       key;
1166 };
1167
1168 struct l_dvd_lu_send_challenge {
1169         u_char          type;
1170         l_uint          agid:2;
1171         l_dvd_challenge chal;
1172 };
1173
1174 struct l_dvd_lu_send_title_key {
1175         u_char          type;
1176         l_uint          agid:2;
1177         l_dvd_key       title_key;
1178         l_int           lba;
1179         l_uint          cpm:1;
1180         l_uint          cp_sec:1;
1181         l_uint          cgms:2;
1182 };
1183
1184 struct l_dvd_lu_send_asf {
1185         u_char          type;
1186         l_uint          agid:2;
1187         l_uint          asf:1;
1188 };
1189
1190 struct l_dvd_host_send_rpcstate {
1191         u_char          type;
1192         u_char          pdrc;
1193 };
1194
1195 struct l_dvd_lu_send_rpcstate {
1196         u_char          type:2;
1197         u_char          vra:3;
1198         u_char          ucca:3;
1199         u_char          region_mask;
1200         u_char          rpc_scheme;
1201 };
1202
1203 typedef union {
1204         u_char                          type;
1205         struct l_dvd_lu_send_agid       lsa;
1206         struct l_dvd_host_send_challenge hsc;
1207         struct l_dvd_send_key           lsk;
1208         struct l_dvd_lu_send_challenge  lsc;
1209         struct l_dvd_send_key           hsk;
1210         struct l_dvd_lu_send_title_key  lstk;
1211         struct l_dvd_lu_send_asf        lsasf;
1212         struct l_dvd_host_send_rpcstate hrpcs;
1213         struct l_dvd_lu_send_rpcstate   lrpcs;
1214 } l_dvd_authinfo;
1215
1216 static void
1217 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
1218 {
1219         if (af == CD_LBA_FORMAT)
1220                 lp->lba = bp->lba;
1221         else {
1222                 lp->msf.minute = bp->msf.minute;
1223                 lp->msf.second = bp->msf.second;
1224                 lp->msf.frame = bp->msf.frame;
1225         }
1226 }
1227
1228 static void
1229 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
1230 {
1231         if (format == LINUX_CDROM_MSF) {
1232                 addr->msf.frame = lba % 75;
1233                 lba /= 75;
1234                 lba += 2;
1235                 addr->msf.second = lba % 60;
1236                 addr->msf.minute = lba / 60;
1237         } else
1238                 addr->lba = lba;
1239 }
1240
1241 static int
1242 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
1243 {
1244         bp->format = lp->type;
1245         switch (bp->format) {
1246         case DVD_STRUCT_PHYSICAL:
1247                 if (bp->layer_num >= 4)
1248                         return (EINVAL);
1249                 bp->layer_num = lp->physical.layer_num;
1250                 break;
1251         case DVD_STRUCT_COPYRIGHT:
1252                 bp->layer_num = lp->copyright.layer_num;
1253                 break;
1254         case DVD_STRUCT_DISCKEY:
1255                 bp->agid = lp->disckey.agid;
1256                 break;
1257         case DVD_STRUCT_BCA:
1258         case DVD_STRUCT_MANUFACT:
1259                 break;
1260         default:
1261                 return (EINVAL);
1262         }
1263         return (0);
1264 }
1265
1266 static int
1267 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
1268 {
1269         switch (bp->format) {
1270         case DVD_STRUCT_PHYSICAL: {
1271                 struct dvd_layer *blp = (struct dvd_layer *)bp->data;
1272                 struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
1273                 memset(llp, 0, sizeof(*llp));
1274                 llp->book_version = blp->book_version;
1275                 llp->book_type = blp->book_type;
1276                 llp->min_rate = blp->max_rate;
1277                 llp->disc_size = blp->disc_size;
1278                 llp->layer_type = blp->layer_type;
1279                 llp->track_path = blp->track_path;
1280                 llp->nlayers = blp->nlayers;
1281                 llp->track_density = blp->track_density;
1282                 llp->linear_density = blp->linear_density;
1283                 llp->bca = blp->bca;
1284                 llp->start_sector = blp->start_sector;
1285                 llp->end_sector = blp->end_sector;
1286                 llp->end_sector_l0 = blp->end_sector_l0;
1287                 break;
1288         }
1289         case DVD_STRUCT_COPYRIGHT:
1290                 lp->copyright.cpst = bp->cpst;
1291                 lp->copyright.rmi = bp->rmi;
1292                 break;
1293         case DVD_STRUCT_DISCKEY:
1294                 memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
1295                 break;
1296         case DVD_STRUCT_BCA:
1297                 lp->bca.len = bp->length;
1298                 memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
1299                 break;
1300         case DVD_STRUCT_MANUFACT:
1301                 lp->manufact.len = bp->length;
1302                 memcpy(lp->manufact.value, bp->data,
1303                     sizeof(lp->manufact.value));
1304                 /* lp->manufact.layer_num is unused in linux (redhat 7.0) */
1305                 break;
1306         default:
1307                 return (EINVAL);
1308         }
1309         return (0);
1310 }
1311
1312 static int
1313 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
1314     struct dvd_authinfo *bp)
1315 {
1316         switch (lp->type) {
1317         case LINUX_DVD_LU_SEND_AGID:
1318                 *bcode = DVDIOCREPORTKEY;
1319                 bp->format = DVD_REPORT_AGID;
1320                 bp->agid = lp->lsa.agid;
1321                 break;
1322         case LINUX_DVD_HOST_SEND_CHALLENGE:
1323                 *bcode = DVDIOCSENDKEY;
1324                 bp->format = DVD_SEND_CHALLENGE;
1325                 bp->agid = lp->hsc.agid;
1326                 memcpy(bp->keychal, lp->hsc.chal, 10);
1327                 break;
1328         case LINUX_DVD_LU_SEND_KEY1:
1329                 *bcode = DVDIOCREPORTKEY;
1330                 bp->format = DVD_REPORT_KEY1;
1331                 bp->agid = lp->lsk.agid;
1332                 break;
1333         case LINUX_DVD_LU_SEND_CHALLENGE:
1334                 *bcode = DVDIOCREPORTKEY;
1335                 bp->format = DVD_REPORT_CHALLENGE;
1336                 bp->agid = lp->lsc.agid;
1337                 break;
1338         case LINUX_DVD_HOST_SEND_KEY2:
1339                 *bcode = DVDIOCSENDKEY;
1340                 bp->format = DVD_SEND_KEY2;
1341                 bp->agid = lp->hsk.agid;
1342                 memcpy(bp->keychal, lp->hsk.key, 5);
1343                 break;
1344         case LINUX_DVD_LU_SEND_TITLE_KEY:
1345                 *bcode = DVDIOCREPORTKEY;
1346                 bp->format = DVD_REPORT_TITLE_KEY;
1347                 bp->agid = lp->lstk.agid;
1348                 bp->lba = lp->lstk.lba;
1349                 break;
1350         case LINUX_DVD_LU_SEND_ASF:
1351                 *bcode = DVDIOCREPORTKEY;
1352                 bp->format = DVD_REPORT_ASF;
1353                 bp->agid = lp->lsasf.agid;
1354                 break;
1355         case LINUX_DVD_INVALIDATE_AGID:
1356                 *bcode = DVDIOCREPORTKEY;
1357                 bp->format = DVD_INVALIDATE_AGID;
1358                 bp->agid = lp->lsa.agid;
1359                 break;
1360         case LINUX_DVD_LU_SEND_RPC_STATE:
1361                 *bcode = DVDIOCREPORTKEY;
1362                 bp->format = DVD_REPORT_RPC;
1363                 break;
1364         case LINUX_DVD_HOST_SEND_RPC_STATE:
1365                 *bcode = DVDIOCSENDKEY;
1366                 bp->format = DVD_SEND_RPC;
1367                 bp->region = lp->hrpcs.pdrc;
1368                 break;
1369         default:
1370                 return (EINVAL);
1371         }
1372         return (0);
1373 }
1374
1375 static int
1376 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
1377 {
1378         switch (lp->type) {
1379         case LINUX_DVD_LU_SEND_AGID:
1380                 lp->lsa.agid = bp->agid;
1381                 break;
1382         case LINUX_DVD_HOST_SEND_CHALLENGE:
1383                 lp->type = LINUX_DVD_LU_SEND_KEY1;
1384                 break;
1385         case LINUX_DVD_LU_SEND_KEY1:
1386                 memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
1387                 break;
1388         case LINUX_DVD_LU_SEND_CHALLENGE:
1389                 memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
1390                 break;
1391         case LINUX_DVD_HOST_SEND_KEY2:
1392                 lp->type = LINUX_DVD_AUTH_ESTABLISHED;
1393                 break;
1394         case LINUX_DVD_LU_SEND_TITLE_KEY:
1395                 memcpy(lp->lstk.title_key, bp->keychal,
1396                     sizeof(lp->lstk.title_key));
1397                 lp->lstk.cpm = bp->cpm;
1398                 lp->lstk.cp_sec = bp->cp_sec;
1399                 lp->lstk.cgms = bp->cgms;
1400                 break;
1401         case LINUX_DVD_LU_SEND_ASF:
1402                 lp->lsasf.asf = bp->asf;
1403                 break;
1404         case LINUX_DVD_INVALIDATE_AGID:
1405                 break;
1406         case LINUX_DVD_LU_SEND_RPC_STATE:
1407                 lp->lrpcs.type = bp->reg_type;
1408                 lp->lrpcs.vra = bp->vend_rsts;
1409                 lp->lrpcs.ucca = bp->user_rsts;
1410                 lp->lrpcs.region_mask = bp->region;
1411                 lp->lrpcs.rpc_scheme = bp->rpc_scheme;
1412                 break;
1413         case LINUX_DVD_HOST_SEND_RPC_STATE:
1414                 break;
1415         default:
1416                 return (EINVAL);
1417         }
1418         return (0);
1419 }
1420
1421 static int
1422 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
1423 {
1424         struct file *fp;
1425         int error;
1426
1427         if ((error = fget(td, args->fd, &fp)) != 0)
1428                 return (error);
1429         switch (args->cmd & 0xffff) {
1430
1431         case LINUX_CDROMPAUSE:
1432                 args->cmd = CDIOCPAUSE;
1433                 error = (ioctl(td, (struct ioctl_args *)args));
1434                 break;
1435
1436         case LINUX_CDROMRESUME:
1437                 args->cmd = CDIOCRESUME;
1438                 error = (ioctl(td, (struct ioctl_args *)args));
1439                 break;
1440
1441         case LINUX_CDROMPLAYMSF:
1442                 args->cmd = CDIOCPLAYMSF;
1443                 error = (ioctl(td, (struct ioctl_args *)args));
1444                 break;
1445
1446         case LINUX_CDROMPLAYTRKIND:
1447                 args->cmd = CDIOCPLAYTRACKS;
1448                 error = (ioctl(td, (struct ioctl_args *)args));
1449                 break;
1450
1451         case LINUX_CDROMREADTOCHDR: {
1452                 struct ioc_toc_header th;
1453                 struct linux_cdrom_tochdr lth;
1454                 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
1455                     td->td_ucred, td);
1456                 if (!error) {
1457                         lth.cdth_trk0 = th.starting_track;
1458                         lth.cdth_trk1 = th.ending_track;
1459                         copyout(&lth, (void *)args->arg, sizeof(lth));
1460                 }
1461                 break;
1462         }
1463
1464         case LINUX_CDROMREADTOCENTRY: {
1465                 struct linux_cdrom_tocentry lte;
1466                 struct ioc_read_toc_single_entry irtse;
1467
1468                 error = copyin((void *)args->arg, &lte, sizeof(lte));
1469                 if (error)
1470                         break;
1471                 irtse.address_format = lte.cdte_format;
1472                 irtse.track = lte.cdte_track;
1473                 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
1474                     td->td_ucred, td);
1475                 if (!error) {
1476                         lte.cdte_ctrl = irtse.entry.control;
1477                         lte.cdte_adr = irtse.entry.addr_type;
1478                         bsd_to_linux_msf_lba(irtse.address_format,
1479                             &irtse.entry.addr, &lte.cdte_addr);
1480                         error = copyout(&lte, (void *)args->arg, sizeof(lte));
1481                 }
1482                 break;
1483         }
1484
1485         case LINUX_CDROMSTOP:
1486                 args->cmd = CDIOCSTOP;
1487                 error = (ioctl(td, (struct ioctl_args *)args));
1488                 break;
1489
1490         case LINUX_CDROMSTART:
1491                 args->cmd = CDIOCSTART;
1492                 error = (ioctl(td, (struct ioctl_args *)args));
1493                 break;
1494
1495         case LINUX_CDROMEJECT:
1496                 args->cmd = CDIOCEJECT;
1497                 error = (ioctl(td, (struct ioctl_args *)args));
1498                 break;
1499
1500         /* LINUX_CDROMVOLCTRL */
1501
1502         case LINUX_CDROMSUBCHNL: {
1503                 struct linux_cdrom_subchnl sc;
1504                 struct ioc_read_subchannel bsdsc;
1505                 struct cd_sub_channel_info bsdinfo;
1506
1507                 bsdsc.address_format = CD_LBA_FORMAT;
1508                 bsdsc.data_format = CD_CURRENT_POSITION;
1509                 bsdsc.track = 0;
1510                 bsdsc.data_len = sizeof(bsdinfo);
1511                 bsdsc.data = &bsdinfo;
1512                 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE,
1513                     (caddr_t)&bsdsc, td->td_ucred, td);
1514                 if (error)
1515                         break;
1516                 error = copyin((void *)args->arg, &sc, sizeof(sc));
1517                 if (error)
1518                         break;
1519                 sc.cdsc_audiostatus = bsdinfo.header.audio_status;
1520                 sc.cdsc_adr = bsdinfo.what.position.addr_type;
1521                 sc.cdsc_ctrl = bsdinfo.what.position.control;
1522                 sc.cdsc_trk = bsdinfo.what.position.track_number;
1523                 sc.cdsc_ind = bsdinfo.what.position.index_number;
1524                 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
1525                     bsdinfo.what.position.absaddr.lba);
1526                 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
1527                     bsdinfo.what.position.reladdr.lba);
1528                 error = copyout(&sc, (void *)args->arg, sizeof(sc));
1529                 break;
1530         }
1531
1532         /* LINUX_CDROMREADMODE2 */
1533         /* LINUX_CDROMREADMODE1 */
1534         /* LINUX_CDROMREADAUDIO */
1535         /* LINUX_CDROMEJECT_SW */
1536         /* LINUX_CDROMMULTISESSION */
1537         /* LINUX_CDROM_GET_UPC */
1538
1539         case LINUX_CDROMRESET:
1540                 args->cmd = CDIOCRESET;
1541                 error = (ioctl(td, (struct ioctl_args *)args));
1542                 break;
1543
1544         /* LINUX_CDROMVOLREAD */
1545         /* LINUX_CDROMREADRAW */
1546         /* LINUX_CDROMREADCOOKED */
1547         /* LINUX_CDROMSEEK */
1548         /* LINUX_CDROMPLAYBLK */
1549         /* LINUX_CDROMREADALL */
1550         /* LINUX_CDROMCLOSETRAY */
1551         /* LINUX_CDROMLOADFROMSLOT */
1552         /* LINUX_CDROMGETSPINDOWN */
1553         /* LINUX_CDROMSETSPINDOWN */
1554         /* LINUX_CDROM_SET_OPTIONS */
1555         /* LINUX_CDROM_CLEAR_OPTIONS */
1556         /* LINUX_CDROM_SELECT_SPEED */
1557         /* LINUX_CDROM_SELECT_DISC */
1558         /* LINUX_CDROM_MEDIA_CHANGED */
1559         /* LINUX_CDROM_DRIVE_STATUS */
1560         /* LINUX_CDROM_DISC_STATUS */
1561         /* LINUX_CDROM_CHANGER_NSLOTS */
1562         /* LINUX_CDROM_LOCKDOOR */
1563         /* LINUX_CDROM_DEBUG */
1564         /* LINUX_CDROM_GET_CAPABILITY */
1565         /* LINUX_CDROMAUDIOBUFSIZ */
1566
1567         case LINUX_DVD_READ_STRUCT: {
1568                 l_dvd_struct *lds;
1569                 struct dvd_struct *bds;
1570
1571                 lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK);
1572                 bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK);
1573                 error = copyin((void *)args->arg, lds, sizeof(*lds));
1574                 if (error)
1575                         goto out;
1576                 error = linux_to_bsd_dvd_struct(lds, bds);
1577                 if (error)
1578                         goto out;
1579                 error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds,
1580                     td->td_ucred, td);
1581                 if (error)
1582                         goto out;
1583                 error = bsd_to_linux_dvd_struct(bds, lds);
1584                 if (error)
1585                         goto out;
1586                 error = copyout(lds, (void *)args->arg, sizeof(*lds));
1587         out:
1588                 free(bds, M_LINUX);
1589                 free(lds, M_LINUX);
1590                 break;
1591         }
1592
1593         /* LINUX_DVD_WRITE_STRUCT */
1594
1595         case LINUX_DVD_AUTH: {
1596                 l_dvd_authinfo lda;
1597                 struct dvd_authinfo bda;
1598                 int bcode;
1599
1600                 error = copyin((void *)args->arg, &lda, sizeof(lda));
1601                 if (error)
1602                         break;
1603                 error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
1604                 if (error)
1605                         break;
1606                 error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
1607                     td);
1608                 if (error) {
1609                         if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
1610                                 lda.type = LINUX_DVD_AUTH_FAILURE;
1611                                 copyout(&lda, (void *)args->arg, sizeof(lda));
1612                         }
1613                         break;
1614                 }
1615                 error = bsd_to_linux_dvd_authinfo(&bda, &lda);
1616                 if (error)
1617                         break;
1618                 error = copyout(&lda, (void *)args->arg, sizeof(lda));
1619                 break;
1620         }
1621
1622         case LINUX_SCSI_GET_BUS_NUMBER:
1623         case LINUX_SCSI_GET_IDLUN:
1624                 error = linux_ioctl_sg(td, args);
1625                 break;
1626
1627         /* LINUX_CDROM_SEND_PACKET */
1628         /* LINUX_CDROM_NEXT_WRITABLE */
1629         /* LINUX_CDROM_LAST_WRITTEN */
1630
1631         default:
1632                 error = ENOIOCTL;
1633                 break;
1634         }
1635
1636         fdrop(fp, td);
1637         return (error);
1638 }
1639
1640 static int
1641 linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
1642 {
1643
1644         return (ENOTTY);
1645 }
1646
1647 /*
1648  * Sound related ioctls
1649  */
1650
1651 struct linux_mixer_info {
1652         char    id[16];
1653         char    name[32];
1654         int     modify_counter;
1655         int     fillers[10];
1656 };
1657
1658 struct linux_old_mixer_info {
1659         char    id[16];
1660         char    name[32];
1661 };
1662
1663 static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
1664
1665 #define SETDIR(c)       (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
1666
1667 static int
1668 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
1669 {
1670
1671         switch (args->cmd & 0xffff) {
1672
1673         case LINUX_SOUND_MIXER_WRITE_VOLUME:
1674                 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
1675                 return (ioctl(td, (struct ioctl_args *)args));
1676
1677         case LINUX_SOUND_MIXER_WRITE_BASS:
1678                 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
1679                 return (ioctl(td, (struct ioctl_args *)args));
1680
1681         case LINUX_SOUND_MIXER_WRITE_TREBLE:
1682                 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
1683                 return (ioctl(td, (struct ioctl_args *)args));
1684
1685         case LINUX_SOUND_MIXER_WRITE_SYNTH:
1686                 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
1687                 return (ioctl(td, (struct ioctl_args *)args));
1688
1689         case LINUX_SOUND_MIXER_WRITE_PCM:
1690                 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
1691                 return (ioctl(td, (struct ioctl_args *)args));
1692
1693         case LINUX_SOUND_MIXER_WRITE_SPEAKER:
1694                 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
1695                 return (ioctl(td, (struct ioctl_args *)args));
1696
1697         case LINUX_SOUND_MIXER_WRITE_LINE:
1698                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
1699                 return (ioctl(td, (struct ioctl_args *)args));
1700
1701         case LINUX_SOUND_MIXER_WRITE_MIC:
1702                 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
1703                 return (ioctl(td, (struct ioctl_args *)args));
1704
1705         case LINUX_SOUND_MIXER_WRITE_CD:
1706                 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
1707                 return (ioctl(td, (struct ioctl_args *)args));
1708
1709         case LINUX_SOUND_MIXER_WRITE_IMIX:
1710                 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
1711                 return (ioctl(td, (struct ioctl_args *)args));
1712
1713         case LINUX_SOUND_MIXER_WRITE_ALTPCM:
1714                 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
1715                 return (ioctl(td, (struct ioctl_args *)args));
1716
1717         case LINUX_SOUND_MIXER_WRITE_RECLEV:
1718                 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
1719                 return (ioctl(td, (struct ioctl_args *)args));
1720
1721         case LINUX_SOUND_MIXER_WRITE_IGAIN:
1722                 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
1723                 return (ioctl(td, (struct ioctl_args *)args));
1724
1725         case LINUX_SOUND_MIXER_WRITE_OGAIN:
1726                 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
1727                 return (ioctl(td, (struct ioctl_args *)args));
1728
1729         case LINUX_SOUND_MIXER_WRITE_LINE1:
1730                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
1731                 return (ioctl(td, (struct ioctl_args *)args));
1732
1733         case LINUX_SOUND_MIXER_WRITE_LINE2:
1734                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
1735                 return (ioctl(td, (struct ioctl_args *)args));
1736
1737         case LINUX_SOUND_MIXER_WRITE_LINE3:
1738                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
1739                 return (ioctl(td, (struct ioctl_args *)args));
1740
1741         case LINUX_SOUND_MIXER_INFO: {
1742                 /* Key on encoded length */
1743                 switch ((args->cmd >> 16) & 0x1fff) {
1744                 case 0x005c: {  /* SOUND_MIXER_INFO */
1745                         struct linux_mixer_info info;
1746                         bzero(&info, sizeof(info));
1747                         strncpy(info.id, "OSS", sizeof(info.id) - 1);
1748                         strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
1749                         copyout(&info, (void *)args->arg, sizeof(info));
1750                         break;
1751                 }
1752                 case 0x0030: {  /* SOUND_OLD_MIXER_INFO */
1753                         struct linux_old_mixer_info info;
1754                         bzero(&info, sizeof(info));
1755                         strncpy(info.id, "OSS", sizeof(info.id) - 1);
1756                         strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
1757                         copyout(&info, (void *)args->arg, sizeof(info));
1758                         break;
1759                 }
1760                 default:
1761                         return (ENOIOCTL);
1762                 }
1763                 break;
1764         }
1765
1766         case LINUX_OSS_GETVERSION: {
1767                 int version = linux_get_oss_version(td);
1768                 return (copyout(&version, (void *)args->arg, sizeof(int)));
1769         }
1770
1771         case LINUX_SOUND_MIXER_READ_STEREODEVS:
1772                 args->cmd = SOUND_MIXER_READ_STEREODEVS;
1773                 return (ioctl(td, (struct ioctl_args *)args));
1774
1775         case LINUX_SOUND_MIXER_READ_RECMASK:
1776                 args->cmd = SOUND_MIXER_READ_RECMASK;
1777                 return (ioctl(td, (struct ioctl_args *)args));
1778
1779         case LINUX_SOUND_MIXER_READ_DEVMASK:
1780                 args->cmd = SOUND_MIXER_READ_DEVMASK;
1781                 return (ioctl(td, (struct ioctl_args *)args));
1782
1783         case LINUX_SOUND_MIXER_WRITE_RECSRC:
1784                 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
1785                 return (ioctl(td, (struct ioctl_args *)args));
1786
1787         case LINUX_SNDCTL_DSP_RESET:
1788                 args->cmd = SNDCTL_DSP_RESET;
1789                 return (ioctl(td, (struct ioctl_args *)args));
1790
1791         case LINUX_SNDCTL_DSP_SYNC:
1792                 args->cmd = SNDCTL_DSP_SYNC;
1793                 return (ioctl(td, (struct ioctl_args *)args));
1794
1795         case LINUX_SNDCTL_DSP_SPEED:
1796                 args->cmd = SNDCTL_DSP_SPEED;
1797                 return (ioctl(td, (struct ioctl_args *)args));
1798
1799         case LINUX_SNDCTL_DSP_STEREO:
1800                 args->cmd = SNDCTL_DSP_STEREO;
1801                 return (ioctl(td, (struct ioctl_args *)args));
1802
1803         case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
1804                 args->cmd = SNDCTL_DSP_GETBLKSIZE;
1805                 return (ioctl(td, (struct ioctl_args *)args));
1806
1807         case LINUX_SNDCTL_DSP_SETFMT:
1808                 args->cmd = SNDCTL_DSP_SETFMT;
1809                 return (ioctl(td, (struct ioctl_args *)args));
1810
1811         case LINUX_SOUND_PCM_WRITE_CHANNELS:
1812                 args->cmd = SOUND_PCM_WRITE_CHANNELS;
1813                 return (ioctl(td, (struct ioctl_args *)args));
1814
1815         case LINUX_SOUND_PCM_WRITE_FILTER:
1816                 args->cmd = SOUND_PCM_WRITE_FILTER;
1817                 return (ioctl(td, (struct ioctl_args *)args));
1818
1819         case LINUX_SNDCTL_DSP_POST:
1820                 args->cmd = SNDCTL_DSP_POST;
1821                 return (ioctl(td, (struct ioctl_args *)args));
1822
1823         case LINUX_SNDCTL_DSP_SUBDIVIDE:
1824                 args->cmd = SNDCTL_DSP_SUBDIVIDE;
1825                 return (ioctl(td, (struct ioctl_args *)args));
1826
1827         case LINUX_SNDCTL_DSP_SETFRAGMENT:
1828                 args->cmd = SNDCTL_DSP_SETFRAGMENT;
1829                 return (ioctl(td, (struct ioctl_args *)args));
1830
1831         case LINUX_SNDCTL_DSP_GETFMTS:
1832                 args->cmd = SNDCTL_DSP_GETFMTS;
1833                 return (ioctl(td, (struct ioctl_args *)args));
1834
1835         case LINUX_SNDCTL_DSP_GETOSPACE:
1836                 args->cmd = SNDCTL_DSP_GETOSPACE;
1837                 return (ioctl(td, (struct ioctl_args *)args));
1838
1839         case LINUX_SNDCTL_DSP_GETISPACE:
1840                 args->cmd = SNDCTL_DSP_GETISPACE;
1841                 return (ioctl(td, (struct ioctl_args *)args));
1842
1843         case LINUX_SNDCTL_DSP_NONBLOCK:
1844                 args->cmd = SNDCTL_DSP_NONBLOCK;
1845                 return (ioctl(td, (struct ioctl_args *)args));
1846
1847         case LINUX_SNDCTL_DSP_GETCAPS:
1848                 args->cmd = SNDCTL_DSP_GETCAPS;
1849                 return (ioctl(td, (struct ioctl_args *)args));
1850
1851         case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
1852                 args->cmd = SNDCTL_DSP_SETTRIGGER;
1853                 return (ioctl(td, (struct ioctl_args *)args));
1854
1855         case LINUX_SNDCTL_DSP_GETIPTR:
1856                 args->cmd = SNDCTL_DSP_GETIPTR;
1857                 return (ioctl(td, (struct ioctl_args *)args));
1858
1859         case LINUX_SNDCTL_DSP_GETOPTR:
1860                 args->cmd = SNDCTL_DSP_GETOPTR;
1861                 return (ioctl(td, (struct ioctl_args *)args));
1862
1863         case LINUX_SNDCTL_DSP_SETDUPLEX:
1864                 args->cmd = SNDCTL_DSP_SETDUPLEX;
1865                 return (ioctl(td, (struct ioctl_args *)args));
1866
1867         case LINUX_SNDCTL_DSP_GETODELAY:
1868                 args->cmd = SNDCTL_DSP_GETODELAY;
1869                 return (ioctl(td, (struct ioctl_args *)args));
1870
1871         case LINUX_SNDCTL_SEQ_RESET:
1872                 args->cmd = SNDCTL_SEQ_RESET;
1873                 return (ioctl(td, (struct ioctl_args *)args));
1874
1875         case LINUX_SNDCTL_SEQ_SYNC:
1876                 args->cmd = SNDCTL_SEQ_SYNC;
1877                 return (ioctl(td, (struct ioctl_args *)args));
1878
1879         case LINUX_SNDCTL_SYNTH_INFO:
1880                 args->cmd = SNDCTL_SYNTH_INFO;
1881                 return (ioctl(td, (struct ioctl_args *)args));
1882
1883         case LINUX_SNDCTL_SEQ_CTRLRATE:
1884                 args->cmd = SNDCTL_SEQ_CTRLRATE;
1885                 return (ioctl(td, (struct ioctl_args *)args));
1886
1887         case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
1888                 args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
1889                 return (ioctl(td, (struct ioctl_args *)args));
1890
1891         case LINUX_SNDCTL_SEQ_GETINCOUNT:
1892                 args->cmd = SNDCTL_SEQ_GETINCOUNT;
1893                 return (ioctl(td, (struct ioctl_args *)args));
1894
1895         case LINUX_SNDCTL_SEQ_PERCMODE:
1896                 args->cmd = SNDCTL_SEQ_PERCMODE;
1897                 return (ioctl(td, (struct ioctl_args *)args));
1898
1899         case LINUX_SNDCTL_FM_LOAD_INSTR:
1900                 args->cmd = SNDCTL_FM_LOAD_INSTR;
1901                 return (ioctl(td, (struct ioctl_args *)args));
1902
1903         case LINUX_SNDCTL_SEQ_TESTMIDI:
1904                 args->cmd = SNDCTL_SEQ_TESTMIDI;
1905                 return (ioctl(td, (struct ioctl_args *)args));
1906
1907         case LINUX_SNDCTL_SEQ_RESETSAMPLES:
1908                 args->cmd = SNDCTL_SEQ_RESETSAMPLES;
1909                 return (ioctl(td, (struct ioctl_args *)args));
1910
1911         case LINUX_SNDCTL_SEQ_NRSYNTHS:
1912                 args->cmd = SNDCTL_SEQ_NRSYNTHS;
1913                 return (ioctl(td, (struct ioctl_args *)args));
1914
1915         case LINUX_SNDCTL_SEQ_NRMIDIS:
1916                 args->cmd = SNDCTL_SEQ_NRMIDIS;
1917                 return (ioctl(td, (struct ioctl_args *)args));
1918
1919         case LINUX_SNDCTL_MIDI_INFO:
1920                 args->cmd = SNDCTL_MIDI_INFO;
1921                 return (ioctl(td, (struct ioctl_args *)args));
1922
1923         case LINUX_SNDCTL_SEQ_TRESHOLD:
1924                 args->cmd = SNDCTL_SEQ_TRESHOLD;
1925                 return (ioctl(td, (struct ioctl_args *)args));
1926
1927         case LINUX_SNDCTL_SYNTH_MEMAVL:
1928                 args->cmd = SNDCTL_SYNTH_MEMAVL;
1929                 return (ioctl(td, (struct ioctl_args *)args));
1930
1931         }
1932
1933         return (ENOIOCTL);
1934 }
1935
1936 /*
1937  * Console related ioctls
1938  */
1939
1940 #define ISSIGVALID(sig)         ((sig) > 0 && (sig) < NSIG)
1941
1942 static int
1943 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
1944 {
1945         struct file *fp;
1946         int error;
1947
1948         if ((error = fget(td, args->fd, &fp)) != 0)
1949                 return (error);
1950         switch (args->cmd & 0xffff) {
1951
1952         case LINUX_KIOCSOUND:
1953                 args->cmd = KIOCSOUND;
1954                 error = (ioctl(td, (struct ioctl_args *)args));
1955                 break;
1956
1957         case LINUX_KDMKTONE:
1958                 args->cmd = KDMKTONE;
1959                 error = (ioctl(td, (struct ioctl_args *)args));
1960                 break;
1961
1962         case LINUX_KDGETLED:
1963                 args->cmd = KDGETLED;
1964                 error = (ioctl(td, (struct ioctl_args *)args));
1965                 break;
1966
1967         case LINUX_KDSETLED:
1968                 args->cmd = KDSETLED;
1969                 error = (ioctl(td, (struct ioctl_args *)args));
1970                 break;
1971
1972         case LINUX_KDSETMODE:
1973                 args->cmd = KDSETMODE;
1974                 error = (ioctl(td, (struct ioctl_args *)args));
1975                 break;
1976
1977         case LINUX_KDGETMODE:
1978                 args->cmd = KDGETMODE;
1979                 error = (ioctl(td, (struct ioctl_args *)args));
1980                 break;
1981
1982         case LINUX_KDGKBMODE:
1983                 args->cmd = KDGKBMODE;
1984                 error = (ioctl(td, (struct ioctl_args *)args));
1985                 break;
1986
1987         case LINUX_KDSKBMODE: {
1988                 int kbdmode;
1989                 switch (args->arg) {
1990                 case LINUX_KBD_RAW:
1991                         kbdmode = K_RAW;
1992                         break;
1993                 case LINUX_KBD_XLATE:
1994                         kbdmode = K_XLATE;
1995                         break;
1996                 case LINUX_KBD_MEDIUMRAW:
1997                         kbdmode = K_RAW;
1998                         break;
1999                 default:
2000                         fdrop(fp, td);
2001                         return (EINVAL);
2002                 }
2003                 error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
2004                     td->td_ucred, td));
2005                 break;
2006         }
2007
2008         case LINUX_VT_OPENQRY:
2009                 args->cmd = VT_OPENQRY;
2010                 error = (ioctl(td, (struct ioctl_args *)args));
2011                 break;
2012
2013         case LINUX_VT_GETMODE:
2014                 args->cmd = VT_GETMODE;
2015                 error = (ioctl(td, (struct ioctl_args *)args));
2016                 break;
2017
2018         case LINUX_VT_SETMODE: {
2019                 struct vt_mode mode;
2020                 if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
2021                         break;
2022                 if (!ISSIGVALID(mode.frsig) && ISSIGVALID(mode.acqsig))
2023                         mode.frsig = mode.acqsig;
2024                 if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
2025                         break;
2026                 args->cmd = VT_SETMODE;
2027                 error = (ioctl(td, (struct ioctl_args *)args));
2028                 break;
2029         }
2030
2031         case LINUX_VT_GETSTATE:
2032                 args->cmd = VT_GETACTIVE;
2033                 error = (ioctl(td, (struct ioctl_args *)args));
2034                 break;
2035
2036         case LINUX_VT_RELDISP:
2037                 args->cmd = VT_RELDISP;
2038                 error = (ioctl(td, (struct ioctl_args *)args));
2039                 break;
2040
2041         case LINUX_VT_ACTIVATE:
2042                 args->cmd = VT_ACTIVATE;
2043                 error = (ioctl(td, (struct ioctl_args *)args));
2044                 break;
2045
2046         case LINUX_VT_WAITACTIVE:
2047                 args->cmd = VT_WAITACTIVE;
2048                 error = (ioctl(td, (struct ioctl_args *)args));
2049                 break;
2050
2051         default:
2052                 error = ENOIOCTL;
2053                 break;
2054         }
2055
2056         fdrop(fp, td);
2057         return (error);
2058 }
2059
2060 /*
2061  * Criteria for interface name translation
2062  */
2063 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
2064
2065 /*
2066  * Interface function used by linprocfs (at the time of writing). It's not
2067  * used by the Linuxulator itself.
2068  */
2069 int
2070 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
2071 {
2072         struct ifnet *ifscan;
2073         int ethno;
2074
2075         IFNET_RLOCK_ASSERT();
2076
2077         /* Short-circuit non ethernet interfaces */
2078         if (!IFP_IS_ETH(ifp))
2079                 return (strlcpy(buffer, ifp->if_xname, buflen));
2080
2081         /* Determine the (relative) unit number for ethernet interfaces */
2082         ethno = 0;
2083         TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
2084                 if (ifscan == ifp)
2085                         return (snprintf(buffer, buflen, "eth%d", ethno));
2086                 if (IFP_IS_ETH(ifscan))
2087                         ethno++;
2088         }
2089
2090         return (0);
2091 }
2092
2093 /*
2094  * Translate a Linux interface name to a FreeBSD interface name,
2095  * and return the associated ifnet structure
2096  * bsdname and lxname need to be least IFNAMSIZ bytes long, but
2097  * can point to the same buffer.
2098  */
2099
2100 static struct ifnet *
2101 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
2102 {
2103         struct ifnet *ifp;
2104         int len, unit;
2105         char *ep;
2106         int is_eth, index;
2107
2108         for (len = 0; len < LINUX_IFNAMSIZ; ++len)
2109                 if (!isalpha(lxname[len]))
2110                         break;
2111         if (len == 0 || len == LINUX_IFNAMSIZ)
2112                 return (NULL);
2113         unit = (int)strtoul(lxname + len, &ep, 10);
2114         if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ)
2115                 return (NULL);
2116         index = 0;
2117         is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
2118         CURVNET_SET(TD_TO_VNET(td));
2119         IFNET_RLOCK();
2120         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
2121                 /*
2122                  * Allow Linux programs to use FreeBSD names. Don't presume
2123                  * we never have an interface named "eth", so don't make
2124                  * the test optional based on is_eth.
2125                  */
2126                 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0)
2127                         break;
2128                 if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
2129                         break;
2130         }
2131         IFNET_RUNLOCK();
2132         CURVNET_RESTORE();
2133         if (ifp != NULL)
2134                 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
2135         return (ifp);
2136 }
2137
2138 /*
2139  * Implement the SIOCGIFCONF ioctl
2140  */
2141
2142 static int
2143 linux_ifconf(struct thread *td, struct ifconf *uifc)
2144 {
2145 #ifdef COMPAT_LINUX32
2146         struct l_ifconf ifc;
2147 #else
2148         struct ifconf ifc;
2149 #endif
2150         struct l_ifreq ifr;
2151         struct ifnet *ifp;
2152         struct ifaddr *ifa;
2153         struct sbuf *sb;
2154         int error, ethno, full = 0, valid_len, max_len;
2155
2156         error = copyin(uifc, &ifc, sizeof(ifc));
2157         if (error != 0)
2158                 return (error);
2159
2160         max_len = MAXPHYS - 1;
2161
2162         CURVNET_SET(TD_TO_VNET(td));
2163         /* handle the 'request buffer size' case */
2164         if (ifc.ifc_buf == PTROUT(NULL)) {
2165                 ifc.ifc_len = 0;
2166                 IFNET_RLOCK();
2167                 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
2168                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2169                                 struct sockaddr *sa = ifa->ifa_addr;
2170                                 if (sa->sa_family == AF_INET)
2171                                         ifc.ifc_len += sizeof(ifr);
2172                         }
2173                 }
2174                 IFNET_RUNLOCK();
2175                 error = copyout(&ifc, uifc, sizeof(ifc));
2176                 CURVNET_RESTORE();
2177                 return (error);
2178         }
2179
2180         if (ifc.ifc_len <= 0) {
2181                 CURVNET_RESTORE();
2182                 return (EINVAL);
2183         }
2184
2185 again:
2186         /* Keep track of eth interfaces */
2187         ethno = 0;
2188         if (ifc.ifc_len <= max_len) {
2189                 max_len = ifc.ifc_len;
2190                 full = 1;
2191         }
2192         sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN);
2193         max_len = 0;
2194         valid_len = 0;
2195
2196         /* Return all AF_INET addresses of all interfaces */
2197         IFNET_RLOCK();
2198         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
2199                 int addrs = 0;
2200
2201                 bzero(&ifr, sizeof(ifr));
2202                 if (IFP_IS_ETH(ifp))
2203                         snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
2204                             ethno++);
2205                 else
2206                         strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
2207
2208                 /* Walk the address list */
2209                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2210                         struct sockaddr *sa = ifa->ifa_addr;
2211
2212                         if (sa->sa_family == AF_INET) {
2213                                 ifr.ifr_addr.sa_family = LINUX_AF_INET;
2214                                 memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
2215                                     sizeof(ifr.ifr_addr.sa_data));
2216                                 sbuf_bcat(sb, &ifr, sizeof(ifr));
2217                                 max_len += sizeof(ifr);
2218                                 addrs++;
2219                         }
2220
2221                         if (!sbuf_overflowed(sb))
2222                                 valid_len = sbuf_len(sb);
2223                 }
2224                 if (addrs == 0) {
2225                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
2226                         sbuf_bcat(sb, &ifr, sizeof(ifr));
2227                         max_len += sizeof(ifr);
2228
2229                         if (!sbuf_overflowed(sb))
2230                                 valid_len = sbuf_len(sb);
2231                 }
2232         }
2233         IFNET_RUNLOCK();
2234
2235         if (valid_len != max_len && !full) {
2236                 sbuf_delete(sb);
2237                 goto again;
2238         }
2239
2240         ifc.ifc_len = valid_len; 
2241         sbuf_finish(sb);
2242         memcpy(PTRIN(ifc.ifc_buf), sbuf_data(sb), ifc.ifc_len);
2243         error = copyout(&ifc, uifc, sizeof(ifc));
2244         sbuf_delete(sb);
2245         CURVNET_RESTORE();
2246
2247         return (error);
2248 }
2249
2250 static int
2251 linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr)
2252 {
2253         l_short flags;
2254
2255         flags = (ifp->if_flags | ifp->if_drv_flags) & 0xffff;
2256         /* these flags have no Linux equivalent */
2257         flags &= ~(IFF_SMART|IFF_DRV_OACTIVE|IFF_SIMPLEX|
2258             IFF_LINK0|IFF_LINK1|IFF_LINK2);
2259         /* Linux' multicast flag is in a different bit */
2260         if (flags & IFF_MULTICAST) {
2261                 flags &= ~IFF_MULTICAST;
2262                 flags |= 0x1000;
2263         }
2264
2265         return (copyout(&flags, &ifr->ifr_flags, sizeof(flags)));
2266 }
2267
2268 #define ARPHRD_ETHER    1
2269 #define ARPHRD_LOOPBACK 772
2270
2271 static int
2272 linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr)
2273 {
2274         struct ifaddr *ifa;
2275         struct sockaddr_dl *sdl;
2276         struct l_sockaddr lsa;
2277
2278         if (ifp->if_type == IFT_LOOP) {
2279                 bzero(&lsa, sizeof(lsa));
2280                 lsa.sa_family = ARPHRD_LOOPBACK;
2281                 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
2282         }
2283
2284         if (ifp->if_type != IFT_ETHER)
2285                 return (ENOENT);
2286
2287         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2288                 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
2289                 if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
2290                     (sdl->sdl_type == IFT_ETHER)) {
2291                         bzero(&lsa, sizeof(lsa));
2292                         lsa.sa_family = ARPHRD_ETHER;
2293                         bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN);
2294                         return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
2295                 }
2296         }
2297
2298         return (ENOENT);
2299 }
2300
2301
2302  /*
2303 * If we fault in bsd_to_linux_ifreq() then we will fault when we call
2304 * the native ioctl().  Thus, we don't really need to check the return
2305 * value of this function.
2306 */
2307 static int
2308 bsd_to_linux_ifreq(struct ifreq *arg)
2309 {
2310         struct ifreq ifr;
2311         size_t ifr_len = sizeof(struct ifreq);
2312         int error;
2313         
2314         if ((error = copyin(arg, &ifr, ifr_len)))
2315                 return (error);
2316         
2317         *(u_short *)&ifr.ifr_addr = ifr.ifr_addr.sa_family;
2318         
2319         error = copyout(&ifr, arg, ifr_len);
2320
2321         return (error);
2322 }
2323
2324 /*
2325  * Socket related ioctls
2326  */
2327
2328 static int
2329 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
2330 {
2331         char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
2332         struct ifnet *ifp;
2333         struct file *fp;
2334         int error, type;
2335
2336         ifp = NULL;
2337         error = 0;
2338
2339         if ((error = fget(td, args->fd, &fp)) != 0)
2340                 return (error);
2341         type = fp->f_type;
2342         fdrop(fp, td);
2343         if (type != DTYPE_SOCKET) {
2344                 /* not a socket - probably a tap / vmnet device */
2345                 switch (args->cmd) {
2346                 case LINUX_SIOCGIFADDR:
2347                 case LINUX_SIOCSIFADDR:
2348                 case LINUX_SIOCGIFFLAGS:
2349                         return (linux_ioctl_special(td, args));
2350                 default:
2351                         return (ENOIOCTL);
2352                 }
2353         }
2354
2355         switch (args->cmd & 0xffff) {
2356
2357         case LINUX_FIOGETOWN:
2358         case LINUX_FIOSETOWN:
2359         case LINUX_SIOCADDMULTI:
2360         case LINUX_SIOCATMARK:
2361         case LINUX_SIOCDELMULTI:
2362         case LINUX_SIOCGIFCONF:
2363         case LINUX_SIOCGPGRP:
2364         case LINUX_SIOCSPGRP:
2365         case LINUX_SIOCGIFCOUNT:
2366                 /* these ioctls don't take an interface name */
2367 #ifdef DEBUG
2368                 printf("%s(): ioctl %d\n", __func__,
2369                     args->cmd & 0xffff);
2370 #endif
2371                 break;
2372
2373         case LINUX_SIOCGIFFLAGS:
2374         case LINUX_SIOCGIFADDR:
2375         case LINUX_SIOCSIFADDR:
2376         case LINUX_SIOCGIFDSTADDR:
2377         case LINUX_SIOCGIFBRDADDR:
2378         case LINUX_SIOCGIFNETMASK:
2379         case LINUX_SIOCSIFNETMASK:
2380         case LINUX_SIOCGIFMTU:
2381         case LINUX_SIOCSIFMTU:
2382         case LINUX_SIOCSIFNAME:
2383         case LINUX_SIOCGIFHWADDR:
2384         case LINUX_SIOCSIFHWADDR:
2385         case LINUX_SIOCDEVPRIVATE:
2386         case LINUX_SIOCDEVPRIVATE+1:
2387         case LINUX_SIOCGIFINDEX:
2388                 /* copy in the interface name and translate it. */
2389                 error = copyin((void *)args->arg, lifname, LINUX_IFNAMSIZ);
2390                 if (error != 0)
2391                         return (error);
2392 #ifdef DEBUG
2393                 printf("%s(): ioctl %d on %.*s\n", __func__,
2394                     args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname);
2395 #endif
2396                 ifp = ifname_linux_to_bsd(td, lifname, ifname);
2397                 if (ifp == NULL)
2398                         return (EINVAL);
2399                 /*
2400                  * We need to copy it back out in case we pass the
2401                  * request on to our native ioctl(), which will expect
2402                  * the ifreq to be in user space and have the correct
2403                  * interface name.
2404                  */
2405                 error = copyout(ifname, (void *)args->arg, IFNAMSIZ);
2406                 if (error != 0)
2407                         return (error);
2408 #ifdef DEBUG
2409                 printf("%s(): %s translated to %s\n", __func__,
2410                     lifname, ifname);
2411 #endif
2412                 break;
2413
2414         default:
2415                 return (ENOIOCTL);
2416         }
2417
2418         switch (args->cmd & 0xffff) {
2419
2420         case LINUX_FIOSETOWN:
2421                 args->cmd = FIOSETOWN;
2422                 error = ioctl(td, (struct ioctl_args *)args);
2423                 break;
2424
2425         case LINUX_SIOCSPGRP:
2426                 args->cmd = SIOCSPGRP;
2427                 error = ioctl(td, (struct ioctl_args *)args);
2428                 break;
2429
2430         case LINUX_FIOGETOWN:
2431                 args->cmd = FIOGETOWN;
2432                 error = ioctl(td, (struct ioctl_args *)args);
2433                 break;
2434
2435         case LINUX_SIOCGPGRP:
2436                 args->cmd = SIOCGPGRP;
2437                 error = ioctl(td, (struct ioctl_args *)args);
2438                 break;
2439
2440         case LINUX_SIOCATMARK:
2441                 args->cmd = SIOCATMARK;
2442                 error = ioctl(td, (struct ioctl_args *)args);
2443                 break;
2444
2445         /* LINUX_SIOCGSTAMP */
2446
2447         case LINUX_SIOCGIFCONF:
2448                 error = linux_ifconf(td, (struct ifconf *)args->arg);
2449                 break;
2450
2451         case LINUX_SIOCGIFFLAGS:
2452                 args->cmd = SIOCGIFFLAGS;
2453                 error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg);
2454                 break;
2455
2456         case LINUX_SIOCGIFADDR:
2457                 args->cmd = SIOCGIFADDR;
2458                 error = ioctl(td, (struct ioctl_args *)args);
2459                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
2460                 break;
2461
2462         case LINUX_SIOCSIFADDR:
2463                 /* XXX probably doesn't work, included for completeness */
2464                 args->cmd = SIOCSIFADDR;
2465                 error = ioctl(td, (struct ioctl_args *)args);
2466                 break;
2467
2468         case LINUX_SIOCGIFDSTADDR:
2469                 args->cmd = SIOCGIFDSTADDR;
2470                 error = ioctl(td, (struct ioctl_args *)args);
2471                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
2472                 break;
2473
2474         case LINUX_SIOCGIFBRDADDR:
2475                 args->cmd = SIOCGIFBRDADDR;
2476                 error = ioctl(td, (struct ioctl_args *)args);
2477                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
2478                 break;
2479
2480         case LINUX_SIOCGIFNETMASK:
2481                 args->cmd = SIOCGIFNETMASK;
2482                 error = ioctl(td, (struct ioctl_args *)args);
2483                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
2484                 break;
2485
2486         case LINUX_SIOCSIFNETMASK:
2487                 error = ENOIOCTL;
2488                 break;
2489
2490         case LINUX_SIOCGIFMTU:
2491                 args->cmd = SIOCGIFMTU;
2492                 error = ioctl(td, (struct ioctl_args *)args);
2493                 break;
2494
2495         case LINUX_SIOCSIFMTU:
2496                 args->cmd = SIOCSIFMTU;
2497                 error = ioctl(td, (struct ioctl_args *)args);
2498                 break;
2499
2500         case LINUX_SIOCSIFNAME:
2501                 error = ENOIOCTL;
2502                 break;
2503
2504         case LINUX_SIOCGIFHWADDR:
2505                 error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg);
2506                 break;
2507
2508         case LINUX_SIOCSIFHWADDR:
2509                 error = ENOIOCTL;
2510                 break;
2511
2512         case LINUX_SIOCADDMULTI:
2513                 args->cmd = SIOCADDMULTI;
2514                 error = ioctl(td, (struct ioctl_args *)args);
2515                 break;
2516
2517         case LINUX_SIOCDELMULTI:
2518                 args->cmd = SIOCDELMULTI;
2519                 error = ioctl(td, (struct ioctl_args *)args);
2520                 break;
2521
2522         case LINUX_SIOCGIFINDEX:
2523                 args->cmd = SIOCGIFINDEX;
2524                 error = ioctl(td, (struct ioctl_args *)args);
2525                 break;
2526
2527         case LINUX_SIOCGIFCOUNT:
2528                 error = 0;
2529                 break;
2530
2531         /*
2532          * XXX This is slightly bogus, but these ioctls are currently
2533          * XXX only used by the aironet (if_an) network driver.
2534          */
2535         case LINUX_SIOCDEVPRIVATE:
2536                 args->cmd = SIOCGPRIVATE_0;
2537                 error = ioctl(td, (struct ioctl_args *)args);
2538                 break;
2539
2540         case LINUX_SIOCDEVPRIVATE+1:
2541                 args->cmd = SIOCGPRIVATE_1;
2542                 error = ioctl(td, (struct ioctl_args *)args);
2543                 break;
2544         }
2545
2546         if (ifp != NULL)
2547                 /* restore the original interface name */
2548                 copyout(lifname, (void *)args->arg, LINUX_IFNAMSIZ);
2549
2550 #ifdef DEBUG
2551         printf("%s(): returning %d\n", __func__, error);
2552 #endif
2553         return (error);
2554 }
2555
2556 /*
2557  * Device private ioctl handler
2558  */
2559 static int
2560 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
2561 {
2562         struct file *fp;
2563         int error, type;
2564
2565         if ((error = fget(td, args->fd, &fp)) != 0)
2566                 return (error);
2567         type = fp->f_type;
2568         fdrop(fp, td);
2569         if (type == DTYPE_SOCKET)
2570                 return (linux_ioctl_socket(td, args));
2571         return (ENOIOCTL);
2572 }
2573
2574 /*
2575  * DRM ioctl handler (sys/dev/drm)
2576  */
2577 static int
2578 linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
2579 {
2580         args->cmd = SETDIR(args->cmd);
2581         return ioctl(td, (struct ioctl_args *)args);
2582 }
2583
2584 static int
2585 linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
2586 {
2587         struct file *fp;
2588         u_long cmd;
2589         int error;
2590
2591         if ((error = fget(td, args->fd, &fp)) != 0) {
2592                 printf("sg_linux_ioctl: fget returned %d\n", error);
2593                 return (error);
2594         }
2595         cmd = args->cmd;
2596
2597         error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td));
2598         fdrop(fp, td);
2599         return (error);
2600 }
2601
2602 /*
2603  * Video4Linux (V4L) ioctl handler
2604  */
2605 static int
2606 linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt)
2607 {
2608         vt->tuner = lvt->tuner;
2609         strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2610         vt->rangelow = lvt->rangelow;   /* possible long size conversion */
2611         vt->rangehigh = lvt->rangehigh; /* possible long size conversion */
2612         vt->flags = lvt->flags;
2613         vt->mode = lvt->mode;
2614         vt->signal = lvt->signal;
2615         return (0);
2616 }
2617
2618 static int
2619 bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
2620 {
2621         lvt->tuner = vt->tuner;
2622         strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2623         lvt->rangelow = vt->rangelow;   /* possible long size conversion */
2624         lvt->rangehigh = vt->rangehigh; /* possible long size conversion */
2625         lvt->flags = vt->flags;
2626         lvt->mode = vt->mode;
2627         lvt->signal = vt->signal;
2628         return (0);
2629 }
2630
2631 static int
2632 linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
2633 {
2634         vc->x = lvc->x;
2635         vc->y = lvc->y;
2636         vc->width = lvc->width;