1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 1994-1995 Søren Schmidt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/capsicum.h>
31 #include <sys/cdio.h>
32 #include <sys/consio.h>
33 #include <sys/disk.h>
34 #include <sys/dvdio.h>
35 #include <sys/fcntl.h>
36 #include <sys/filio.h>
37 #include <sys/jail.h>
38 #include <sys/kbio.h>
39 #include <sys/kcov.h>
40 #include <sys/kernel.h>
41 #include <sys/linker_set.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mman.h>
45 #include <sys/proc.h>
46 #include <sys/vnode.h>
47 #include <sys/sbuf.h>
48 #include <sys/sockio.h>
49 #include <sys/soundcard.h>
50 #include <sys/syscallsubr.h>
51 #include <sys/sysctl.h>
52 #include <sys/sysproto.h>
53 #include <sys/sx.h>
54 #include <sys/tty.h>
55
56 #include <net/if.h>
57 #include <net/if_var.h>
58 #include <net/if_dl.h>
59 #include <net/if_types.h>
60
61 #include <dev/evdev/input.h>
62 #include <dev/hid/hidraw.h>
63 #include <dev/iicbus/iic.h>
64 #include <dev/usb/usb_ioctl.h>
65
66 #ifdef COMPAT_LINUX32
67 #include <machine/../linux32/linux.h>
68 #include <machine/../linux32/linux32_proto.h>
69 #else
70 #include <machine/../linux/linux.h>
71 #include <machine/../linux/linux_proto.h>
72 #endif
73
74 #include <compat/linux/linux_common.h>
75 #include <compat/linux/linux_ioctl.h>
76 #include <compat/linux/linux_mib.h>
77 #include <compat/linux/linux_socket.h>
78 #include <compat/linux/linux_time.h>
79 #include <compat/linux/linux_util.h>
80
81 #include <contrib/v4l/videodev.h>
82 #include <compat/linux/linux_videodev_compat.h>
83
84 #include <contrib/v4l/videodev2.h>
85 #include <compat/linux/linux_videodev2_compat.h>
86
87 #include <cam/scsi/scsi_sg.h>
88
89 #include <dev/nvme/nvme_linux.h>
90
91 #define DEFINE_LINUX_IOCTL_SET(shortname, SHORTNAME) \
92 static linux_ioctl_function_t linux_ioctl_ ## shortname; \
93 static struct linux_ioctl_handler shortname ## _handler = { \
94 .func = linux_ioctl_ ## shortname, \
95 .low = LINUX_IOCTL_ ## SHORTNAME ## _MIN, \
96 .high = LINUX_IOCTL_ ## SHORTNAME ## _MAX, \
97 }; \
98 DATA_SET(linux_ioctl_handler_set, shortname ## _handler)
99
100 DEFINE_LINUX_IOCTL_SET(cdrom, CDROM);
101 DEFINE_LINUX_IOCTL_SET(vfat, VFAT);
102 DEFINE_LINUX_IOCTL_SET(console, CONSOLE);
103 DEFINE_LINUX_IOCTL_SET(hdio, HDIO);
104 DEFINE_LINUX_IOCTL_SET(disk, DISK);
105 DEFINE_LINUX_IOCTL_SET(i2c, I2C);
106 DEFINE_LINUX_IOCTL_SET(socket, SOCKET);
107 DEFINE_LINUX_IOCTL_SET(sound, SOUND);
108 DEFINE_LINUX_IOCTL_SET(termio, TERMIO);
109 DEFINE_LINUX_IOCTL_SET(private, PRIVATE);
110 DEFINE_LINUX_IOCTL_SET(drm, DRM);
111 DEFINE_LINUX_IOCTL_SET(sg, SG);
112 DEFINE_LINUX_IOCTL_SET(v4l, VIDEO);
113 DEFINE_LINUX_IOCTL_SET(v4l2, VIDEO2);
114 DEFINE_LINUX_IOCTL_SET(fbsd_usb, FBSD_LUSB);
115 DEFINE_LINUX_IOCTL_SET(evdev, EVDEV);
116 DEFINE_LINUX_IOCTL_SET(kcov, KCOV);
117 #ifndef COMPAT_LINUX32
118 DEFINE_LINUX_IOCTL_SET(nvme, NVME);
119 #endif
120 DEFINE_LINUX_IOCTL_SET(hidraw, HIDRAW);
121
122 #undef DEFINE_LINUX_IOCTL_SET
123
124 static int linux_ioctl_special(struct thread *, struct linux_ioctl_args *);
125
126 /*
127 * Keep sorted by low.
128 */
129 static struct linux_ioctl_handler linux_ioctls[] = {
130 { .func = linux_ioctl_termio, .low = LINUX_IOCTL_TERMIO_MIN,
131 .high = LINUX_IOCTL_TERMIO_MAX },
132 };
133
134 #ifdef __i386__
135 static TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers =
136 TAILQ_HEAD_INITIALIZER(linux_ioctl_handlers);
137 static struct sx linux_ioctl_sx;
138 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "Linux ioctl handlers");
139 #else
140 extern TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers;
141 extern struct sx linux_ioctl_sx;
142 #endif
143 #ifdef COMPAT_LINUX32
144 static TAILQ_HEAD(, linux_ioctl_handler_element) linux32_ioctl_handlers =
145 TAILQ_HEAD_INITIALIZER(linux32_ioctl_handlers);
146 #endif
147
148 /*
149 * hdio related ioctls for VMWare support
150 */
151
152 struct linux_hd_geometry {
153 uint8_t heads;
154 uint8_t sectors;
155 uint16_t cylinders;
156 uint32_t start;
157 };
158
159 struct linux_hd_big_geometry {
160 uint8_t heads;
161 uint8_t sectors;
162 uint32_t cylinders;
163 uint32_t start;
164 };
165
166 struct linux_i2c_msg {
167 uint16_t addr;
168 uint16_t flags;
169 uint16_t len;
170 l_uintptr_t buf;
171 };
172
173 struct linux_i2c_rdwr_data {
174 l_uintptr_t msgs;
175 l_uint nmsgs;
176 };
177
178 static int
linux_ioctl_hdio(struct thread * td,struct linux_ioctl_args * args)179 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
180 {
181 struct file *fp;
182 int error;
183 u_int sectorsize, fwcylinders, fwheads, fwsectors;
184 off_t mediasize, bytespercyl;
185
186 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
187 if (error != 0)
188 return (error);
189 switch (args->cmd & 0xffff) {
190 case LINUX_HDIO_GET_GEO:
191 case LINUX_HDIO_GET_GEO_BIG:
192 error = fo_ioctl(fp, DIOCGMEDIASIZE,
193 (caddr_t)&mediasize, td->td_ucred, td);
194 if (!error)
195 error = fo_ioctl(fp, DIOCGSECTORSIZE,
196 (caddr_t)§orsize, td->td_ucred, td);
197 if (!error)
198 error = fo_ioctl(fp, DIOCGFWHEADS,
199 (caddr_t)&fwheads, td->td_ucred, td);
200 if (!error)
201 error = fo_ioctl(fp, DIOCGFWSECTORS,
202 (caddr_t)&fwsectors, td->td_ucred, td);
203 /*
204 * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
205 * so pretend that GEOM always says 0. This is NOT VALID
206 * for slices or partitions, only the per-disk raw devices.
207 */
208
209 fdrop(fp, td);
210 if (error)
211 return (error);
212 /*
213 * 1. Calculate the number of bytes in a cylinder,
214 * given the firmware's notion of heads and sectors
215 * per cylinder.
216 * 2. Calculate the number of cylinders, given the total
217 * size of the media.
218 * All internal calculations should have 64-bit precision.
219 */
220 bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
221 fwcylinders = mediasize / bytespercyl;
222
223 if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
224 struct linux_hd_geometry hdg;
225
226 hdg.cylinders = fwcylinders;
227 hdg.heads = fwheads;
228 hdg.sectors = fwsectors;
229 hdg.start = 0;
230 error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
231 } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
232 struct linux_hd_big_geometry hdbg;
233
234 memset(&hdbg, 0, sizeof(hdbg));
235 hdbg.cylinders = fwcylinders;
236 hdbg.heads = fwheads;
237 hdbg.sectors = fwsectors;
238 hdbg.start = 0;
239 error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
240 }
241 return (error);
242 break;
243 default:
244 /* XXX */
245 linux_msg(td,
246 "%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
247 __func__, args->fd, args->cmd,
248 (int)(args->cmd & 0xff00) >> 8,
249 (int)(args->cmd & 0xff));
250 break;
251 }
252 fdrop(fp, td);
253 return (ENOIOCTL);
254 }
255
256 static int
linux_ioctl_disk(struct thread * td,struct linux_ioctl_args * args)257 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
258 {
259 struct file *fp;
260 int error;
261 u_int sectorsize, psectorsize;
262 uint64_t blksize64;
263 off_t mediasize, stripesize;
264
265 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
266 if (error != 0)
267 return (error);
268 switch (args->cmd & 0xffff) {
269 case LINUX_BLKGETSIZE:
270 error = fo_ioctl(fp, DIOCGSECTORSIZE,
271 (caddr_t)§orsize, td->td_ucred, td);
272 if (!error)
273 error = fo_ioctl(fp, DIOCGMEDIASIZE,
274 (caddr_t)&mediasize, td->td_ucred, td);
275 fdrop(fp, td);
276 if (error)
277 return (error);
278 sectorsize = mediasize / sectorsize;
279 /*
280 * XXX: How do we know we return the right size of integer ?
281 */
282 return (copyout(§orsize, (void *)args->arg,
283 sizeof(sectorsize)));
284 break;
285 case LINUX_BLKGETSIZE64:
286 error = fo_ioctl(fp, DIOCGMEDIASIZE,
287 (caddr_t)&mediasize, td->td_ucred, td);
288 fdrop(fp, td);
289 if (error)
290 return (error);
291 blksize64 = mediasize;
292 return (copyout(&blksize64, (void *)args->arg,
293 sizeof(blksize64)));
294 case LINUX_BLKSSZGET:
295 error = fo_ioctl(fp, DIOCGSECTORSIZE,
296 (caddr_t)§orsize, td->td_ucred, td);
297 fdrop(fp, td);
298 if (error)
299 return (error);
300 return (copyout(§orsize, (void *)args->arg,
301 sizeof(sectorsize)));
302 break;
303 case LINUX_BLKPBSZGET:
304 error = fo_ioctl(fp, DIOCGSTRIPESIZE,
305 (caddr_t)&stripesize, td->td_ucred, td);
306 if (error != 0) {
307 fdrop(fp, td);
308 return (error);
309 }
310 if (stripesize > 0 && stripesize <= 4096) {
311 psectorsize = stripesize;
312 } else {
313 error = fo_ioctl(fp, DIOCGSECTORSIZE,
314 (caddr_t)§orsize, td->td_ucred, td);
315 if (error != 0) {
316 fdrop(fp, td);
317 return (error);
318 }
319 psectorsize = sectorsize;
320 }
321 fdrop(fp, td);
322 return (copyout(&psectorsize, (void *)args->arg,
323 sizeof(psectorsize)));
324 }
325 fdrop(fp, td);
326 return (ENOIOCTL);
327 }
328
329 /*
330 * termio related ioctls
331 */
332
333 struct linux_termio {
334 unsigned short c_iflag;
335 unsigned short c_oflag;
336 unsigned short c_cflag;
337 unsigned short c_lflag;
338 unsigned char c_line;
339 unsigned char c_cc[LINUX_NCC];
340 };
341
342 struct linux_termios {
343 unsigned int c_iflag;
344 unsigned int c_oflag;
345 unsigned int c_cflag;
346 unsigned int c_lflag;
347 unsigned char c_line;
348 unsigned char c_cc[LINUX_NCCS];
349 };
350
351 struct linux_termios2 {
352 unsigned int c_iflag;
353 unsigned int c_oflag;
354 unsigned int c_cflag;
355 unsigned int c_lflag;
356 unsigned char c_line;
357 unsigned char c_cc[LINUX_NCCS];
358 unsigned int c_ispeed;
359 unsigned int c_ospeed;
360 };
361
362 struct linux_winsize {
363 unsigned short ws_row, ws_col;
364 unsigned short ws_xpixel, ws_ypixel;
365 };
366
367 struct speedtab {
368 int sp_speed; /* Speed. */
369 int sp_code; /* Code. */
370 };
371
372 static struct speedtab sptab[] = {
373 { B0, LINUX_B0 }, { B50, LINUX_B50 },
374 { B75, LINUX_B75 }, { B110, LINUX_B110 },
375 { B134, LINUX_B134 }, { B150, LINUX_B150 },
376 { B200, LINUX_B200 }, { B300, LINUX_B300 },
377 { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
378 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
379 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
380 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
381 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
382 {-1, -1 }
383 };
384
385 struct linux_serial_struct {
386 int type;
387 int line;
388 int port;
389 int irq;
390 int flags;
391 int xmit_fifo_size;
392 int custom_divisor;
393 int baud_base;
394 unsigned short close_delay;
395 char reserved_char[2];
396 int hub6;
397 unsigned short closing_wait;
398 unsigned short closing_wait2;
399 int reserved[4];
400 };
401
402 static int
linux_to_bsd_speed(int code,struct speedtab * table)403 linux_to_bsd_speed(int code, struct speedtab *table)
404 {
405 for ( ; table->sp_code != -1; table++)
406 if (table->sp_code == code)
407 return (table->sp_speed);
408 return (-1);
409 }
410
411 static int
bsd_to_linux_speed(int speed,struct speedtab * table)412 bsd_to_linux_speed(int speed, struct speedtab *table)
413 {
414 for ( ; table->sp_speed != -1; table++)
415 if (table->sp_speed == speed)
416 return (table->sp_code);
417 return (LINUX_BOTHER);
418 }
419
420 static void
bsd_to_linux_termios(struct termios * bios,struct linux_termios * lios)421 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
422 {
423 int i;
424
425 lios->c_iflag = 0;
426 if (bios->c_iflag & IGNBRK)
427 lios->c_iflag |= LINUX_IGNBRK;
428 if (bios->c_iflag & BRKINT)
429 lios->c_iflag |= LINUX_BRKINT;
430 if (bios->c_iflag & IGNPAR)
431 lios->c_iflag |= LINUX_IGNPAR;
432 if (bios->c_iflag & PARMRK)
433 lios->c_iflag |= LINUX_PARMRK;
434 if (bios->c_iflag & INPCK)
435 lios->c_iflag |= LINUX_INPCK;
436 if (bios->c_iflag & ISTRIP)
437 lios->c_iflag |= LINUX_ISTRIP;
438 if (bios->c_iflag & INLCR)
439 lios->c_iflag |= LINUX_INLCR;
440 if (bios->c_iflag & IGNCR)
441 lios->c_iflag |= LINUX_IGNCR;
442 if (bios->c_iflag & ICRNL)
443 lios->c_iflag |= LINUX_ICRNL;
444 if (bios->c_iflag & IXON)
445 lios->c_iflag |= LINUX_IXON;
446 if (bios->c_iflag & IXANY)
447 lios->c_iflag |= LINUX_IXANY;
448 if (bios->c_iflag & IXOFF)
449 lios->c_iflag |= LINUX_IXOFF;
450 if (bios->c_iflag & IMAXBEL)
451 lios->c_iflag |= LINUX_IMAXBEL;
452 if (bios->c_iflag & IUTF8)
453 lios->c_iflag |= LINUX_IUTF8;
454
455 lios->c_oflag = 0;
456 if (bios->c_oflag & OPOST)
457 lios->c_oflag |= LINUX_OPOST;
458 if (bios->c_oflag & ONLCR)
459 lios->c_oflag |= LINUX_ONLCR;
460 if (bios->c_oflag & TAB3)
461 lios->c_oflag |= LINUX_XTABS;
462
463 lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
464 lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
465 if (bios->c_cflag & CSTOPB)
466 lios->c_cflag |= LINUX_CSTOPB;
467 if (bios->c_cflag & CREAD)
468 lios->c_cflag |= LINUX_CREAD;
469 if (bios->c_cflag & PARENB)
470 lios->c_cflag |= LINUX_PARENB;
471 if (bios->c_cflag & PARODD)
472 lios->c_cflag |= LINUX_PARODD;
473 if (bios->c_cflag & HUPCL)
474 lios->c_cflag |= LINUX_HUPCL;
475 if (bios->c_cflag & CLOCAL)
476 lios->c_cflag |= LINUX_CLOCAL;
477 if (bios->c_cflag & CRTSCTS)
478 lios->c_cflag |= LINUX_CRTSCTS;
479
480 lios->c_lflag = 0;
481 if (bios->c_lflag & ISIG)
482 lios->c_lflag |= LINUX_ISIG;
483 if (bios->c_lflag & ICANON)
484 lios->c_lflag |= LINUX_ICANON;
485 if (bios->c_lflag & ECHO)
486 lios->c_lflag |= LINUX_ECHO;
487 if (bios->c_lflag & ECHOE)
488 lios->c_lflag |= LINUX_ECHOE;
489 if (bios->c_lflag & ECHOK)
490 lios->c_lflag |= LINUX_ECHOK;
491 if (bios->c_lflag & ECHONL)
492 lios->c_lflag |= LINUX_ECHONL;
493 if (bios->c_lflag & NOFLSH)
494 lios->c_lflag |= LINUX_NOFLSH;
495 if (bios->c_lflag & TOSTOP)
496 lios->c_lflag |= LINUX_TOSTOP;
497 if (bios->c_lflag & ECHOCTL)
498 lios->c_lflag |= LINUX_ECHOCTL;
499 if (bios->c_lflag & ECHOPRT)
500 lios->c_lflag |= LINUX_ECHOPRT;
501 if (bios->c_lflag & ECHOKE)
502 lios->c_lflag |= LINUX_ECHOKE;
503 if (bios->c_lflag & FLUSHO)
504 lios->c_lflag |= LINUX_FLUSHO;
505 if (bios->c_lflag & PENDIN)
506 lios->c_lflag |= LINUX_PENDIN;
507 if (bios->c_lflag & IEXTEN)
508 lios->c_lflag |= LINUX_IEXTEN;
509
510 for (i=0; i<LINUX_NCCS; i++)
511 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
512 lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
513 lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
514 lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
515 lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
516 lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
517 lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
518 lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
519 lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
520 lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
521 lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
522 lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
523 lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
524 lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
525 lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
526 lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
527 lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
528 if (linux_preserve_vstatus)
529 lios->c_cc[LINUX_VSTATUS] = bios->c_cc[VSTATUS];
530
531 for (i=0; i<LINUX_NCCS; i++) {
532 if (i != LINUX_VMIN && i != LINUX_VTIME &&
533 lios->c_cc[i] == _POSIX_VDISABLE)
534 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
535 }
536 lios->c_line = 0;
537 }
538
539 static void
bsd_to_linux_termios2(struct termios * bios,struct linux_termios2 * lios2)540 bsd_to_linux_termios2(struct termios *bios, struct linux_termios2 *lios2)
541 {
542 bsd_to_linux_termios(bios, (struct linux_termios *)lios2);
543 lios2->c_ospeed = bios->c_ospeed;
544 lios2->c_ispeed = bios->c_ispeed;
545 }
546
547 static void
linux_to_bsd_termios(struct linux_termios * lios,struct termios * bios)548 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
549 {
550 int i;
551
552 bios->c_iflag = 0;
553 if (lios->c_iflag & LINUX_IGNBRK)
554 bios->c_iflag |= IGNBRK;
555 if (lios->c_iflag & LINUX_BRKINT)
556 bios->c_iflag |= BRKINT;
557 if (lios->c_iflag & LINUX_IGNPAR)
558 bios->c_iflag |= IGNPAR;
559 if (lios->c_iflag & LINUX_PARMRK)
560 bios->c_iflag |= PARMRK;
561 if (lios->c_iflag & LINUX_INPCK)
562 bios->c_iflag |= INPCK;
563 if (lios->c_iflag & LINUX_ISTRIP)
564 bios->c_iflag |= ISTRIP;
565 if (lios->c_iflag & LINUX_INLCR)
566 bios->c_iflag |= INLCR;
567 if (lios->c_iflag & LINUX_IGNCR)
568 bios->c_iflag |= IGNCR;
569 if (lios->c_iflag & LINUX_ICRNL)
570 bios->c_iflag |= ICRNL;
571 if (lios->c_iflag & LINUX_IXON)
572 bios->c_iflag |= IXON;
573 if (lios->c_iflag & LINUX_IXANY)
574 bios->c_iflag |= IXANY;
575 if (lios->c_iflag & LINUX_IXOFF)
576 bios->c_iflag |= IXOFF;
577 if (lios->c_iflag & LINUX_IMAXBEL)
578 bios->c_iflag |= IMAXBEL;
579 if (lios->c_iflag & LINUX_IUTF8)
580 bios->c_iflag |= IUTF8;
581
582 bios->c_oflag = 0;
583 if (lios->c_oflag & LINUX_OPOST)
584 bios->c_oflag |= OPOST;
585 if (lios->c_oflag & LINUX_ONLCR)
586 bios->c_oflag |= ONLCR;
587 if (lios->c_oflag & LINUX_XTABS)
588 bios->c_oflag |= TAB3;
589
590 bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
591 if (lios->c_cflag & LINUX_CSTOPB)
592 bios->c_cflag |= CSTOPB;
593 if (lios->c_cflag & LINUX_CREAD)
594 bios->c_cflag |= CREAD;
595 if (lios->c_cflag & LINUX_PARENB)
596 bios->c_cflag |= PARENB;
597 if (lios->c_cflag & LINUX_PARODD)
598 bios->c_cflag |= PARODD;
599 if (lios->c_cflag & LINUX_HUPCL)
600 bios->c_cflag |= HUPCL;
601 if (lios->c_cflag & LINUX_CLOCAL)
602 bios->c_cflag |= CLOCAL;
603 if (lios->c_cflag & LINUX_CRTSCTS)
604 bios->c_cflag |= CRTSCTS;
605
606 bios->c_lflag = 0;
607 if (lios->c_lflag & LINUX_ISIG)
608 bios->c_lflag |= ISIG;
609 if (lios->c_lflag & LINUX_ICANON)
610 bios->c_lflag |= ICANON;
611 if (lios->c_lflag & LINUX_ECHO)
612 bios->c_lflag |= ECHO;
613 if (lios->c_lflag & LINUX_ECHOE)
614 bios->c_lflag |= ECHOE;
615 if (lios->c_lflag & LINUX_ECHOK)
616 bios->c_lflag |= ECHOK;
617 if (lios->c_lflag & LINUX_ECHONL)
618 bios->c_lflag |= ECHONL;
619 if (lios->c_lflag & LINUX_NOFLSH)
620 bios->c_lflag |= NOFLSH;
621 if (lios->c_lflag & LINUX_TOSTOP)
622 bios->c_lflag |= TOSTOP;
623 if (lios->c_lflag & LINUX_ECHOCTL)
624 bios->c_lflag |= ECHOCTL;
625 if (lios->c_lflag & LINUX_ECHOPRT)
626 bios->c_lflag |= ECHOPRT;
627 if (lios->c_lflag & LINUX_ECHOKE)
628 bios->c_lflag |= ECHOKE;
629 if (lios->c_lflag & LINUX_FLUSHO)
630 bios->c_lflag |= FLUSHO;
631 if (lios->c_lflag & LINUX_PENDIN)
632 bios->c_lflag |= PENDIN;
633 if (lios->c_lflag & LINUX_IEXTEN)
634 bios->c_lflag |= IEXTEN;
635
636 for (i=0; i<NCCS; i++)
637 bios->c_cc[i] = _POSIX_VDISABLE;
638 bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
639 bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
640 bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
641 bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
642 bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
643 bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
644 bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
645 bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
646 bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
647 bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
648 bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
649 bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
650 bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
651 bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
652 bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
653 bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
654 if (linux_preserve_vstatus)
655 bios->c_cc[VSTATUS] = lios->c_cc[LINUX_VSTATUS];
656
657 for (i=0; i<NCCS; i++) {
658 if (i != VMIN && i != VTIME &&
659 bios->c_cc[i] == LINUX_POSIX_VDISABLE)
660 bios->c_cc[i] = _POSIX_VDISABLE;
661 }
662
663 bios->c_ispeed = bios->c_ospeed =
664 linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
665 }
666
667 static void
linux_to_bsd_termios2(struct linux_termios2 * lios2,struct termios * bios)668 linux_to_bsd_termios2(struct linux_termios2 *lios2, struct termios *bios)
669 {
670 linux_to_bsd_termios((struct linux_termios *)lios2, bios);
671 if ((lios2->c_cflag & LINUX_CBAUD) == LINUX_BOTHER)
672 bios->c_ospeed = lios2->c_ospeed;
673 if ((lios2->c_cflag & LINUX_CIBAUD) == LINUX_BOTHER << LINUX_IBSHIFT)
674 bios->c_ispeed = lios2->c_ispeed;
675 }
676
677 static void
bsd_to_linux_termio(struct termios * bios,struct linux_termio * lio)678 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
679 {
680 struct linux_termios lios;
681
682 memset(lio, 0, sizeof(*lio));
683 bsd_to_linux_termios(bios, &lios);
684 lio->c_iflag = lios.c_iflag;
685 lio->c_oflag = lios.c_oflag;
686 lio->c_cflag = lios.c_cflag;
687 lio->c_lflag = lios.c_lflag;
688 lio->c_line = lios.c_line;
689 memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
690 }
691
692 static void
linux_to_bsd_termio(struct linux_termio * lio,struct termios * bios)693 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
694 {
695 struct linux_termios lios;
696 int i;
697
698 lios.c_iflag = lio->c_iflag;
699 lios.c_oflag = lio->c_oflag;
700 lios.c_cflag = lio->c_cflag;
701 lios.c_lflag = lio->c_lflag;
702 for (i=LINUX_NCC; i<LINUX_NCCS; i++)
703 lios.c_cc[i] = LINUX_POSIX_VDISABLE;
704 memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
705 linux_to_bsd_termios(&lios, bios);
706 }
707
708 static int
linux_ioctl_termio(struct thread * td,struct linux_ioctl_args * args)709 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
710 {
711 struct termios bios;
712 struct linux_termios lios;
713 struct linux_termios2 lios2;
714 struct linux_termio lio;
715 struct file *fp;
716 int error;
717
718 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
719 if (error != 0)
720 return (error);
721
722 switch (args->cmd & 0xffff) {
723 case LINUX_TCGETS:
724 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
725 td);
726 if (error)
727 break;
728 bsd_to_linux_termios(&bios, &lios);
729 error = copyout(&lios, (void *)args->arg, sizeof(lios));
730 break;
731
732 case LINUX_TCSETS:
733 error = copyin((void *)args->arg, &lios, sizeof(lios));
734 if (error)
735 break;
736 linux_to_bsd_termios(&lios, &bios);
737 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
738 td));
739 break;
740
741 case LINUX_TCSETSW:
742 error = copyin((void *)args->arg, &lios, sizeof(lios));
743 if (error)
744 break;
745 linux_to_bsd_termios(&lios, &bios);
746 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
747 td));
748 break;
749
750 case LINUX_TCSETSF:
751 error = copyin((void *)args->arg, &lios, sizeof(lios));
752 if (error)
753 break;
754 linux_to_bsd_termios(&lios, &bios);
755 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
756 td));
757 break;
758
759 case LINUX_TCGETA:
760 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
761 td);
762 if (error)
763 break;
764 bsd_to_linux_termio(&bios, &lio);
765 error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
766 break;
767
768 case LINUX_TCSETA:
769 error = copyin((void *)args->arg, &lio, sizeof(lio));
770 if (error)
771 break;
772 linux_to_bsd_termio(&lio, &bios);
773 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
774 td));
775 break;
776
777 case LINUX_TCSETAW:
778 error = copyin((void *)args->arg, &lio, sizeof(lio));
779 if (error)
780 break;
781 linux_to_bsd_termio(&lio, &bios);
782 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
783 td));
784 break;
785
786 case LINUX_TCSETAF:
787 error = copyin((void *)args->arg, &lio, sizeof(lio));
788 if (error)
789 break;
790 linux_to_bsd_termio(&lio, &bios);
791 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
792 td));
793 break;
794
795 case LINUX_TCSBRK:
796 if (args->arg != 0) {
797 error = (fo_ioctl(fp, TIOCDRAIN, (caddr_t)&bios, td->td_ucred,
798 td));
799 } else {
800 linux_msg(td, "ioctl TCSBRK arg 0 not implemented");
801 error = ENOIOCTL;
802 }
803 break;
804
805 case LINUX_TCXONC: {
806 switch (args->arg) {
807 case LINUX_TCOOFF:
808 args->cmd = TIOCSTOP;
809 break;
810 case LINUX_TCOON:
811 args->cmd = TIOCSTART;
812 break;
813 case LINUX_TCIOFF:
814 case LINUX_TCION: {
815 int c;
816 struct write_args wr;
817 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
818 td->td_ucred, td);
819 if (error)
820 break;
821 fdrop(fp, td);
822 c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
823 c = bios.c_cc[c];
824 if (c != _POSIX_VDISABLE) {
825 wr.fd = args->fd;
826 wr.buf = &c;
827 wr.nbyte = sizeof(c);
828 return (sys_write(td, &wr));
829 } else
830 return (0);
831 }
832 default:
833 fdrop(fp, td);
834 return (EINVAL);
835 }
836 args->arg = 0;
837 error = (sys_ioctl(td, (struct ioctl_args *)args));
838 break;
839 }
840
841 case LINUX_TCFLSH: {
842 int val;
843 switch (args->arg) {
844 case LINUX_TCIFLUSH:
845 val = FREAD;
846 break;
847 case LINUX_TCOFLUSH:
848 val = FWRITE;
849 break;
850 case LINUX_TCIOFLUSH:
851 val = FREAD | FWRITE;
852 break;
853 default:
854 fdrop(fp, td);
855 return (EINVAL);
856 }
857 error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
858 break;
859 }
860
861 case LINUX_TIOCEXCL:
862 args->cmd = TIOCEXCL;
863 error = (sys_ioctl(td, (struct ioctl_args *)args));
864 break;
865
866 case LINUX_TIOCNXCL:
867 args->cmd = TIOCNXCL;
868 error = (sys_ioctl(td, (struct ioctl_args *)args));
869 break;
870
871 case LINUX_TIOCSCTTY:
872 args->cmd = TIOCSCTTY;
873 error = (sys_ioctl(td, (struct ioctl_args *)args));
874 break;
875
876 case LINUX_TIOCGPGRP:
877 args->cmd = TIOCGPGRP;
878 error = (sys_ioctl(td, (struct ioctl_args *)args));
879 break;
880
881 case LINUX_TIOCSPGRP:
882 args->cmd = TIOCSPGRP;
883 error = (sys_ioctl(td, (struct ioctl_args *)args));
884 break;
885
886 /* LINUX_TIOCOUTQ */
887 /* LINUX_TIOCSTI */
888
889 case LINUX_TIOCGWINSZ:
890 args->cmd = TIOCGWINSZ;
891 error = (sys_ioctl(td, (struct ioctl_args *)args));
892 break;
893
894 case LINUX_TIOCSWINSZ:
895 args->cmd = TIOCSWINSZ;
896 error = (sys_ioctl(td, (struct ioctl_args *)args));
897 break;
898
899 case LINUX_TIOCMGET:
900 args->cmd = TIOCMGET;
901 error = (sys_ioctl(td, (struct ioctl_args *)args));
902 break;
903
904 case LINUX_TIOCMBIS:
905 args->cmd = TIOCMBIS;
906 error = (sys_ioctl(td, (struct ioctl_args *)args));
907 break;
908
909 case LINUX_TIOCMBIC:
910 args->cmd = TIOCMBIC;
911 error = (sys_ioctl(td, (struct ioctl_args *)args));
912 break;
913
914 case LINUX_TIOCMSET:
915 args->cmd = TIOCMSET;
916 error = (sys_ioctl(td, (struct ioctl_args *)args));
917 break;
918
919 /* TIOCGSOFTCAR */
920 /* TIOCSSOFTCAR */
921
922 case LINUX_FIONREAD: /* LINUX_TIOCINQ */
923 args->cmd = FIONREAD;
924 error = (sys_ioctl(td, (struct ioctl_args *)args));
925 break;
926
927 /* LINUX_TIOCLINUX */
928
929 case LINUX_TIOCCONS:
930 args->cmd = TIOCCONS;
931 error = (sys_ioctl(td, (struct ioctl_args *)args));
932 break;
933
934 case LINUX_TIOCGSERIAL: {
935 struct linux_serial_struct lss;
936
937 bzero(&lss, sizeof(lss));
938 lss.type = LINUX_PORT_16550A;
939 lss.flags = 0;
940 lss.close_delay = 0;
941 error = copyout(&lss, (void *)args->arg, sizeof(lss));
942 break;
943 }
944
945 case LINUX_TIOCSSERIAL: {
946 struct linux_serial_struct lss;
947 error = copyin((void *)args->arg, &lss, sizeof(lss));
948 if (error)
949 break;
950 /* XXX - It really helps to have an implementation that
951 * does nothing. NOT!
952 */
953 error = 0;
954 break;
955 }
956
957 case LINUX_TIOCPKT:
958 args->cmd = TIOCPKT;
959 error = (sys_ioctl(td, (struct ioctl_args *)args));
960 break;
961
962 case LINUX_FIONBIO:
963 args->cmd = FIONBIO;
964 error = (sys_ioctl(td, (struct ioctl_args *)args));
965 break;
966
967 case LINUX_TIOCNOTTY:
968 args->cmd = TIOCNOTTY;
969 error = (sys_ioctl(td, (struct ioctl_args *)args));
970 break;
971
972 case LINUX_TIOCSETD: {
973 int line;
974 switch (args->arg) {
975 case LINUX_N_TTY:
976 line = TTYDISC;
977 break;
978 case LINUX_N_SLIP:
979 line = SLIPDISC;
980 break;
981 case LINUX_N_PPP:
982 line = PPPDISC;
983 break;
984 default:
985 fdrop(fp, td);
986 return (EINVAL);
987 }
988 error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
989 td));
990 break;
991 }
992
993 case LINUX_TIOCGETD: {
994 int linux_line;
995 int bsd_line = TTYDISC;
996 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
997 td->td_ucred, td);
998 if (error)
999 break;
1000 switch (bsd_line) {
1001 case TTYDISC:
1002 linux_line = LINUX_N_TTY;
1003 break;
1004 case SLIPDISC:
1005 linux_line = LINUX_N_SLIP;
1006 break;
1007 case PPPDISC:
1008 linux_line = LINUX_N_PPP;
1009 break;
1010 default:
1011 fdrop(fp, td);
1012 return (EINVAL);
1013 }
1014 error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
1015 break;
1016 }
1017
1018 /* LINUX_TCSBRKP */
1019 /* LINUX_TIOCTTYGSTRUCT */
1020
1021 case LINUX_FIONCLEX:
1022 args->cmd = FIONCLEX;
1023 error = (sys_ioctl(td, (struct ioctl_args *)args));
1024 break;
1025
1026 case LINUX_FIOCLEX:
1027 args->cmd = FIOCLEX;
1028 error = (sys_ioctl(td, (struct ioctl_args *)args));
1029 break;
1030
1031 case LINUX_FIOASYNC:
1032 args->cmd = FIOASYNC;
1033 error = (sys_ioctl(td, (struct ioctl_args *)args));
1034 break;
1035
1036 /* LINUX_TIOCSERCONFIG */
1037 /* LINUX_TIOCSERGWILD */
1038 /* LINUX_TIOCSERSWILD */
1039 /* LINUX_TIOCGLCKTRMIOS */
1040 /* LINUX_TIOCSLCKTRMIOS */
1041
1042 case LINUX_TIOCSBRK:
1043 args->cmd = TIOCSBRK;
1044 error = (sys_ioctl(td, (struct ioctl_args *)args));
1045 break;
1046
1047 case LINUX_TIOCCBRK:
1048 args->cmd = TIOCCBRK;
1049 error = (sys_ioctl(td, (struct ioctl_args *)args));
1050 break;
1051
1052 case LINUX_TCGETS2:
1053 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
1054 td);
1055 if (error)
1056 break;
1057 bsd_to_linux_termios2(&bios, &lios2);
1058 error = copyout(&lios2, (void *)args->arg, sizeof(lios2));
1059 break;
1060
1061 case LINUX_TCSETS2:
1062 error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1063 if (error)
1064 break;
1065 linux_to_bsd_termios2(&lios2, &bios);
1066 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
1067 td));
1068 break;
1069
1070 case LINUX_TCSETSW2:
1071 error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1072 if (error)
1073 break;
1074 linux_to_bsd_termios2(&lios2, &bios);
1075 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
1076 td));
1077 break;
1078
1079 case LINUX_TCSETSF2:
1080 error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1081 if (error)
1082 break;
1083 linux_to_bsd_termios2(&lios2, &bios);
1084 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
1085 td));
1086 break;
1087
1088 case LINUX_TIOCGPTN: {
1089 int nb;
1090
1091 error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
1092 if (!error)
1093 error = copyout(&nb, (void *)args->arg,
1094 sizeof(int));
1095 break;
1096 }
1097 case LINUX_TIOCGPTPEER:
1098 linux_msg(td, "unsupported ioctl TIOCGPTPEER");
1099 error = ENOIOCTL;
1100 break;
1101 case LINUX_TIOCSPTLCK:
1102 /*
1103 * Our unlockpt() does nothing. Check that fd refers
1104 * to a pseudo-terminal master device.
1105 */
1106 args->cmd = TIOCPTMASTER;
1107 error = (sys_ioctl(td, (struct ioctl_args *)args));
1108 break;
1109 default:
1110 error = ENOIOCTL;
1111 break;
1112 }
1113
1114 fdrop(fp, td);
1115 return (error);
1116 }
1117
1118 /*
1119 * CDROM related ioctls
1120 */
1121
1122 struct linux_cdrom_msf
1123 {
1124 u_char cdmsf_min0;
1125 u_char cdmsf_sec0;
1126 u_char cdmsf_frame0;
1127 u_char cdmsf_min1;
1128 u_char cdmsf_sec1;
1129 u_char cdmsf_frame1;
1130 };
1131
1132 struct linux_cdrom_tochdr
1133 {
1134 u_char cdth_trk0;
1135 u_char cdth_trk1;
1136 };
1137
1138 union linux_cdrom_addr
1139 {
1140 struct {
1141 u_char minute;
1142 u_char second;
1143 u_char frame;
1144 } msf;
1145 int lba;
1146 };
1147
1148 struct linux_cdrom_tocentry
1149 {
1150 u_char cdte_track;
1151 u_char cdte_adr:4;
1152 u_char cdte_ctrl:4;
1153 u_char cdte_format;
1154 union linux_cdrom_addr cdte_addr;
1155 u_char cdte_datamode;
1156 };
1157
1158 struct linux_cdrom_subchnl
1159 {
1160 u_char cdsc_format;
1161 u_char cdsc_audiostatus;
1162 u_char cdsc_adr:4;
1163 u_char cdsc_ctrl:4;
1164 u_char cdsc_trk;
1165 u_char cdsc_ind;
1166 union linux_cdrom_addr cdsc_absaddr;
1167 union linux_cdrom_addr cdsc_reladdr;
1168 };
1169
1170 struct l_cdrom_read_audio {
1171 union linux_cdrom_addr addr;
1172 u_char addr_format;
1173 l_int nframes;
1174 u_char *buf;
1175 };
1176
1177 struct l_dvd_layer {
1178 u_char book_version:4;
1179 u_char book_type:4;
1180 u_char min_rate:4;
1181 u_char disc_size:4;
1182 u_char layer_type:4;
1183 u_char track_path:1;
1184 u_char nlayers:2;
1185 u_char track_density:4;
1186 u_char linear_density:4;
1187 u_char bca:1;
1188 uint32_t start_sector;
1189 uint32_t end_sector;
1190 uint32_t end_sector_l0;
1191 };
1192
1193 struct l_dvd_physical {
1194 u_char type;
1195 u_char layer_num;
1196 struct l_dvd_layer layer[4];
1197 };
1198
1199 struct l_dvd_copyright {
1200 u_char type;
1201 u_char layer_num;
1202 u_char cpst;
1203 u_char rmi;
1204 };
1205
1206 struct l_dvd_disckey {
1207 u_char type;
1208 l_uint agid:2;
1209 u_char value[2048];
1210 };
1211
1212 struct l_dvd_bca {
1213 u_char type;
1214 l_int len;
1215 u_char value[188];
1216 };
1217
1218 struct l_dvd_manufact {
1219 u_char type;
1220 u_char layer_num;
1221 l_int len;
1222 u_char value[2048];
1223 };
1224
1225 typedef union {
1226 u_char type;
1227 struct l_dvd_physical physical;
1228 struct l_dvd_copyright copyright;
1229 struct l_dvd_disckey disckey;
1230 struct l_dvd_bca bca;
1231 struct l_dvd_manufact manufact;
1232 } l_dvd_struct;
1233
1234 typedef u_char l_dvd_key[5];
1235 typedef u_char l_dvd_challenge[10];
1236
1237 struct l_dvd_lu_send_agid {
1238 u_char type;
1239 l_uint agid:2;
1240 };
1241
1242 struct l_dvd_host_send_challenge {
1243 u_char type;
1244 l_uint agid:2;
1245 l_dvd_challenge chal;
1246 };
1247
1248 struct l_dvd_send_key {
1249 u_char type;
1250 l_uint agid:2;
1251 l_dvd_key key;
1252 };
1253
1254 struct l_dvd_lu_send_challenge {
1255 u_char type;
1256 l_uint agid:2;
1257 l_dvd_challenge chal;
1258 };
1259
1260 struct l_dvd_lu_send_title_key {
1261 u_char type;
1262 l_uint agid:2;
1263 l_dvd_key title_key;
1264 l_int lba;
1265 l_uint cpm:1;
1266 l_uint cp_sec:1;
1267 l_uint cgms:2;
1268 };
1269
1270 struct l_dvd_lu_send_asf {
1271 u_char type;
1272 l_uint agid:2;
1273 l_uint asf:1;
1274 };
1275
1276 struct l_dvd_host_send_rpcstate {
1277 u_char type;
1278 u_char pdrc;
1279 };
1280
1281 struct l_dvd_lu_send_rpcstate {
1282 u_char type:2;
1283 u_char vra:3;
1284 u_char ucca:3;
1285 u_char region_mask;
1286 u_char rpc_scheme;
1287 };
1288
1289 typedef union {
1290 u_char type;
1291 struct l_dvd_lu_send_agid lsa;
1292 struct l_dvd_host_send_challenge hsc;
1293 struct l_dvd_send_key lsk;
1294 struct l_dvd_lu_send_challenge lsc;
1295 struct l_dvd_send_key hsk;
1296 struct l_dvd_lu_send_title_key lstk;
1297 struct l_dvd_lu_send_asf lsasf;
1298 struct l_dvd_host_send_rpcstate hrpcs;
1299 struct l_dvd_lu_send_rpcstate lrpcs;
1300 } l_dvd_authinfo;
1301
1302 static void
bsd_to_linux_msf_lba(u_char af,union msf_lba * bp,union linux_cdrom_addr * lp)1303 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
1304 {
1305 if (af == CD_LBA_FORMAT)
1306 lp->lba = bp->lba;
1307 else {
1308 lp->msf.minute = bp->msf.minute;
1309 lp->msf.second = bp->msf.second;
1310 lp->msf.frame = bp->msf.frame;
1311 }
1312 }
1313
1314 static void
set_linux_cdrom_addr(union linux_cdrom_addr * addr,int format,int lba)1315 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
1316 {
1317 if (format == LINUX_CDROM_MSF) {
1318 addr->msf.frame = lba % 75;
1319 lba /= 75;
1320 lba += 2;
1321 addr->msf.second = lba % 60;
1322 addr->msf.minute = lba / 60;
1323 } else
1324 addr->lba = lba;
1325 }
1326
1327 static int
linux_to_bsd_dvd_struct(l_dvd_struct * lp,struct dvd_struct * bp)1328 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
1329 {
1330 bp->format = lp->type;
1331 switch (bp->format) {
1332 case DVD_STRUCT_PHYSICAL:
1333 if (bp->layer_num >= 4)
1334 return (EINVAL);
1335 bp->layer_num = lp->physical.layer_num;
1336 break;
1337 case DVD_STRUCT_COPYRIGHT:
1338 bp->layer_num = lp->copyright.layer_num;
1339 break;
1340 case DVD_STRUCT_DISCKEY:
1341 bp->agid = lp->disckey.agid;
1342 break;
1343 case DVD_STRUCT_BCA:
1344 case DVD_STRUCT_MANUFACT:
1345 break;
1346 default:
1347 return (EINVAL);
1348 }
1349 return (0);
1350 }
1351
1352 static int
bsd_to_linux_dvd_struct(struct dvd_struct * bp,l_dvd_struct * lp)1353 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
1354 {
1355 switch (bp->format) {
1356 case DVD_STRUCT_PHYSICAL: {
1357 struct dvd_layer *blp = (struct dvd_layer *)bp->data;
1358 struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
1359 memset(llp, 0, sizeof(*llp));
1360 llp->book_version = blp->book_version;
1361 llp->book_type = blp->book_type;
1362 llp->min_rate = blp->max_rate;
1363 llp->disc_size = blp->disc_size;
1364 llp->layer_type = blp->layer_type;
1365 llp->track_path = blp->track_path;
1366 llp->nlayers = blp->nlayers;
1367 llp->track_density = blp->track_density;
1368 llp->linear_density = blp->linear_density;
1369 llp->bca = blp->bca;
1370 llp->start_sector = blp->start_sector;
1371 llp->end_sector = blp->end_sector;
1372 llp->end_sector_l0 = blp->end_sector_l0;
1373 break;
1374 }
1375 case DVD_STRUCT_COPYRIGHT:
1376 lp->copyright.cpst = bp->cpst;
1377 lp->copyright.rmi = bp->rmi;
1378 break;
1379 case DVD_STRUCT_DISCKEY:
1380 memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
1381 break;
1382 case DVD_STRUCT_BCA:
1383 lp->bca.len = bp->length;
1384 memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
1385 break;
1386 case DVD_STRUCT_MANUFACT:
1387 lp->manufact.len = bp->length;
1388 memcpy(lp->manufact.value, bp->data,
1389 sizeof(lp->manufact.value));
1390 /* lp->manufact.layer_num is unused in Linux (redhat 7.0). */
1391 break;
1392 default:
1393 return (EINVAL);
1394 }
1395 return (0);
1396 }
1397
1398 static int
linux_to_bsd_dvd_authinfo(l_dvd_authinfo * lp,int * bcode,struct dvd_authinfo * bp)1399 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
1400 struct dvd_authinfo *bp)
1401 {
1402 switch (lp->type) {
1403 case LINUX_DVD_LU_SEND_AGID:
1404 *bcode = DVDIOCREPORTKEY;
1405 bp->format = DVD_REPORT_AGID;
1406 bp->agid = lp->lsa.agid;
1407 break;
1408 case LINUX_DVD_HOST_SEND_CHALLENGE:
1409 *bcode = DVDIOCSENDKEY;
1410 bp->format = DVD_SEND_CHALLENGE;
1411 bp->agid = lp->hsc.agid;
1412 memcpy(bp->keychal, lp->hsc.chal, 10);
1413 break;
1414 case LINUX_DVD_LU_SEND_KEY1:
1415 *bcode = DVDIOCREPORTKEY;
1416 bp->format = DVD_REPORT_KEY1;
1417 bp->agid = lp->lsk.agid;
1418 break;
1419 case LINUX_DVD_LU_SEND_CHALLENGE:
1420 *bcode = DVDIOCREPORTKEY;
1421 bp->format = DVD_REPORT_CHALLENGE;
1422 bp->agid = lp->lsc.agid;
1423 break;
1424 case LINUX_DVD_HOST_SEND_KEY2:
1425 *bcode = DVDIOCSENDKEY;
1426 bp->format = DVD_SEND_KEY2;
1427 bp->agid = lp->hsk.agid;
1428 memcpy(bp->keychal, lp->hsk.key, 5);
1429 break;
1430 case LINUX_DVD_LU_SEND_TITLE_KEY:
1431 *bcode = DVDIOCREPORTKEY;
1432 bp->format = DVD_REPORT_TITLE_KEY;
1433 bp->agid = lp->lstk.agid;
1434 bp->lba = lp->lstk.lba;
1435 break;
1436 case LINUX_DVD_LU_SEND_ASF:
1437 *bcode = DVDIOCREPORTKEY;
1438 bp->format = DVD_REPORT_ASF;
1439 bp->agid = lp->lsasf.agid;
1440 break;
1441 case LINUX_DVD_INVALIDATE_AGID:
1442 *bcode = DVDIOCREPORTKEY;
1443 bp->format = DVD_INVALIDATE_AGID;
1444 bp->agid = lp->lsa.agid;
1445 break;
1446 case LINUX_DVD_LU_SEND_RPC_STATE:
1447 *bcode = DVDIOCREPORTKEY;
1448 bp->format = DVD_REPORT_RPC;
1449 break;
1450 case LINUX_DVD_HOST_SEND_RPC_STATE:
1451 *bcode = DVDIOCSENDKEY;
1452 bp->format = DVD_SEND_RPC;
1453 bp->region = lp->hrpcs.pdrc;
1454 break;
1455 default:
1456 return (EINVAL);
1457 }
1458 return (0);
1459 }
1460
1461 static int
bsd_to_linux_dvd_authinfo(struct dvd_authinfo * bp,l_dvd_authinfo * lp)1462 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
1463 {
1464 switch (lp->type) {
1465 case LINUX_DVD_LU_SEND_AGID:
1466 lp->lsa.agid = bp->agid;
1467 break;
1468 case LINUX_DVD_HOST_SEND_CHALLENGE:
1469 lp->type = LINUX_DVD_LU_SEND_KEY1;
1470 break;
1471 case LINUX_DVD_LU_SEND_KEY1:
1472 memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
1473 break;
1474 case LINUX_DVD_LU_SEND_CHALLENGE:
1475 memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
1476 break;
1477 case LINUX_DVD_HOST_SEND_KEY2:
1478 lp->type = LINUX_DVD_AUTH_ESTABLISHED;
1479 break;
1480 case LINUX_DVD_LU_SEND_TITLE_KEY:
1481 memcpy(lp->lstk.title_key, bp->keychal,
1482 sizeof(lp->lstk.title_key));
1483 lp->lstk.cpm = bp->cpm;
1484 lp->lstk.cp_sec = bp->cp_sec;
1485 lp->lstk.cgms = bp->cgms;
1486 break;
1487 case LINUX_DVD_LU_SEND_ASF:
1488 lp->lsasf.asf = bp->asf;
1489 break;
1490 case LINUX_DVD_INVALIDATE_AGID:
1491 break;
1492 case LINUX_DVD_LU_SEND_RPC_STATE:
1493 lp->lrpcs.type = bp->reg_type;
1494 lp->lrpcs.vra = bp->vend_rsts;
1495 lp->lrpcs.ucca = bp->user_rsts;
1496 lp->lrpcs.region_mask = bp->region;
1497 lp->lrpcs.rpc_scheme = bp->rpc_scheme;
1498 break;
1499 case LINUX_DVD_HOST_SEND_RPC_STATE:
1500 break;
1501 default:
1502 return (EINVAL);
1503 }
1504 return (0);
1505 }
1506
1507 static int
linux_ioctl_cdrom(struct thread * td,struct linux_ioctl_args * args)1508 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
1509 {
1510 struct file *fp;
1511 int error;
1512
1513 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
1514 if (error != 0)
1515 return (error);
1516 switch (args->cmd & 0xffff) {
1517 case LINUX_CDROMPAUSE:
1518 args->cmd = CDIOCPAUSE;
1519 error = (sys_ioctl(td, (struct ioctl_args *)args));
1520 break;
1521
1522 case LINUX_CDROMRESUME:
1523 args->cmd = CDIOCRESUME;
1524 error = (sys_ioctl(td, (struct ioctl_args *)args));
1525 break;
1526
1527 case LINUX_CDROMPLAYMSF:
1528 args->cmd = CDIOCPLAYMSF;
1529 error = (sys_ioctl(td, (struct ioctl_args *)args));
1530 break;
1531
1532 case LINUX_CDROMPLAYTRKIND:
1533 args->cmd = CDIOCPLAYTRACKS;
1534 error = (sys_ioctl(td, (struct ioctl_args *)args));
1535 break;
1536
1537 case LINUX_CDROMREADTOCHDR: {
1538 struct ioc_toc_header th;
1539 struct linux_cdrom_tochdr lth;
1540 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
1541 td->td_ucred, td);
1542 if (!error) {
1543 lth.cdth_trk0 = th.starting_track;
1544 lth.cdth_trk1 = th.ending_track;
1545 error = copyout(<h, (void *)args->arg, sizeof(lth));
1546 }
1547 break;
1548 }
1549
1550 case LINUX_CDROMREADTOCENTRY: {
1551 struct linux_cdrom_tocentry lte;
1552 struct ioc_read_toc_single_entry irtse;
1553
1554 error = copyin((void *)args->arg, <e, sizeof(lte));
1555 if (error)
1556 break;
1557 irtse.address_format = lte.cdte_format;
1558 irtse.track = lte.cdte_track;
1559 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
1560 td->td_ucred, td);
1561 if (!error) {
1562 lte.cdte_ctrl = irtse.entry.control;
1563 lte.cdte_adr = irtse.entry.addr_type;
1564 bsd_to_linux_msf_lba(irtse.address_format,
1565 &irtse.entry.addr, <e.cdte_addr);
1566 error = copyout(<e, (void *)args->arg, sizeof(lte));
1567 }
1568 break;
1569 }
1570
1571 case LINUX_CDROMSTOP:
1572 args->cmd = CDIOCSTOP;
1573 error = (sys_ioctl(td, (struct ioctl_args *)args));
1574 break;
1575
1576 case LINUX_CDROMSTART:
1577 args->cmd = CDIOCSTART;
1578 error = (sys_ioctl(td, (struct ioctl_args *)args));
1579 break;
1580
1581 case LINUX_CDROMEJECT:
1582 args->cmd = CDIOCEJECT;
1583 error = (sys_ioctl(td, (struct ioctl_args *)args));
1584 break;
1585
1586 /* LINUX_CDROMVOLCTRL */
1587
1588 case LINUX_CDROMSUBCHNL: {
1589 struct linux_cdrom_subchnl sc;
1590 struct ioc_read_subchannel bsdsc;
1591 struct cd_sub_channel_info bsdinfo;
1592
1593 error = copyin((void *)args->arg, &sc, sizeof(sc));
1594 if (error)
1595 break;
1596
1597 /*
1598 * Invoke the native ioctl and bounce the returned data through
1599 * the userspace buffer. This works because the Linux structure
1600 * is the same size as our structures for the subchannel header
1601 * and position data.
1602 */
1603 bsdsc.address_format = CD_LBA_FORMAT;
1604 bsdsc.data_format = CD_CURRENT_POSITION;
1605 bsdsc.track = 0;
1606 bsdsc.data_len = sizeof(sc);
1607 bsdsc.data = (void *)args->arg;
1608 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc,
1609 td->td_ucred, td);
1610 if (error)
1611 break;
1612 error = copyin((void *)args->arg, &bsdinfo, sizeof(bsdinfo));
1613 if (error)
1614 break;
1615 sc.cdsc_audiostatus = bsdinfo.header.audio_status;
1616 sc.cdsc_adr = bsdinfo.what.position.addr_type;
1617 sc.cdsc_ctrl = bsdinfo.what.position.control;
1618 sc.cdsc_trk = bsdinfo.what.position.track_number;
1619 sc.cdsc_ind = bsdinfo.what.position.index_number;
1620 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
1621 bsdinfo.what.position.absaddr.lba);
1622 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
1623 bsdinfo.what.position.reladdr.lba);
1624 error = copyout(&sc, (void *)args->arg, sizeof(sc));
1625 break;
1626 }
1627
1628 /* LINUX_CDROMREADMODE2 */
1629 /* LINUX_CDROMREADMODE1 */
1630 /* LINUX_CDROMREADAUDIO */
1631 /* LINUX_CDROMEJECT_SW */
1632 /* LINUX_CDROMMULTISESSION */
1633 /* LINUX_CDROM_GET_UPC */
1634
1635 case LINUX_CDROMRESET:
1636 args->cmd = CDIOCRESET;
1637 error = (sys_ioctl(td, (struct ioctl_args *)args));
1638 break;
1639
1640 /* LINUX_CDROMVOLREAD */
1641 /* LINUX_CDROMREADRAW */
1642 /* LINUX_CDROMREADCOOKED */
1643 /* LINUX_CDROMSEEK */
1644 /* LINUX_CDROMPLAYBLK */
1645 /* LINUX_CDROMREADALL */
1646 /* LINUX_CDROMCLOSETRAY */
1647 /* LINUX_CDROMLOADFROMSLOT */
1648 /* LINUX_CDROMGETSPINDOWN */
1649 /* LINUX_CDROMSETSPINDOWN */
1650 /* LINUX_CDROM_SET_OPTIONS */
1651 /* LINUX_CDROM_CLEAR_OPTIONS */
1652 /* LINUX_CDROM_SELECT_SPEED */
1653 /* LINUX_CDROM_SELECT_DISC */
1654 /* LINUX_CDROM_MEDIA_CHANGED */
1655 /* LINUX_CDROM_DRIVE_STATUS */
1656 /* LINUX_CDROM_DISC_STATUS */
1657 /* LINUX_CDROM_CHANGER_NSLOTS */
1658 /* LINUX_CDROM_LOCKDOOR */
1659 /* LINUX_CDROM_DEBUG */
1660 /* LINUX_CDROM_GET_CAPABILITY */
1661 /* LINUX_CDROMAUDIOBUFSIZ */
1662
1663 case LINUX_DVD_READ_STRUCT: {
1664 l_dvd_struct *lds;
1665 struct dvd_struct *bds;
1666
1667 lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK);
1668 bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK);
1669 error = copyin((void *)args->arg, lds, sizeof(*lds));
1670 if (error)
1671 goto out;
1672 error = linux_to_bsd_dvd_struct(lds, bds);
1673 if (error)
1674 goto out;
1675 error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds,
1676 td->td_ucred, td);
1677 if (error)
1678 goto out;
1679 error = bsd_to_linux_dvd_struct(bds, lds);
1680 if (error)
1681 goto out;
1682 error = copyout(lds, (void *)args->arg, sizeof(*lds));
1683 out:
1684 free(bds, M_LINUX);
1685 free(lds, M_LINUX);
1686 break;
1687 }
1688
1689 /* LINUX_DVD_WRITE_STRUCT */
1690
1691 case LINUX_DVD_AUTH: {
1692 l_dvd_authinfo lda;
1693 struct dvd_authinfo bda;
1694 int bcode;
1695
1696 error = copyin((void *)args->arg, &lda, sizeof(lda));
1697 if (error)
1698 break;
1699 error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
1700 if (error)
1701 break;
1702 error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
1703 td);
1704 if (error) {
1705 if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
1706 lda.type = LINUX_DVD_AUTH_FAILURE;
1707 (void)copyout(&lda, (void *)args->arg,
1708 sizeof(lda));
1709 }
1710 break;
1711 }
1712 error = bsd_to_linux_dvd_authinfo(&bda, &lda);
1713 if (error)
1714 break;
1715 error = copyout(&lda, (void *)args->arg, sizeof(lda));
1716 break;
1717 }
1718
1719 case LINUX_SCSI_GET_BUS_NUMBER:
1720 {
1721 struct sg_scsi_id id;
1722
1723 error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1724 td->td_ucred, td);
1725 if (error)
1726 break;
1727 error = copyout(&id.channel, (void *)args->arg, sizeof(int));
1728 break;
1729 }
1730
1731 case LINUX_SCSI_GET_IDLUN:
1732 {
1733 struct sg_scsi_id id;
1734 struct scsi_idlun idl;
1735
1736 error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1737 td->td_ucred, td);
1738 if (error)
1739 break;
1740 idl.dev_id = (id.scsi_id & 0xff) + ((id.lun & 0xff) << 8) +
1741 ((id.channel & 0xff) << 16) + ((id.host_no & 0xff) << 24);
1742 idl.host_unique_id = id.host_no;
1743 error = copyout(&idl, (void *)args->arg, sizeof(idl));
1744 break;
1745 }
1746
1747 /* LINUX_CDROM_SEND_PACKET */
1748 /* LINUX_CDROM_NEXT_WRITABLE */
1749 /* LINUX_CDROM_LAST_WRITTEN */
1750
1751 default:
1752 error = ENOIOCTL;
1753 break;
1754 }
1755
1756 fdrop(fp, td);
1757 return (error);
1758 }
1759
1760 static int
linux_ioctl_vfat(struct thread * td,struct linux_ioctl_args * args)1761 linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
1762 {
1763
1764 return (ENOTTY);
1765 }
1766
1767 /*
1768 * Sound related ioctls
1769 */
1770
1771 struct linux_old_mixer_info {
1772 char id[16];
1773 char name[32];
1774 };
1775
1776 static uint32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
1777
1778 #define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
1779
1780 static int
linux_ioctl_sound(struct thread * td,struct linux_ioctl_args * args)1781 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
1782 {
1783
1784 switch (args->cmd & 0xffff) {
1785 case LINUX_SOUND_MIXER_WRITE_VOLUME:
1786 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
1787 return (sys_ioctl(td, (struct ioctl_args *)args));
1788
1789 case LINUX_SOUND_MIXER_WRITE_BASS:
1790 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
1791 return (sys_ioctl(td, (struct ioctl_args *)args));
1792
1793 case LINUX_SOUND_MIXER_WRITE_TREBLE:
1794 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
1795 return (sys_ioctl(td, (struct ioctl_args *)args));
1796
1797 case LINUX_SOUND_MIXER_WRITE_SYNTH:
1798 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
1799 return (sys_ioctl(td, (struct ioctl_args *)args));
1800
1801 case LINUX_SOUND_MIXER_WRITE_PCM:
1802 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
1803 return (sys_ioctl(td, (struct ioctl_args *)args));
1804
1805 case LINUX_SOUND_MIXER_WRITE_SPEAKER:
1806 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
1807 return (sys_ioctl(td, (struct ioctl_args *)args));
1808
1809 case LINUX_SOUND_MIXER_WRITE_LINE:
1810 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
1811 return (sys_ioctl(td, (struct ioctl_args *)args));
1812
1813 case LINUX_SOUND_MIXER_WRITE_MIC:
1814 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
1815 return (sys_ioctl(td, (struct ioctl_args *)args));
1816
1817 case LINUX_SOUND_MIXER_WRITE_CD:
1818 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
1819 return (sys_ioctl(td, (struct ioctl_args *)args));
1820
1821 case LINUX_SOUND_MIXER_WRITE_IMIX:
1822 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
1823 return (sys_ioctl(td, (struct ioctl_args *)args));
1824
1825 case LINUX_SOUND_MIXER_WRITE_ALTPCM:
1826 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
1827 return (sys_ioctl(td, (struct ioctl_args *)args));
1828
1829 case LINUX_SOUND_MIXER_WRITE_RECLEV:
1830 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
1831 return (sys_ioctl(td, (struct ioctl_args *)args));
1832
1833 case LINUX_SOUND_MIXER_WRITE_IGAIN:
1834 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
1835 return (sys_ioctl(td, (struct ioctl_args *)args));
1836
1837 case LINUX_SOUND_MIXER_WRITE_OGAIN:
1838 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
1839 return (sys_ioctl(td, (struct ioctl_args *)args));
1840
1841 case LINUX_SOUND_MIXER_WRITE_LINE1:
1842 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
1843 return (sys_ioctl(td, (struct ioctl_args *)args));
1844
1845 case LINUX_SOUND_MIXER_WRITE_LINE2:
1846 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
1847 return (sys_ioctl(td, (struct ioctl_args *)args));
1848
1849 case LINUX_SOUND_MIXER_WRITE_LINE3:
1850 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
1851 return (sys_ioctl(td, (struct ioctl_args *)args));
1852
1853 case LINUX_SOUND_MIXER_WRITE_MONITOR:
1854 args->cmd = SETDIR(SOUND_MIXER_WRITE_MONITOR);
1855 return (sys_ioctl(td, (struct ioctl_args *)args));
1856
1857 case LINUX_SOUND_MIXER_INFO: {
1858 /* Key on encoded length */
1859 switch ((args->cmd >> 16) & 0x1fff) {
1860 case 0x005c: { /* SOUND_MIXER_INFO */
1861 args->cmd = SOUND_MIXER_INFO;
1862 return (sys_ioctl(td, (struct ioctl_args *)args));
1863 }
1864 case 0x0030: { /* SOUND_OLD_MIXER_INFO */
1865 struct linux_old_mixer_info info;
1866 bzero(&info, sizeof(info));
1867 strncpy(info.id, "OSS", sizeof(info.id) - 1);
1868 strncpy(info.name, "FreeBSD OSS Mixer",
1869 sizeof(info.name) - 1);
1870 return (copyout(&info, (void *)args->arg,
1871 sizeof(info)));
1872 }
1873 default:
1874 return (ENOIOCTL);
1875 }
1876 break;
1877 }
1878
1879 case LINUX_OSS_GETVERSION: {
1880 int version = linux_get_oss_version(td);
1881 return (copyout(&version, (void *)args->arg, sizeof(int)));
1882 }
1883
1884 case LINUX_SOUND_MIXER_READ_STEREODEVS:
1885 args->cmd = SOUND_MIXER_READ_STEREODEVS;
1886 return (sys_ioctl(td, (struct ioctl_args *)args));
1887
1888 case LINUX_SOUND_MIXER_READ_CAPS:
1889 args->cmd = SOUND_MIXER_READ_CAPS;
1890 return (sys_ioctl(td, (struct ioctl_args *)args));
1891
1892 case LINUX_SOUND_MIXER_READ_RECMASK:
1893 args->cmd = SOUND_MIXER_READ_RECMASK;
1894 return (sys_ioctl(td, (struct ioctl_args *)args));
1895
1896 case LINUX_SOUND_MIXER_READ_DEVMASK:
1897 args->cmd = SOUND_MIXER_READ_DEVMASK;
1898 return (sys_ioctl(td, (struct ioctl_args *)args));
1899
1900 case LINUX_SOUND_MIXER_WRITE_RECSRC:
1901 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
1902 return (sys_ioctl(td, (struct ioctl_args *)args));
1903
1904 case LINUX_SNDCTL_DSP_RESET:
1905 args->cmd = SNDCTL_DSP_RESET;
1906 return (sys_ioctl(td, (struct ioctl_args *)args));
1907
1908 case LINUX_SNDCTL_DSP_SYNC:
1909 args->cmd = SNDCTL_DSP_SYNC;
1910 return (sys_ioctl(td, (struct ioctl_args *)args));
1911
1912 case LINUX_SNDCTL_DSP_SPEED:
1913 args->cmd = SNDCTL_DSP_SPEED;
1914 return (sys_ioctl(td, (struct ioctl_args *)args));
1915
1916 case LINUX_SNDCTL_DSP_STEREO:
1917 args->cmd = SNDCTL_DSP_STEREO;
1918 return (sys_ioctl(td, (struct ioctl_args *)args));
1919
1920 case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
1921 args->cmd = SNDCTL_DSP_GETBLKSIZE;
1922 return (sys_ioctl(td, (struct ioctl_args *)args));
1923
1924 case LINUX_SNDCTL_DSP_SETFMT:
1925 args->cmd = SNDCTL_DSP_SETFMT;
1926 return (sys_ioctl(td, (struct ioctl_args *)args));
1927
1928 case LINUX_SOUND_PCM_WRITE_CHANNELS:
1929 args->cmd = SOUND_PCM_WRITE_CHANNELS;
1930 return (sys_ioctl(td, (struct ioctl_args *)args));
1931
1932 case LINUX_SOUND_PCM_WRITE_FILTER:
1933 args->cmd = SOUND_PCM_WRITE_FILTER;
1934 return (sys_ioctl(td, (struct ioctl_args *)args));
1935
1936 case LINUX_SNDCTL_DSP_POST:
1937 args->cmd = SNDCTL_DSP_POST;
1938 return (sys_ioctl(td, (struct ioctl_args *)args));
1939
1940 case LINUX_SNDCTL_DSP_SUBDIVIDE:
1941 args->cmd = SNDCTL_DSP_SUBDIVIDE;
1942 return (sys_ioctl(td, (struct ioctl_args *)args));
1943
1944 case LINUX_SNDCTL_DSP_SETFRAGMENT:
1945 args->cmd = SNDCTL_DSP_SETFRAGMENT;
1946 return (sys_ioctl(td, (struct ioctl_args *)args));
1947
1948 case LINUX_SNDCTL_DSP_GETFMTS:
1949 args->cmd = SNDCTL_DSP_GETFMTS;
1950 return (sys_ioctl(td, (struct ioctl_args *)args));
1951
1952 case LINUX_SNDCTL_DSP_GETOSPACE:
1953 args->cmd = SNDCTL_DSP_GETOSPACE;
1954 return (sys_ioctl(td, (struct ioctl_args *)args));
1955
1956 case LINUX_SNDCTL_DSP_GETISPACE:
1957 args->cmd = SNDCTL_DSP_GETISPACE;
1958 return (sys_ioctl(td, (struct ioctl_args *)args));
1959
1960 case LINUX_SNDCTL_DSP_NONBLOCK:
1961 args->cmd = SNDCTL_DSP_NONBLOCK;
1962 return (sys_ioctl(td, (struct ioctl_args *)args));
1963
1964 case LINUX_SNDCTL_DSP_GETCAPS:
1965 args->cmd = SNDCTL_DSP_GETCAPS;
1966 return (sys_ioctl(td, (struct ioctl_args *)args));
1967
1968 case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
1969 args->cmd = SNDCTL_DSP_SETTRIGGER;
1970 return (sys_ioctl(td, (struct ioctl_args *)args));
1971
1972 case LINUX_SNDCTL_DSP_GETIPTR:
1973 args->cmd = SNDCTL_DSP_GETIPTR;
1974 return (sys_ioctl(td, (struct ioctl_args *)args));
1975
1976 case LINUX_SNDCTL_DSP_GETOPTR:
1977 args->cmd = SNDCTL_DSP_GETOPTR;
1978 return (sys_ioctl(td, (struct ioctl_args *)args));
1979
1980 case LINUX_SNDCTL_DSP_SETDUPLEX:
1981 args->cmd = SNDCTL_DSP_SETDUPLEX;
1982 return (sys_ioctl(td, (struct ioctl_args *)args));
1983
1984 case LINUX_SNDCTL_DSP_GETODELAY:
1985 args->cmd = SNDCTL_DSP_GETODELAY;
1986 return (sys_ioctl(td, (struct ioctl_args *)args));
1987
1988 case LINUX_SNDCTL_SEQ_RESET:
1989 args->cmd = SNDCTL_SEQ_RESET;
1990 return (sys_ioctl(td, (struct ioctl_args *)args));
1991
1992 case LINUX_SNDCTL_SEQ_SYNC:
1993 args->cmd = SNDCTL_SEQ_SYNC;
1994 return (sys_ioctl(td, (struct ioctl_args *)args));
1995
1996 case LINUX_SNDCTL_SYNTH_INFO:
1997 args->cmd = SNDCTL_SYNTH_INFO;
1998 return (sys_ioctl(td, (struct ioctl_args *)args));
1999
2000 case LINUX_SNDCTL_SEQ_CTRLRATE:
2001 args->cmd = SNDCTL_SEQ_CTRLRATE;
2002 return (sys_ioctl(td, (struct ioctl_args *)args));
2003
2004 case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
2005 args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
2006 return (sys_ioctl(td, (struct ioctl_args *)args));
2007
2008 case LINUX_SNDCTL_SEQ_GETINCOUNT:
2009 args->cmd = SNDCTL_SEQ_GETINCOUNT;
2010 return (sys_ioctl(td, (struct ioctl_args *)args));
2011
2012 case LINUX_SNDCTL_SEQ_PERCMODE:
2013 args->cmd = SNDCTL_SEQ_PERCMODE;
2014 return (sys_ioctl(td, (struct ioctl_args *)args));
2015
2016 case LINUX_SNDCTL_FM_LOAD_INSTR:
2017 args->cmd = SNDCTL_FM_LOAD_INSTR;
2018 return (sys_ioctl(td, (struct ioctl_args *)args));
2019
2020 case LINUX_SNDCTL_SEQ_TESTMIDI:
2021 args->cmd = SNDCTL_SEQ_TESTMIDI;
2022 return (sys_ioctl(td, (struct ioctl_args *)args));
2023
2024 case LINUX_SNDCTL_SEQ_RESETSAMPLES:
2025 args->cmd = SNDCTL_SEQ_RESETSAMPLES;
2026 return (sys_ioctl(td, (struct ioctl_args *)args));
2027
2028 case LINUX_SNDCTL_SEQ_NRSYNTHS:
2029 args->cmd = SNDCTL_SEQ_NRSYNTHS;
2030 return (sys_ioctl(td, (struct ioctl_args *)args));
2031
2032 case LINUX_SNDCTL_SEQ_NRMIDIS:
2033 args->cmd = SNDCTL_SEQ_NRMIDIS;
2034 return (sys_ioctl(td, (struct ioctl_args *)args));
2035
2036 case LINUX_SNDCTL_MIDI_INFO:
2037 args->cmd = SNDCTL_MIDI_INFO;
2038 return (sys_ioctl(td, (struct ioctl_args *)args));
2039
2040 case LINUX_SNDCTL_SEQ_TRESHOLD:
2041 args->cmd = SNDCTL_SEQ_TRESHOLD;
2042 return (sys_ioctl(td, (struct ioctl_args *)args));
2043
2044 case LINUX_SNDCTL_SYNTH_MEMAVL:
2045 args->cmd = SNDCTL_SYNTH_MEMAVL;
2046 return (sys_ioctl(td, (struct ioctl_args *)args));
2047 }
2048
2049 return (ENOIOCTL);
2050 }
2051
2052 /*
2053 * Console related ioctls
2054 */
2055
2056 static int
linux_ioctl_console(struct thread * td,struct linux_ioctl_args * args)2057 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
2058 {
2059 struct file *fp;
2060 int error;
2061
2062 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2063 if (error != 0)
2064 return (error);
2065 switch (args->cmd & 0xffff) {
2066 case LINUX_KIOCSOUND:
2067 args->cmd = KIOCSOUND;
2068 error = (sys_ioctl(td, (struct ioctl_args *)args));
2069 break;
2070
2071 case LINUX_KDMKTONE:
2072 args->cmd = KDMKTONE;
2073 error = (sys_ioctl(td, (struct ioctl_args *)args));
2074 break;
2075
2076 case LINUX_KDGETLED:
2077 args->cmd = KDGETLED;
2078 error = (sys_ioctl(td, (struct ioctl_args *)args));
2079 break;
2080
2081 case LINUX_KDSETLED:
2082 args->cmd = KDSETLED;
2083 error = (sys_ioctl(td, (struct ioctl_args *)args));
2084 break;
2085
2086 case LINUX_KDSETMODE:
2087 args->cmd = KDSETMODE;
2088 error = (sys_ioctl(td, (struct ioctl_args *)args));
2089 break;
2090
2091 case LINUX_KDGETMODE:
2092 args->cmd = KDGETMODE;
2093 error = (sys_ioctl(td, (struct ioctl_args *)args));
2094 break;
2095
2096 case LINUX_KDGKBMODE:
2097 args->cmd = KDGKBMODE;
2098 error = (sys_ioctl(td, (struct ioctl_args *)args));
2099 break;
2100
2101 case LINUX_KDSKBMODE: {
2102 int kbdmode;
2103 switch (args->arg) {
2104 case LINUX_KBD_RAW:
2105 kbdmode = K_RAW;
2106 break;
2107 case LINUX_KBD_XLATE:
2108 kbdmode = K_XLATE;
2109 break;
2110 case LINUX_KBD_MEDIUMRAW:
2111 kbdmode = K_RAW;
2112 break;
2113 default:
2114 fdrop(fp, td);
2115 return (EINVAL);
2116 }
2117 error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
2118 td->td_ucred, td));
2119 break;
2120 }
2121
2122 case LINUX_VT_OPENQRY:
2123 args->cmd = VT_OPENQRY;
2124 error = (sys_ioctl(td, (struct ioctl_args *)args));
2125 break;
2126
2127 case LINUX_VT_GETMODE:
2128 args->cmd = VT_GETMODE;
2129 error = (sys_ioctl(td, (struct ioctl_args *)args));
2130 break;
2131
2132 case LINUX_VT_SETMODE: {
2133 struct vt_mode mode;
2134 if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
2135 break;
2136 if (LINUX_SIG_VALID(mode.relsig))
2137 mode.relsig = linux_to_bsd_signal(mode.relsig);
2138 else
2139 mode.relsig = 0;
2140 if (LINUX_SIG_VALID(mode.acqsig))
2141 mode.acqsig = linux_to_bsd_signal(mode.acqsig);
2142 else
2143 mode.acqsig = 0;
2144 /* XXX. Linux ignores frsig and set it to 0. */
2145 mode.frsig = 0;
2146 if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
2147 break;
2148 args->cmd = VT_SETMODE;
2149 error = (sys_ioctl(td, (struct ioctl_args *)args));
2150 break;
2151 }
2152
2153 case LINUX_VT_GETSTATE:
2154 args->cmd = VT_GETACTIVE;
2155 error = (sys_ioctl(td, (struct ioctl_args *)args));
2156 break;
2157
2158 case LINUX_VT_RELDISP:
2159 args->cmd = VT_RELDISP;
2160 error = (sys_ioctl(td, (struct ioctl_args *)args));
2161 break;
2162
2163 case LINUX_VT_ACTIVATE:
2164 args->cmd = VT_ACTIVATE;
2165 error = (sys_ioctl(td, (struct ioctl_args *)args));
2166 break;
2167
2168 case LINUX_VT_WAITACTIVE:
2169 args->cmd = VT_WAITACTIVE;
2170 error = (sys_ioctl(td, (struct ioctl_args *)args));
2171 break;
2172
2173 default:
2174 error = ENOIOCTL;
2175 break;
2176 }
2177
2178 fdrop(fp, td);
2179 return (error);
2180 }
2181
2182 /*
2183 * Implement the SIOCGIFNAME ioctl
2184 */
2185
2186 static int
linux_ioctl_ifname(struct thread * td,struct l_ifreq * uifr)2187 linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
2188 {
2189 struct l_ifreq ifr;
2190 int error, ret;
2191
2192 error = copyin(uifr, &ifr, sizeof(ifr));
2193 if (error != 0)
2194 return (error);
2195 ret = ifname_bsd_to_linux_idx(ifr.ifr_index, ifr.ifr_name,
2196 LINUX_IFNAMSIZ);
2197 if (ret > 0)
2198 return (copyout(&ifr, uifr, sizeof(ifr)));
2199 else
2200 return (ENODEV);
2201 }
2202
2203 /*
2204 * Implement the SIOCGIFCONF ioctl
2205 */
2206 static u_int
linux_ifconf_ifaddr_cb(void * arg,struct ifaddr * ifa,u_int count)2207 linux_ifconf_ifaddr_cb(void *arg, struct ifaddr *ifa, u_int count)
2208 {
2209 #ifdef COMPAT_LINUX32
2210 struct l_ifconf *ifc;
2211 #else
2212 struct ifconf *ifc;
2213 #endif
2214
2215 ifc = arg;
2216 ifc->ifc_len += sizeof(struct l_ifreq);
2217 return (1);
2218 }
2219
2220 static int
linux_ifconf_ifnet_cb(if_t ifp,void * arg)2221 linux_ifconf_ifnet_cb(if_t ifp, void *arg)
2222 {
2223
2224 if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb, arg);
2225 return (0);
2226 }
2227
2228 struct linux_ifconfig_ifaddr_cb2_s {
2229 struct l_ifreq ifr;
2230 struct sbuf *sb;
2231 size_t max_len;
2232 size_t valid_len;
2233 };
2234
2235 static u_int
linux_ifconf_ifaddr_cb2(void * arg,struct ifaddr * ifa,u_int len)2236 linux_ifconf_ifaddr_cb2(void *arg, struct ifaddr *ifa, u_int len)
2237 {
2238 struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
2239 struct sockaddr *sa = ifa->ifa_addr;
2240
2241 cbs->ifr.ifr_addr.sa_family = LINUX_AF_INET;
2242 memcpy(cbs->ifr.ifr_addr.sa_data, sa->sa_data,
2243 sizeof(cbs->ifr.ifr_addr.sa_data));
2244 sbuf_bcat(cbs->sb, &cbs->ifr, sizeof(cbs->ifr));
2245 cbs->max_len += sizeof(cbs->ifr);
2246
2247 if (sbuf_error(cbs->sb) == 0)
2248 cbs->valid_len = sbuf_len(cbs->sb);
2249 return (1);
2250 }
2251
2252 static int
linux_ifconf_ifnet_cb2(if_t ifp,void * arg)2253 linux_ifconf_ifnet_cb2(if_t ifp, void *arg)
2254 {
2255 struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
2256
2257 bzero(&cbs->ifr, sizeof(cbs->ifr));
2258 ifname_bsd_to_linux_ifp(ifp, cbs->ifr.ifr_name,
2259 sizeof(cbs->ifr.ifr_name));
2260
2261 /* Walk the address list */
2262 if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb2, cbs);
2263 return (0);
2264 }
2265
2266 static int
linux_ifconf(struct thread * td,struct ifconf * uifc)2267 linux_ifconf(struct thread *td, struct ifconf *uifc)
2268 {
2269 struct linux_ifconfig_ifaddr_cb2_s cbs;
2270 struct epoch_tracker et;
2271 #ifdef COMPAT_LINUX32
2272 struct l_ifconf ifc;
2273 #else
2274 struct ifconf ifc;
2275 #endif
2276 struct sbuf *sb;
2277 int error, full;
2278
2279 error = copyin(uifc, &ifc, sizeof(ifc));
2280 if (error != 0)
2281 return (error);
2282
2283 /* handle the 'request buffer size' case */
2284 if (PTRIN(ifc.ifc_buf) == NULL) {
2285 ifc.ifc_len = 0;
2286 NET_EPOCH_ENTER(et);
2287 if_foreach(linux_ifconf_ifnet_cb, &ifc);
2288 NET_EPOCH_EXIT(et);
2289 return (copyout(&ifc, uifc, sizeof(ifc)));
2290 }
2291 if (ifc.ifc_len <= 0)
2292 return (EINVAL);
2293
2294 full = 0;
2295 cbs.max_len = maxphys - 1;
2296
2297 again:
2298 if (ifc.ifc_len <= cbs.max_len) {
2299 cbs.max_len = ifc.ifc_len;
2300 full = 1;
2301 }
2302 cbs.sb = sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN);
2303 cbs.max_len = 0;
2304 cbs.valid_len = 0;
2305
2306 /* Return all AF_INET addresses of all interfaces */
2307 NET_EPOCH_ENTER(et);
2308 if_foreach(linux_ifconf_ifnet_cb2, &cbs);
2309 NET_EPOCH_EXIT(et);
2310
2311 if (cbs.valid_len != cbs.max_len && !full) {
2312 sbuf_delete(sb);
2313 goto again;
2314 }
2315
2316 ifc.ifc_len = cbs.valid_len;
2317 sbuf_finish(sb);
2318 error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len);
2319 if (error == 0)
2320 error = copyout(&ifc, uifc, sizeof(ifc));
2321 sbuf_delete(sb);
2322
2323 return (error);
2324 }
2325
2326 static int
linux_ioctl_socket_ifreq(struct thread * td,int fd,u_int cmd,struct l_ifreq * uifr)2327 linux_ioctl_socket_ifreq(struct thread *td, int fd, u_int cmd,
2328 struct l_ifreq *uifr)
2329 {
2330 struct l_ifreq lifr;
2331 struct ifreq bifr;
2332 size_t ifrusiz;
2333 int error, temp_flags;
2334
2335 switch (cmd) {
2336 case LINUX_SIOCGIFINDEX:
2337 cmd = SIOCGIFINDEX;
2338 break;
2339 case LINUX_SIOCGIFFLAGS:
2340 cmd = SIOCGIFFLAGS;
2341 break;
2342 case LINUX_SIOCGIFADDR:
2343 cmd = SIOCGIFADDR;
2344 break;
2345 case LINUX_SIOCSIFADDR:
2346 cmd = SIOCSIFADDR;
2347 break;
2348 case LINUX_SIOCGIFDSTADDR:
2349 cmd = SIOCGIFDSTADDR;
2350 break;
2351 case LINUX_SIOCGIFBRDADDR:
2352 cmd = SIOCGIFBRDADDR;
2353 break;
2354 case LINUX_SIOCGIFNETMASK:
2355 cmd = SIOCGIFNETMASK;
2356 break;
2357 case LINUX_SIOCSIFNETMASK:
2358 cmd = SIOCSIFNETMASK;
2359 break;
2360 case LINUX_SIOCGIFMTU:
2361 cmd = SIOCGIFMTU;
2362 break;
2363 case LINUX_SIOCSIFMTU:
2364 cmd = SIOCSIFMTU;
2365 break;
2366 case LINUX_SIOCGIFHWADDR:
2367 cmd = SIOCGHWADDR;
2368 break;
2369 case LINUX_SIOCGIFMETRIC:
2370 cmd = SIOCGIFMETRIC;
2371 break;
2372 case LINUX_SIOCSIFMETRIC:
2373 cmd = SIOCSIFMETRIC;
2374 break;
2375 /*
2376 * XXX This is slightly bogus, but these ioctls are currently
2377 * XXX only used by the aironet (if_an) network driver.
2378 */
2379 case LINUX_SIOCDEVPRIVATE:
2380 cmd = SIOCGPRIVATE_0;
2381 break;
2382 case LINUX_SIOCDEVPRIVATE+1:
2383 cmd = SIOCGPRIVATE_1;
2384 break;
2385 default:
2386 LINUX_RATELIMIT_MSG_OPT2(
2387 "ioctl_socket_ifreq fd=%d, cmd=0x%x is not implemented",
2388 fd, cmd);
2389 return (ENOIOCTL);
2390 }
2391
2392 error = copyin(uifr, &lifr, sizeof(lifr));
2393 if (error != 0)
2394 return (error);
2395 bzero(&bifr, sizeof(bifr));
2396
2397 /*
2398 * The size of Linux enum ifr_ifru is bigger than
2399 * the FreeBSD size due to the struct ifmap.
2400 */
2401 ifrusiz = (sizeof(lifr) > sizeof(bifr) ? sizeof(bifr) :
2402 sizeof(lifr)) - offsetof(struct l_ifreq, ifr_ifru);
2403 bcopy(&lifr.ifr_ifru, &bifr.ifr_ifru, ifrusiz);
2404
2405 error = ifname_linux_to_bsd(td, lifr.ifr_name, bifr.ifr_name);
2406 if (error != 0)
2407 return (error);
2408
2409 /* Translate in values. */
2410 switch (cmd) {
2411 case SIOCGIFINDEX:
2412 bifr.ifr_index = lifr.ifr_index;
2413 break;
2414 case SIOCSIFADDR:
2415 case SIOCSIFNETMASK:
2416 bifr.ifr_addr.sa_len = sizeof(struct sockaddr);
2417 bifr.ifr_addr.sa_family =
2418 linux_to_bsd_domain(lifr.ifr_addr.sa_family);
2419 break;
2420 default:
2421 break;
2422 }
2423
2424 error = kern_ioctl(td, fd, cmd, (caddr_t)&bifr);
2425 if (error != 0)
2426 return (error);
2427 bzero(&lifr.ifr_ifru, sizeof(lifr.ifr_ifru));
2428
2429 /* Translate out values. */
2430 switch (cmd) {
2431 case SIOCGIFINDEX:
2432 lifr.ifr_index = bifr.ifr_index;
2433 break;
2434 case SIOCGIFFLAGS:
2435 temp_flags = bifr.ifr_flags | (bifr.ifr_flagshigh << 16);
2436 lifr.ifr_flags = bsd_to_linux_ifflags(temp_flags);
2437 break;
2438 case SIOCGIFADDR:
2439 case SIOCSIFADDR:
2440 case SIOCGIFDSTADDR:
2441 case SIOCGIFBRDADDR:
2442 case SIOCGIFNETMASK:
2443 bcopy(&bifr.ifr_addr, &lifr.ifr_addr, sizeof(bifr.ifr_addr));
2444 lifr.ifr_addr.sa_family =
2445 bsd_to_linux_domain(bifr.ifr_addr.sa_family);
2446 break;
2447 case SIOCGHWADDR:
2448 bcopy(&bifr.ifr_addr, &lifr.ifr_hwaddr, sizeof(bifr.ifr_addr));
2449 lifr.ifr_hwaddr.sa_family = LINUX_ARPHRD_ETHER;
2450 break;
2451 default:
2452 bcopy(&bifr.ifr_ifru, &lifr.ifr_ifru, ifrusiz);
2453 break;
2454 }
2455
2456 return (copyout(&lifr, uifr, sizeof(lifr)));
2457 }
2458
2459 /*
2460 * Socket related ioctls
2461 */
2462
2463 static int
linux_ioctl_socket(struct thread * td,struct linux_ioctl_args * args)2464 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
2465 {
2466 struct file *fp;
2467 int error, type;
2468
2469 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2470 if (error != 0)
2471 return (error);
2472 type = fp->f_type;
2473 fdrop(fp, td);
2474
2475 CURVNET_SET(TD_TO_VNET(td));
2476
2477 if (type != DTYPE_SOCKET) {
2478 /* not a socket - probably a tap / vmnet device */
2479 switch (args->cmd) {
2480 case LINUX_SIOCGIFADDR:
2481 case LINUX_SIOCSIFADDR:
2482 case LINUX_SIOCGIFFLAGS:
2483 error = linux_ioctl_special(td, args);
2484 break;
2485 default:
2486 error = ENOIOCTL;
2487 break;
2488 }
2489 CURVNET_RESTORE();
2490 return (error);
2491 }
2492
2493 switch (args->cmd) {
2494 case LINUX_FIOSETOWN:
2495 args->cmd = FIOSETOWN;
2496 error = sys_ioctl(td, (struct ioctl_args *)args);
2497 break;
2498
2499 case LINUX_SIOCSPGRP:
2500 args->cmd = SIOCSPGRP;
2501 error = sys_ioctl(td, (struct ioctl_args *)args);
2502 break;
2503
2504 case LINUX_FIOGETOWN:
2505 args->cmd = FIOGETOWN;
2506 error = sys_ioctl(td, (struct ioctl_args *)args);
2507 break;
2508
2509 case LINUX_SIOCGPGRP:
2510 args->cmd = SIOCGPGRP;
2511 error = sys_ioctl(td, (struct ioctl_args *)args);
2512 break;
2513
2514 case LINUX_SIOCATMARK:
2515 args->cmd = SIOCATMARK;
2516 error = sys_ioctl(td, (struct ioctl_args *)args);
2517 break;
2518
2519 /* LINUX_SIOCGSTAMP */
2520
2521 case LINUX_SIOCGIFNAME:
2522 error = linux_ioctl_ifname(td, (struct l_ifreq *)args->arg);
2523 break;
2524
2525 case LINUX_SIOCGIFCONF:
2526 error = linux_ifconf(td, (struct ifconf *)args->arg);
2527 break;
2528
2529 case LINUX_SIOCADDMULTI:
2530 args->cmd = SIOCADDMULTI;
2531 error = sys_ioctl(td, (struct ioctl_args *)args);
2532 break;
2533
2534 case LINUX_SIOCDELMULTI:
2535 args->cmd = SIOCDELMULTI;
2536 error = sys_ioctl(td, (struct ioctl_args *)args);
2537 break;
2538
2539 case LINUX_SIOCGIFCOUNT:
2540 error = 0;
2541 break;
2542
2543 default:
2544 error = linux_ioctl_socket_ifreq(td, args->fd, args->cmd,
2545 PTRIN(args->arg));
2546 break;
2547 }
2548
2549 CURVNET_RESTORE();
2550 return (error);
2551 }
2552
2553 /*
2554 * Device private ioctl handler
2555 */
2556 static int
linux_ioctl_private(struct thread * td,struct linux_ioctl_args * args)2557 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
2558 {
2559 struct file *fp;
2560 int error, type;
2561
2562 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2563 if (error != 0)
2564 return (error);
2565 type = fp->f_type;
2566 fdrop(fp, td);
2567 if (type == DTYPE_SOCKET)
2568 return (linux_ioctl_socket(td, args));
2569 return (ENOIOCTL);
2570 }
2571
2572 /*
2573 * DRM ioctl handler (sys/dev/drm)
2574 */
2575 static int
linux_ioctl_drm(struct thread * td,struct linux_ioctl_args * args)2576 linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
2577 {
2578 args->cmd = SETDIR(args->cmd);
2579 return (sys_ioctl(td, (struct ioctl_args *)args));
2580 }
2581
2582 #ifdef COMPAT_LINUX32
2583 static int
linux_ioctl_sg_io(struct thread * td,struct linux_ioctl_args * args)2584 linux_ioctl_sg_io(struct thread *td, struct linux_ioctl_args *args)
2585 {
2586 struct sg_io_hdr io;
2587 struct sg_io_hdr32 io32;
2588 struct file *fp;
2589 int error;
2590
2591 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2592 if (error != 0) {
2593 printf("sg_linux_ioctl: fget returned %d\n", error);
2594 return (error);
2595 }
2596
2597 if ((error = copyin((void *)args->arg, &io32, sizeof(io32))) != 0)
2598 goto out;
2599
2600 CP(io32, io, interface_id);
2601 CP(io32, io, dxfer_direction);
2602 CP(io32, io, cmd_len);
2603 CP(io32, io, mx_sb_len);
2604 CP(io32, io, iovec_count);
2605 CP(io32, io, dxfer_len);
2606 PTRIN_CP(io32, io, dxferp);
2607 PTRIN_CP(io32, io, cmdp);
2608 PTRIN_CP(io32, io, sbp);
2609 CP(io32, io, timeout);
2610 CP(io32, io, flags);
2611 CP(io32, io, pack_id);
2612 PTRIN_CP(io32, io, usr_ptr);
2613 CP(io32, io, status);
2614 CP(io32, io, masked_status);
2615 CP(io32, io, msg_status);
2616 CP(io32, io, sb_len_wr);
2617 CP(io32, io, host_status);
2618 CP(io32, io, driver_status);
2619 CP(io32, io, resid);
2620 CP(io32, io, duration);
2621 CP(io32, io, info);
2622
2623 if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0)
2624 goto out;
2625
2626 CP(io, io32, interface_id);
2627 CP(io, io32, dxfer_direction);
2628 CP(io, io32, cmd_len);
2629 CP(io, io32, mx_sb_len);
2630 CP(io, io32, iovec_count);
2631 CP(io, io32, dxfer_len);
2632 PTROUT_CP(io, io32, dxferp);
2633 PTROUT_CP(io, io32, cmdp);
2634 PTROUT_CP(io, io32, sbp);
2635 CP(io, io32, timeout);
2636 CP(io, io32, flags);
2637 CP(io, io32, pack_id);
2638 PTROUT_CP(io, io32, usr_ptr);
2639 CP(io, io32, status);
2640 CP(io, io32, masked_status);
2641 CP(io, io32, msg_status);
2642 CP(io, io32, sb_len_wr);
2643 CP(io, io32, host_status);
2644 CP(io, io32, driver_status);
2645 CP(io, io32, resid);
2646 CP(io, io32, duration);
2647 CP(io, io32, info);
2648
2649 error = copyout(&io32, (void *)args->arg, sizeof(io32));
2650
2651 out:
2652 fdrop(fp, td);
2653 return (error);
2654 }
2655 #endif
2656
2657 static int
linux_ioctl_sg(struct thread * td,struct linux_ioctl_args * args)2658 linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
2659 {
2660
2661 switch (args->cmd) {
2662 case LINUX_SG_GET_VERSION_NUM:
2663 args->cmd = SG_GET_VERSION_NUM;
2664 break;
2665 case LINUX_SG_SET_TIMEOUT:
2666 args->cmd = SG_SET_TIMEOUT;
2667 break;
2668 case LINUX_SG_GET_TIMEOUT:
2669 args->cmd = SG_GET_TIMEOUT;
2670 break;
2671 case LINUX_SG_IO:
2672 args->cmd = SG_IO;
2673 #ifdef COMPAT_LINUX32
2674 return (linux_ioctl_sg_io(td, args));
2675 #endif
2676 break;
2677 case LINUX_SG_GET_RESERVED_SIZE:
2678 args->cmd = SG_GET_RESERVED_SIZE;
2679 break;
2680 case LINUX_SG_GET_SCSI_ID:
2681 args->cmd = SG_GET_SCSI_ID;
2682 break;
2683 case LINUX_SG_GET_SG_TABLESIZE:
2684 args->cmd = SG_GET_SG_TABLESIZE;
2685 break;
2686 default:
2687 return (ENODEV);
2688 }
2689 return (sys_ioctl(td, (struct ioctl_args *)args));
2690 }
2691
2692 /*
2693 * Video4Linux (V4L) ioctl handler
2694 */
2695 static int
linux_to_bsd_v4l_tuner(struct l_video_tuner * lvt,struct video_tuner * vt)2696 linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt)
2697 {
2698 vt->tuner = lvt->tuner;
2699 strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2700 vt->rangelow = lvt->rangelow; /* possible long size conversion */
2701 vt->rangehigh = lvt->rangehigh; /* possible long size conversion */
2702 vt->flags = lvt->flags;
2703 vt->mode = lvt->mode;
2704 vt->signal = lvt->signal;
2705 return (0);
2706 }
2707
2708 static int
bsd_to_linux_v4l_tuner(struct video_tuner * vt,struct l_video_tuner * lvt)2709 bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
2710 {
2711 lvt->tuner = vt->tuner;
2712 strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2713 lvt->rangelow = vt->rangelow; /* possible long size conversion */
2714 lvt->rangehigh = vt->rangehigh; /* possible long size conversion */
2715 lvt->flags = vt->flags;
2716 lvt->mode = vt->mode;
2717 lvt->signal = vt->signal;
2718 return (0);
2719 }
2720
2721 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2722 static int
linux_to_bsd_v4l_clip(struct l_video_clip * lvc,struct video_clip * vc)2723 linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
2724 {
2725 vc->x = lvc->x;
2726 vc->y = lvc->y;
2727 vc->width = lvc->width;
2728 vc->height = lvc->height;
2729 vc->next = PTRIN(lvc->next); /* possible pointer size conversion */
2730 return (0);
2731 }
2732 #endif
2733
2734 static int
linux_to_bsd_v4l_window(struct l_video_window * lvw,struct video_window * vw)2735 linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
2736 {
2737 vw->x = lvw->x;
2738 vw->y = lvw->y;
2739 vw->width = lvw->width;
2740 vw->height = lvw->height;
2741 vw->chromakey = lvw->chromakey;
2742 vw->flags = lvw->flags;
2743 vw->clips = PTRIN(lvw->clips); /* possible pointer size conversion */
2744 vw->clipcount = lvw->clipcount;
2745 return (0);
2746 }
2747
2748 static int
bsd_to_linux_v4l_window(struct video_window * vw,struct l_video_window * lvw)2749 bsd_to_linux_v4l_window(struct video_window *vw, struct l_video_window *lvw)
2750 {
2751 memset(lvw, 0, sizeof(*lvw));
2752
2753 lvw->x = vw->x;
2754 lvw->y = vw->y;
2755 lvw->width = vw->width;
2756 lvw->height = vw->height;
2757 lvw->chromakey = vw->chromakey;
2758 lvw->flags = vw->flags;
2759 lvw->clips = PTROUT(vw->clips); /* possible pointer size conversion */
2760 lvw->clipcount = vw->clipcount;
2761 return (0);
2762 }
2763
2764 static int
linux_to_bsd_v4l_buffer(struct l_video_buffer * lvb,struct video_buffer * vb)2765 linux_to_bsd_v4l_buffer(struct l_video_buffer *lvb, struct video_buffer *vb)
2766 {
2767 vb->base = PTRIN(lvb->base); /* possible pointer size conversion */
2768 vb->height = lvb->height;
2769 vb->width = lvb->width;
2770 vb->depth = lvb->depth;
2771 vb->bytesperline = lvb->bytesperline;
2772 return (0);
2773 }
2774
2775 static int
bsd_to_linux_v4l_buffer(struct video_buffer * vb,struct l_video_buffer * lvb)2776 bsd_to_linux_v4l_buffer(struct video_buffer *vb, struct l_video_buffer *lvb)
2777 {
2778 lvb->base = PTROUT(vb->base); /* possible pointer size conversion */
2779 lvb->height = vb->height;
2780 lvb->width = vb->width;
2781 lvb->depth = vb->depth;
2782 lvb->bytesperline = vb->bytesperline;
2783 return (0);
2784 }
2785
2786 static int
linux_to_bsd_v4l_code(struct l_video_code * lvc,struct video_code * vc)2787 linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc)
2788 {
2789 strlcpy(vc->loadwhat, lvc->loadwhat, LINUX_VIDEO_CODE_LOADWHAT_SIZE);
2790 vc->datasize = lvc->datasize;
2791 vc->data = PTRIN(lvc->data); /* possible pointer size conversion */
2792 return (0);
2793 }
2794
2795 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2796 static int
linux_v4l_clip_copy(void * lvc,struct video_clip ** ppvc)2797 linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
2798 {
2799 int error;
2800 struct video_clip vclip;
2801 struct l_video_clip l_vclip;
2802
2803 error = copyin(lvc, &l_vclip, sizeof(l_vclip));
2804 if (error) return (error);
2805 linux_to_bsd_v4l_clip(&l_vclip, &vclip);
2806 /* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
2807 if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
2808 return (ENOMEM); /* XXX: Linux has no ENOMEM here. */
2809 memcpy(*ppvc, &vclip, sizeof(vclip));
2810 (*ppvc)->next = NULL;
2811 return (0);
2812 }
2813
2814 static int
linux_v4l_cliplist_free(struct video_window * vw)2815 linux_v4l_cliplist_free(struct video_window *vw)
2816 {
2817 struct video_clip **ppvc;
2818 struct video_clip **ppvc_next;
2819
2820 for (ppvc = &(vw->clips); *ppvc != NULL; ppvc = ppvc_next) {
2821 ppvc_next = &((*ppvc)->next);
2822 free(*ppvc, M_LINUX);
2823 }
2824 vw->clips = NULL;
2825
2826 return (0);
2827 }
2828
2829 static int
linux_v4l_cliplist_copy(struct l_video_window * lvw,struct video_window * vw)2830 linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
2831 {
2832 int error;
2833 int clipcount;
2834 void *plvc;
2835 struct video_clip **ppvc;
2836
2837 /*
2838 * XXX: The cliplist is used to pass in a list of clipping
2839 * rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a
2840 * clipping bitmap. Some Linux apps, however, appear to
2841 * leave cliplist and clips uninitialized. In any case,
2842 * the cliplist is not used by pwc(4), at the time of
2843 * writing, FreeBSD's only V4L driver. When a driver
2844 * that uses the cliplist is developed, this code may
2845 * need re-examiniation.
2846 */
2847 error = 0;
2848 clipcount = vw->clipcount;
2849 if (clipcount == VIDEO_CLIP_BITMAP) {
2850 /*
2851 * In this case, the pointer (clips) is overloaded
2852 * to be a "void *" to a bitmap, therefore there
2853 * is no struct video_clip to copy now.
2854 */
2855 } else if (clipcount > 0 && clipcount <= 16384) {
2856 /*
2857 * Clips points to list of clip rectangles, so
2858 * copy the list.
2859 *
2860 * XXX: Upper limit of 16384 was used here to try to
2861 * avoid cases when clipcount and clips pointer
2862 * are uninitialized and therefore have high random
2863 * values, as is the case in the Linux Skype
2864 * application. The value 16384 was chosen as that
2865 * is what is used in the Linux stradis(4) MPEG
2866 * decoder driver, the only place we found an
2867 * example of cliplist use.
2868 */
2869 plvc = PTRIN(lvw->clips);
2870 vw->clips = NULL;
2871 ppvc = &(vw->clips);
2872 while (clipcount-- > 0) {
2873 if (plvc == NULL) {
2874 error = EFAULT;
2875 break;
2876 } else {
2877 error = linux_v4l_clip_copy(plvc, ppvc);
2878 if (error) {
2879 linux_v4l_cliplist_free(vw);
2880 break;
2881 }
2882 }
2883 ppvc = &((*ppvc)->next);
2884 plvc = PTRIN(((struct l_video_clip *) plvc)->next);
2885 }
2886 } else {
2887 /*
2888 * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP)
2889 * Force cliplist to null.
2890 */
2891 vw->clipcount = 0;
2892 vw->clips = NULL;
2893 }
2894 return (error);
2895 }
2896 #endif
2897
2898 static int
linux_ioctl_v4l(struct thread * td,struct linux_ioctl_args * args)2899 linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
2900 {
2901 struct file *fp;
2902 int error;
2903 struct video_tuner vtun;
2904 struct video_window vwin;
2905 struct video_buffer vbuf;
2906 struct video_code vcode;
2907 struct l_video_tuner l_vtun;
2908 struct l_video_window l_vwin;
2909 struct l_video_buffer l_vbuf;
2910 struct l_video_code l_vcode;
2911
2912 switch (args->cmd & 0xffff) {
2913 case LINUX_VIDIOCGCAP: args->cmd = VIDIOCGCAP; break;
2914 case LINUX_VIDIOCGCHAN: args->cmd = VIDIOCGCHAN; break;
2915 case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break;
2916
2917 case LINUX_VIDIOCGTUNER:
2918 error = fget(td, args->fd,
2919 &cap_ioctl_rights, &fp);
2920 if (error != 0)
2921 return (error);
2922 error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
2923 if (error) {
2924 fdrop(fp, td);
2925 return (error);
2926 }
2927 linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
2928 error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td);
2929 if (!error) {
2930 bsd_to_linux_v4l_tuner(&vtun, &l_vtun);
2931 error = copyout(&l_vtun, (void *) args->arg,
2932 sizeof(l_vtun));
2933 }
2934 fdrop(fp, td);
2935 return (error);
2936
2937 case LINUX_VIDIOCSTUNER:
2938 error = fget(td, args->fd,
2939 &cap_ioctl_rights, &fp);
2940 if (error != 0)
2941 return (error);
2942 error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
2943 if (error) {
2944 fdrop(fp, td);
2945 return (error);
2946 }
2947 linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
2948 error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td);
2949 fdrop(fp, td);
2950 return (error);
2951
2952 case LINUX_VIDIOCGPICT: args->cmd = VIDIOCGPICT; break;
2953 case LINUX_VIDIOCSPICT: args->cmd = VIDIOCSPICT; break;
2954 case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break;
2955
2956 case LINUX_VIDIOCGWIN:
2957 error = fget(td, args->fd,
2958 &cap_ioctl_rights, &fp);
2959 if (error != 0)
2960 return (error);
2961 error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
2962 if (!error) {
2963 bsd_to_linux_v4l_window(&vwin, &l_vwin);
2964 error = copyout(&l_vwin, (void *) args->arg,
2965 sizeof(l_vwin));
2966 }
2967 fdrop(fp, td);
2968 return (error);
2969
2970 case LINUX_VIDIOCSWIN:
2971 error = fget(td, args->fd,
2972 &cap_ioctl_rights, &fp);
2973 if (error != 0)
2974 return (error);
2975 error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
2976 if (error) {
2977 fdrop(fp, td);
2978 return (error);
2979 }
2980 linux_to_bsd_v4l_window(&l_vwin, &vwin);
2981 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2982 error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
2983 if (error) {
2984 fdrop(fp, td);
2985 return (error);
2986 }
2987 #endif
2988 error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
2989 fdrop(fp, td);
2990 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2991 linux_v4l_cliplist_free(&vwin);
2992 #endif
2993 return (error);
2994
2995 case LINUX_VIDIOCGFBUF:
2996 error = fget(td, args->fd,
2997 &cap_ioctl_rights, &fp);
2998 if (error != 0)
2999 return (error);
3000 error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
3001 if (!error) {
3002 bsd_to_linux_v4l_buffer(&vbuf, &l_vbuf);
3003 error = copyout(&l_vbuf, (void *) args->arg,
3004 sizeof(l_vbuf));
3005 }
3006 fdrop(fp, td);
3007 return (error);
3008
3009 case LINUX_VIDIOCSFBUF:
3010 error = fget(td, args->fd,
3011 &cap_ioctl_rights, &fp);
3012 if (error != 0)
3013 return (error);
3014 error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
3015 if (error) {
3016 fdrop(fp, td);
3017 return (error);
3018 }
3019 linux_to_bsd_v4l_buffer(&l_vbuf, &vbuf);
3020 error = fo_ioctl(fp, VIDIOCSFBUF, &vbuf, td->td_ucred, td);
3021 fdrop(fp, td);
3022 return (error);
3023
3024 case LINUX_VIDIOCKEY: args->cmd = VIDIOCKEY; break;
3025 case LINUX_VIDIOCGFREQ: args->cmd = VIDIOCGFREQ; break;
3026 case LINUX_VIDIOCSFREQ: args->cmd = VIDIOCSFREQ; break;
3027 case LINUX_VIDIOCGAUDIO: args->cmd = VIDIOCGAUDIO; break;
3028 case LINUX_VIDIOCSAUDIO: args->cmd = VIDIOCSAUDIO; break;
3029 case LINUX_VIDIOCSYNC: args->cmd = VIDIOCSYNC; break;
3030 case LINUX_VIDIOCMCAPTURE: args->cmd = VIDIOCMCAPTURE; break;
3031 case LINUX_VIDIOCGMBUF: args->cmd = VIDIOCGMBUF; break;
3032 case LINUX_VIDIOCGUNIT: args->cmd = VIDIOCGUNIT; break;
3033 case LINUX_VIDIOCGCAPTURE: args->cmd = VIDIOCGCAPTURE; break;
3034 case LINUX_VIDIOCSCAPTURE: args->cmd = VIDIOCSCAPTURE; break;
3035 case LINUX_VIDIOCSPLAYMODE: args->cmd = VIDIOCSPLAYMODE; break;
3036 case LINUX_VIDIOCSWRITEMODE: args->cmd = VIDIOCSWRITEMODE; break;
3037 case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break;
3038
3039 case LINUX_VIDIOCSMICROCODE:
3040 error = fget(td, args->fd,
3041 &cap_ioctl_rights, &fp);
3042 if (error != 0)
3043 return (error);
3044 error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
3045 if (error) {
3046 fdrop(fp, td);
3047 return (error);
3048 }
3049 linux_to_bsd_v4l_code(&l_vcode, &vcode);
3050 error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td);
3051 fdrop(fp, td);
3052 return (error);
3053
3054 case LINUX_VIDIOCGVBIFMT: args->cmd = VIDIOCGVBIFMT; break;
3055 case LINUX_VIDIOCSVBIFMT: args->cmd = VIDIOCSVBIFMT; break;
3056 default: return (ENOIOCTL);
3057 }
3058
3059 error = sys_ioctl(td, (struct ioctl_args *)args);
3060 return (error);
3061 }
3062
3063 /*
3064 * Special ioctl handler
3065 */
3066 static int
linux_ioctl_special(struct thread * td,struct linux_ioctl_args * args)3067 linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
3068 {
3069 int error;
3070
3071 switch (args->cmd) {
3072 case LINUX_SIOCGIFADDR:
3073 args->cmd = SIOCGIFADDR;
3074 error = sys_ioctl(td, (struct ioctl_args *)args);
3075 break;
3076 case LINUX_SIOCSIFADDR:
3077 args->cmd = SIOCSIFADDR;
3078 error = sys_ioctl(td, (struct ioctl_args *)args);
3079 break;
3080 case LINUX_SIOCGIFFLAGS:
3081 args->cmd = SIOCGIFFLAGS;
3082 error = sys_ioctl(td, (struct ioctl_args *)args);
3083 break;
3084 default:
3085 error = ENOIOCTL;
3086 }
3087
3088 return (error);
3089 }
3090
3091 static int
linux_to_bsd_v4l2_standard(struct l_v4l2_standard * lvstd,struct v4l2_standard * vstd)3092 linux_to_bsd_v4l2_standard(struct l_v4l2_standard *lvstd, struct v4l2_standard *vstd)
3093 {
3094 vstd->index = lvstd->index;
3095 vstd->id = lvstd->id;
3096 CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3097 memcpy(vstd->name, lvstd->name, sizeof(vstd->name));
3098 vstd->frameperiod = lvstd->frameperiod;
3099 vstd->framelines = lvstd->framelines;
3100 CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3101 memcpy(vstd->reserved, lvstd->reserved, sizeof(vstd->reserved));
3102 return (0);
3103 }
3104
3105 static int
bsd_to_linux_v4l2_standard(struct v4l2_standard * vstd,struct l_v4l2_standard * lvstd)3106 bsd_to_linux_v4l2_standard(struct v4l2_standard *vstd, struct l_v4l2_standard *lvstd)
3107 {
3108 lvstd->index = vstd->index;
3109 lvstd->id = vstd->id;
3110 CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3111 memcpy(lvstd->name, vstd->name, sizeof(lvstd->name));
3112 lvstd->frameperiod = vstd->frameperiod;
3113 lvstd->framelines = vstd->framelines;
3114 CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3115 memcpy(lvstd->reserved, vstd->reserved, sizeof(lvstd->reserved));
3116 return (0);
3117 }
3118
3119 static int
linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer * lvb,struct v4l2_buffer * vb)3120 linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer *lvb, struct v4l2_buffer *vb)
3121 {
3122 vb->index = lvb->index;
3123 vb->type = lvb->type;
3124 vb->bytesused = lvb->bytesused;
3125 vb->flags = lvb->flags;
3126 vb->field = lvb->field;
3127 vb->timestamp.tv_sec = lvb->timestamp.tv_sec;
3128 vb->timestamp.tv_usec = lvb->timestamp.tv_usec;
3129 memcpy(&vb->timecode, &lvb->timecode, sizeof (lvb->timecode));
3130 vb->sequence = lvb->sequence;
3131 vb->memory = lvb->memory;
3132 if (lvb->memory == V4L2_MEMORY_USERPTR)
3133 /* possible pointer size conversion */
3134 vb->m.userptr = (unsigned long)PTRIN(lvb->m.userptr);
3135 else
3136 vb->m.offset = lvb->m.offset;
3137 vb->length = lvb->length;
3138 vb->input = lvb->input;
3139 vb->reserved = lvb->reserved;
3140 return (0);
3141 }
3142
3143 static int
bsd_to_linux_v4l2_buffer(struct v4l2_buffer * vb,struct l_v4l2_buffer * lvb)3144 bsd_to_linux_v4l2_buffer(struct v4l2_buffer *vb, struct l_v4l2_buffer *lvb)
3145 {
3146 lvb->index = vb->index;
3147 lvb->type = vb->type;
3148 lvb->bytesused = vb->bytesused;
3149 lvb->flags = vb->flags;
3150 lvb->field = vb->field;
3151 lvb->timestamp.tv_sec = vb->timestamp.tv_sec;
3152 lvb->timestamp.tv_usec = vb->timestamp.tv_usec;
3153 memcpy(&lvb->timecode, &vb->timecode, sizeof (vb->timecode));
3154 lvb->sequence = vb->sequence;
3155 lvb->memory = vb->memory;
3156 if (vb->memory == V4L2_MEMORY_USERPTR)
3157 /* possible pointer size conversion */
3158 lvb->m.userptr = PTROUT(vb->m.userptr);
3159 else
3160 lvb->m.offset = vb->m.offset;
3161 lvb->length = vb->length;
3162 lvb->input = vb->input;
3163 lvb->reserved = vb->reserved;
3164 return (0);
3165 }
3166
3167 static int
linux_to_bsd_v4l2_format(struct l_v4l2_format * lvf,struct v4l2_format * vf)3168 linux_to_bsd_v4l2_format(struct l_v4l2_format *lvf, struct v4l2_format *vf)
3169 {
3170 vf->type = lvf->type;
3171 if (lvf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
3172 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3173 || lvf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3174 #endif
3175 )
3176 /*
3177 * XXX TODO - needs 32 -> 64 bit conversion:
3178 * (unused by webcams?)
3179 */
3180 return (EINVAL);
3181 memcpy(&vf->fmt, &lvf->fmt, sizeof(vf->fmt));
3182 return (0);
3183 }
3184
3185 static int
bsd_to_linux_v4l2_format(struct v4l2_format * vf,struct l_v4l2_format * lvf)3186 bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf)
3187 {
3188 lvf->type = vf->type;
3189 if (vf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
3190 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3191 || vf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3192 #endif
3193 )
3194 /*
3195 * XXX TODO - needs 32 -> 64 bit conversion:
3196 * (unused by webcams?)
3197 */
3198 return (EINVAL);
3199 memcpy(&lvf->fmt, &vf->fmt, sizeof(vf->fmt));
3200 return (0);
3201 }
3202 static int
linux_ioctl_v4l2(struct thread * td,struct linux_ioctl_args * args)3203 linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
3204 {
3205 struct file *fp;
3206 int error;
3207 struct v4l2_format vformat;
3208 struct l_v4l2_format l_vformat;
3209 struct v4l2_standard vstd;
3210 struct l_v4l2_standard l_vstd;
3211 struct l_v4l2_buffer l_vbuf;
3212 struct v4l2_buffer vbuf;
3213 struct v4l2_input vinp;
3214
3215 switch (args->cmd & 0xffff) {
3216 case LINUX_VIDIOC_RESERVED:
3217 case LINUX_VIDIOC_LOG_STATUS:
3218 if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID)
3219 return (ENOIOCTL);
3220 args->cmd = (args->cmd & 0xffff) | IOC_VOID;
3221 break;
3222
3223 case LINUX_VIDIOC_OVERLAY:
3224 case LINUX_VIDIOC_STREAMON:
3225 case LINUX_VIDIOC_STREAMOFF:
3226 case LINUX_VIDIOC_S_STD:
3227 case LINUX_VIDIOC_S_TUNER:
3228 case LINUX_VIDIOC_S_AUDIO:
3229 case LINUX_VIDIOC_S_AUDOUT:
3230 case LINUX_VIDIOC_S_MODULATOR:
3231 case LINUX_VIDIOC_S_FREQUENCY:
3232 case LINUX_VIDIOC_S_CROP:
3233 case LINUX_VIDIOC_S_JPEGCOMP:
3234 case LINUX_VIDIOC_S_PRIORITY:
3235 case LINUX_VIDIOC_DBG_S_REGISTER:
3236 case LINUX_VIDIOC_S_HW_FREQ_SEEK:
3237 case LINUX_VIDIOC_SUBSCRIBE_EVENT:
3238 case LINUX_VIDIOC_UNSUBSCRIBE_EVENT:
3239 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN;
3240 break;
3241
3242 case LINUX_VIDIOC_QUERYCAP:
3243 case LINUX_VIDIOC_G_STD:
3244 case LINUX_VIDIOC_G_AUDIO:
3245 case LINUX_VIDIOC_G_INPUT:
3246 case LINUX_VIDIOC_G_OUTPUT:
3247 case LINUX_VIDIOC_G_AUDOUT:
3248 case LINUX_VIDIOC_G_JPEGCOMP:
3249 case LINUX_VIDIOC_QUERYSTD:
3250 case LINUX_VIDIOC_G_PRIORITY:
3251 case LINUX_VIDIOC_QUERY_DV_PRESET:
3252 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT;
3253 break;
3254
3255 case LINUX_VIDIOC_ENUM_FMT:
3256 case LINUX_VIDIOC_REQBUFS:
3257 case LINUX_VIDIOC_G_PARM:
3258 case LINUX_VIDIOC_S_PARM:
3259 case LINUX_VIDIOC_G_CTRL:
3260 case LINUX_VIDIOC_S_CTRL:
3261 case LINUX_VIDIOC_G_TUNER:
3262 case LINUX_VIDIOC_QUERYCTRL:
3263 case LINUX_VIDIOC_QUERYMENU:
3264 case LINUX_VIDIOC_S_INPUT:
3265 case LINUX_VIDIOC_S_OUTPUT:
3266 case LINUX_VIDIOC_ENUMOUTPUT:
3267 case LINUX_VIDIOC_G_MODULATOR:
3268 case LINUX_VIDIOC_G_FREQUENCY:
3269 case LINUX_VIDIOC_CROPCAP:
3270 case LINUX_VIDIOC_G_CROP:
3271 case LINUX_VIDIOC_ENUMAUDIO:
3272 case LINUX_VIDIOC_ENUMAUDOUT:
3273 case LINUX_VIDIOC_G_SLICED_VBI_CAP:
3274 #ifdef VIDIOC_ENUM_FRAMESIZES
3275 case LINUX_VIDIOC_ENUM_FRAMESIZES:
3276 case LINUX_VIDIOC_ENUM_FRAMEINTERVALS:
3277 case LINUX_VIDIOC_ENCODER_CMD:
3278 case LINUX_VIDIOC_TRY_ENCODER_CMD:
3279 #endif
3280 case LINUX_VIDIOC_DBG_G_REGISTER:
3281 case LINUX_VIDIOC_DBG_G_CHIP_IDENT:
3282 case LINUX_VIDIOC_ENUM_DV_PRESETS:
3283 case LINUX_VIDIOC_S_DV_PRESET:
3284 case LINUX_VIDIOC_G_DV_PRESET:
3285 case LINUX_VIDIOC_S_DV_TIMINGS:
3286 case LINUX_VIDIOC_G_DV_TIMINGS:
3287 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
3288 break;
3289
3290 case LINUX_VIDIOC_G_FMT:
3291 case LINUX_VIDIOC_S_FMT:
3292 case LINUX_VIDIOC_TRY_FMT:
3293 error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
3294 if (error)
3295 return (error);
3296 error = fget(td, args->fd,
3297 &cap_ioctl_rights, &fp);
3298 if (error)
3299 return (error);
3300 if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
3301 error = EINVAL;
3302 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_G_FMT)
3303 error = fo_ioctl(fp, VIDIOC_G_FMT, &vformat,
3304 td->td_ucred, td);
3305 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_S_FMT)
3306 error = fo_ioctl(fp, VIDIOC_S_FMT, &vformat,
3307 td->td_ucred, td);
3308 else
3309 error = fo_ioctl(fp, VIDIOC_TRY_FMT, &vformat,
3310 td->td_ucred, td);
3311 bsd_to_linux_v4l2_format(&vformat, &l_vformat);
3312 if (error == 0)
3313 error = copyout(&l_vformat, (void *)args->arg,
3314 sizeof(l_vformat));
3315 fdrop(fp, td);
3316 return (error);
3317
3318 case LINUX_VIDIOC_ENUMSTD:
3319 error = copyin((void *)args->arg, &l_vstd, sizeof(l_vstd));
3320 if (error)
3321 return (error);
3322 linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
3323 error = fget(td, args->fd,
3324 &cap_ioctl_rights, &fp);
3325 if (error)
3326 return (error);
3327 error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
3328 td->td_ucred, td);
3329 if (error) {
3330 fdrop(fp, td);
3331 return (error);
3332 }
3333 bsd_to_linux_v4l2_standard(&vstd, &l_vstd);
3334 error = copyout(&l_vstd, (void *)args->arg, sizeof(l_vstd));
3335 fdrop(fp, td);
3336 return (error);
3337
3338 case LINUX_VIDIOC_ENUMINPUT:
3339 /*
3340 * The Linux struct l_v4l2_input differs only in size,
3341 * it has no padding at the end.
3342 */
3343 error = copyin((void *)args->arg, &vinp,
3344 sizeof(struct l_v4l2_input));
3345 if (error != 0)
3346 return (error);
3347 error = fget(td, args->fd,
3348 &cap_ioctl_rights, &fp);
3349 if (error != 0)
3350 return (error);
3351 error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
3352 td->td_ucred, td);
3353 if (error) {
3354 fdrop(fp, td);
3355 return (error);
3356 }
3357 error = copyout(&vinp, (void *)args->arg,
3358 sizeof(struct l_v4l2_input));
3359 fdrop(fp, td);
3360 return (error);
3361
3362 case LINUX_VIDIOC_QUERYBUF:
3363 case LINUX_VIDIOC_QBUF:
3364 case LINUX_VIDIOC_DQBUF:
3365 error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
3366 if (error)
3367 return (error);
3368 error = fget(td, args->fd,
3369 &cap_ioctl_rights, &fp);
3370 if (error)
3371 return (error);
3372 linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
3373 if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
3374 error = fo_ioctl(fp, VIDIOC_QUERYBUF, &vbuf,
3375 td->td_ucred, td);
3376 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_QBUF)
3377 error = fo_ioctl(fp, VIDIOC_QBUF, &vbuf,
3378 td->td_ucred, td);
3379 else
3380 error = fo_ioctl(fp, VIDIOC_DQBUF, &vbuf,
3381 td->td_ucred, td);
3382 bsd_to_linux_v4l2_buffer(&vbuf, &l_vbuf);
3383 if (error == 0)
3384 error = copyout(&l_vbuf, (void *)args->arg,
3385 sizeof(l_vbuf));
3386 fdrop(fp, td);
3387 return (error);
3388
3389 /*
3390 * XXX TODO - these need 32 -> 64 bit conversion:
3391 * (are any of them needed for webcams?)
3392 */
3393 case LINUX_VIDIOC_G_FBUF:
3394 case LINUX_VIDIOC_S_FBUF:
3395
3396 case LINUX_VIDIOC_G_EXT_CTRLS:
3397 case LINUX_VIDIOC_S_EXT_CTRLS:
3398 case LINUX_VIDIOC_TRY_EXT_CTRLS:
3399
3400 case LINUX_VIDIOC_DQEVENT:
3401
3402 default: return (ENOIOCTL);
3403 }
3404
3405 error = sys_ioctl(td, (struct ioctl_args *)args);
3406 return (error);
3407 }
3408
3409 /*
3410 * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros
3411 * instead of USB* ones. This lets us to provide correct values for cmd.
3412 * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone.
3413 */
3414 static int
linux_ioctl_fbsd_usb(struct thread * td,struct linux_ioctl_args * args)3415 linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args)
3416 {
3417 int error;
3418
3419 error = 0;
3420 switch (args->cmd) {
3421 case FBSD_LUSB_DEVICEENUMERATE:
3422 args->cmd = USB_DEVICEENUMERATE;
3423 break;
3424 case FBSD_LUSB_DEV_QUIRK_ADD:
3425 args->cmd = USB_DEV_QUIRK_ADD;
3426 break;
3427 case FBSD_LUSB_DEV_QUIRK_GET:
3428 args->cmd = USB_DEV_QUIRK_GET;
3429 break;
3430 case FBSD_LUSB_DEV_QUIRK_REMOVE:
3431 args->cmd = USB_DEV_QUIRK_REMOVE;
3432 break;
3433 case FBSD_LUSB_DO_REQUEST:
3434 args->cmd = USB_DO_REQUEST;
3435 break;
3436 case FBSD_LUSB_FS_CLEAR_STALL_SYNC:
3437 args->cmd = USB_FS_CLEAR_STALL_SYNC;
3438 break;
3439 case FBSD_LUSB_FS_CLOSE:
3440 args->cmd = USB_FS_CLOSE;
3441 break;
3442 case FBSD_LUSB_FS_COMPLETE:
3443 args->cmd = USB_FS_COMPLETE;
3444 break;
3445 case FBSD_LUSB_FS_INIT:
3446 args->cmd = USB_FS_INIT;
3447 break;
3448 case FBSD_LUSB_FS_OPEN:
3449 args->cmd = USB_FS_OPEN;
3450 break;
3451 case FBSD_LUSB_FS_START:
3452 args->cmd = USB_FS_START;
3453 break;
3454 case FBSD_LUSB_FS_STOP:
3455 args->cmd = USB_FS_STOP;
3456 break;
3457 case FBSD_LUSB_FS_UNINIT:
3458 args->cmd = USB_FS_UNINIT;
3459 break;
3460 case FBSD_LUSB_GET_CONFIG:
3461 args->cmd = USB_GET_CONFIG;
3462 break;
3463 case FBSD_LUSB_GET_DEVICEINFO:
3464 args->cmd = USB_GET_DEVICEINFO;
3465 break;
3466 case FBSD_LUSB_GET_DEVICE_DESC:
3467 args->cmd = USB_GET_DEVICE_DESC;
3468 break;
3469 case FBSD_LUSB_GET_FULL_DESC:
3470 args->cmd = USB_GET_FULL_DESC;
3471 break;
3472 case FBSD_LUSB_GET_IFACE_DRIVER:
3473 args->cmd = USB_GET_IFACE_DRIVER;
3474 break;
3475 case FBSD_LUSB_GET_PLUGTIME:
3476 args->cmd = USB_GET_PLUGTIME;
3477 break;
3478 case FBSD_LUSB_GET_POWER_MODE:
3479 args->cmd = USB_GET_POWER_MODE;
3480 break;
3481 case FBSD_LUSB_GET_REPORT_DESC:
3482 args->cmd = USB_GET_REPORT_DESC;
3483 break;
3484 case FBSD_LUSB_GET_REPORT_ID:
3485 args->cmd = USB_GET_REPORT_ID;
3486 break;
3487 case FBSD_LUSB_GET_TEMPLATE:
3488 args->cmd = USB_GET_TEMPLATE;
3489 break;
3490 case FBSD_LUSB_IFACE_DRIVER_ACTIVE:
3491 args->cmd = USB_IFACE_DRIVER_ACTIVE;
3492 break;
3493 case FBSD_LUSB_IFACE_DRIVER_DETACH:
3494 args->cmd = USB_IFACE_DRIVER_DETACH;
3495 break;
3496 case FBSD_LUSB_QUIRK_NAME_GET:
3497 args->cmd = USB_QUIRK_NAME_GET;
3498 break;
3499 case FBSD_LUSB_READ_DIR:
3500 args->cmd = USB_READ_DIR;
3501 break;
3502 case FBSD_LUSB_SET_ALTINTERFACE:
3503 args->cmd = USB_SET_ALTINTERFACE;
3504 break;
3505 case FBSD_LUSB_SET_CONFIG:
3506 args->cmd = USB_SET_CONFIG;
3507 break;
3508 case FBSD_LUSB_SET_IMMED:
3509 args->cmd = USB_SET_IMMED;
3510 break;
3511 case FBSD_LUSB_SET_POWER_MODE:
3512 args->cmd = USB_SET_POWER_MODE;
3513 break;
3514 case FBSD_LUSB_SET_TEMPLATE:
3515 args->cmd = USB_SET_TEMPLATE;
3516 break;
3517 case FBSD_LUSB_FS_OPEN_STREAM:
3518 args->cmd = USB_FS_OPEN_STREAM;
3519 break;
3520 case FBSD_LUSB_GET_DEV_PORT_PATH:
3521 args->cmd = USB_GET_DEV_PORT_PATH;
3522 break;
3523 case FBSD_LUSB_GET_POWER_USAGE:
3524 args->cmd = USB_GET_POWER_USAGE;
3525 break;
3526 case FBSD_LUSB_DEVICESTATS:
3527 args->cmd = USB_DEVICESTATS;
3528 break;
3529 default:
3530 error = ENOIOCTL;
3531 }
3532 if (error != ENOIOCTL)
3533 error = sys_ioctl(td, (struct ioctl_args *)args);
3534 return (error);
3535 }
3536
3537 /*
3538 * Some evdev ioctls must be translated.
3539 * - EVIOCGMTSLOTS is a IOC_READ ioctl on Linux although it has input data
3540 * (must be IOC_INOUT on FreeBSD).
3541 * - On Linux, EVIOCGRAB, EVIOCREVOKE and EVIOCRMFF are defined as _IOW with
3542 * an int argument. You don't pass an int pointer to the ioctl(), however,
3543 * but just the int directly. On FreeBSD, they are defined as _IOWINT for
3544 * this to work.
3545 */
3546 static int
linux_ioctl_evdev(struct thread * td,struct linux_ioctl_args * args)3547 linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args)
3548 {
3549 struct file *fp;
3550 clockid_t clock;
3551 int error;
3552
3553 args->cmd = SETDIR(args->cmd);
3554
3555 switch (args->cmd) {
3556 case (EVIOCGRAB & ~IOC_DIRMASK) | IOC_IN:
3557 args->cmd = EVIOCGRAB;
3558 break;
3559 case (EVIOCREVOKE & ~IOC_DIRMASK) | IOC_IN:
3560 args->cmd = EVIOCREVOKE;
3561 break;
3562 case (EVIOCRMFF & ~IOC_DIRMASK) | IOC_IN:
3563 args->cmd = EVIOCRMFF;
3564 break;
3565 case EVIOCSCLOCKID: {
3566 error = copyin(PTRIN(args->arg), &clock, sizeof(clock));
3567 if (error != 0)
3568 return (error);
3569 if (clock & ~(LINUX_IOCTL_EVDEV_CLK))
3570 return (EINVAL);
3571 error = linux_to_native_clockid(&clock, clock);
3572 if (error != 0)
3573 return (error);
3574
3575 error = fget(td, args->fd,
3576 &cap_ioctl_rights, &fp);
3577 if (error != 0)
3578 return (error);
3579
3580 error = fo_ioctl(fp, EVIOCSCLOCKID, &clock, td->td_ucred, td);
3581 fdrop(fp, td);
3582 return (error);
3583 }
3584 default:
3585 break;
3586 }
3587
3588 if (IOCBASECMD(args->cmd) ==
3589 ((EVIOCGMTSLOTS(0) & ~IOC_DIRMASK) | IOC_OUT))
3590 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
3591
3592 return (sys_ioctl(td, (struct ioctl_args *)args));
3593 }
3594
3595 static int
linux_ioctl_kcov(struct thread * td,struct linux_ioctl_args * args)3596 linux_ioctl_kcov(struct thread *td, struct linux_ioctl_args *args)
3597 {
3598 int error;
3599
3600 error = 0;
3601 switch (args->cmd & 0xffff) {
3602 case LINUX_KCOV_INIT_TRACE:
3603 args->cmd = KIOSETBUFSIZE;
3604 break;
3605 case LINUX_KCOV_ENABLE:
3606 args->cmd = KIOENABLE;
3607 if (args->arg == 0)
3608 args->arg = KCOV_MODE_TRACE_PC;
3609 else if (args->arg == 1)
3610 args->arg = KCOV_MODE_TRACE_CMP;
3611 else
3612 error = EINVAL;
3613 break;
3614 case LINUX_KCOV_DISABLE:
3615 args->cmd = KIODISABLE;
3616 break;
3617 default:
3618 error = ENOTTY;
3619 break;
3620 }
3621
3622 if (error == 0)
3623 error = sys_ioctl(td, (struct ioctl_args *)args);
3624 return (error);
3625 }
3626
3627 #ifndef COMPAT_LINUX32
3628 static int
linux_ioctl_nvme(struct thread * td,struct linux_ioctl_args * args)3629 linux_ioctl_nvme(struct thread *td, struct linux_ioctl_args *args)
3630 {
3631
3632 /*
3633 * The NVMe drivers for namespace and controller implement these
3634 * commands using their native format. All the others are not
3635 * implemented yet.
3636 */
3637 switch (args->cmd & 0xffff) {
3638 case LINUX_NVME_IOCTL_ID:
3639 args->cmd = NVME_IOCTL_ID;
3640 break;
3641 case LINUX_NVME_IOCTL_RESET:
3642 args->cmd = NVME_IOCTL_RESET;
3643 break;
3644 case LINUX_NVME_IOCTL_ADMIN_CMD:
3645 args->cmd = NVME_IOCTL_ADMIN_CMD;
3646 break;
3647 case LINUX_NVME_IOCTL_IO_CMD:
3648 args->cmd = NVME_IOCTL_IO_CMD;
3649 break;
3650 default:
3651 return (ENODEV);
3652 }
3653 return (sys_ioctl(td, (struct ioctl_args *)args));
3654 }
3655 #endif
3656
3657 static int
linux_ioctl_i2c(struct thread * td,struct linux_ioctl_args * args)3658 linux_ioctl_i2c(struct thread *td, struct linux_ioctl_args *args)
3659 {
3660 struct linux_i2c_rdwr_data lrdwr;
3661 struct linux_i2c_msg *lmsgs = NULL;
3662 struct iic_rdwr_data rdwr;
3663 struct iic_msg *msgs = NULL;
3664 struct file *fp;
3665 iic_linux_rdwr_t *linux_rdwr;
3666 l_ulong funcs;
3667 uint16_t lflags;
3668 uint8_t addr;
3669 int error;
3670 l_uint i;
3671
3672 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
3673 if (error != 0)
3674 return (error);
3675
3676 linux_rdwr = NULL;
3677 if (fp->f_type == DTYPE_VNODE && fp->f_vnode != NULL &&
3678 fp->f_vnode->v_rdev != NULL)
3679 linux_rdwr = (iic_linux_rdwr_t *)fp->f_vnode->v_rdev->si_drv2;
3680
3681 switch (args->cmd & 0xffff) {
3682 case LINUX_I2C_RETRIES:
3683 case LINUX_I2C_TIMEOUT:
3684 case LINUX_I2C_PEC:
3685 error = 0;
3686 break;
3687 case LINUX_I2C_TENBIT:
3688 error = (args->arg == 0) ? 0 : ENOTSUP;
3689 break;
3690 case LINUX_I2C_FUNCS:
3691 funcs = LINUX_I2C_FUNC_I2C | LINUX_I2C_FUNC_NOSTART;
3692 error = copyout(&funcs, (void *)args->arg, sizeof(funcs));
3693 break;
3694 case LINUX_I2C_SLAVE:
3695 case LINUX_I2C_SLAVE_FORCE:
3696 if (args->arg > 0x7f) {
3697 error = EINVAL;
3698 break;
3699 }
3700 addr = (uint8_t)(args->arg << 1);
3701 error = fo_ioctl(fp, I2CSADDR, (caddr_t)&addr, td->td_ucred, td);
3702 break;
3703 case LINUX_I2C_RDWR:
3704 error = copyin((void *)args->arg, &lrdwr, sizeof(lrdwr));
3705 if (error != 0)
3706 break;
3707 if (lrdwr.nmsgs > IIC_RDRW_MAX_MSGS) {
3708 error = EINVAL;
3709 break;
3710 }
3711 lmsgs = malloc(sizeof(*lmsgs) * lrdwr.nmsgs, M_TEMP, M_WAITOK);
3712 msgs = malloc(sizeof(*msgs) * lrdwr.nmsgs, M_TEMP, M_WAITOK);
3713 error = copyin((void *)(uintptr_t)lrdwr.msgs, lmsgs,
3714 sizeof(*lmsgs) * lrdwr.nmsgs);
3715 if (error != 0)
3716 break;
3717 for (i = 0; i < lrdwr.nmsgs; i++) {
3718 lflags = lmsgs[i].flags;
3719 if (lmsgs[i].addr > 0x7f || (lflags & LINUX_I2C_M_TEN) != 0) {
3720 error = ENOTSUP;
3721 break;
3722 }
3723 if ((lflags & ~(LINUX_I2C_M_RD | LINUX_I2C_M_NOSTART)) != 0) {
3724 error = ENOTSUP;
3725 break;
3726 }
3727 msgs[i].slave = lmsgs[i].addr << 1;
3728 msgs[i].flags = (lflags & LINUX_I2C_M_RD) ? IIC_M_RD : IIC_M_WR;
3729 if ((lflags & LINUX_I2C_M_NOSTART) != 0)
3730 msgs[i].flags |= IIC_M_NOSTART;
3731 msgs[i].len = lmsgs[i].len;
3732 msgs[i].buf = (uint8_t *)(uintptr_t)lmsgs[i].buf;
3733 }
3734 if (error == 0) {
3735 if (linux_rdwr == NULL) {
3736 error = ENOTTY;
3737 } else {
3738 rdwr.msgs = msgs;
3739 rdwr.nmsgs = lrdwr.nmsgs;
3740 error = linux_rdwr(fp, &rdwr, fp->f_flag, td);
3741 if (error == 0)
3742 td->td_retval[0] = lrdwr.nmsgs;
3743 }
3744 }
3745 break;
3746 case LINUX_I2C_SMBUS:
3747 default:
3748 error = ENOTSUP;
3749 break;
3750 }
3751 free(msgs, M_TEMP);
3752 free(lmsgs, M_TEMP);
3753 fdrop(fp, td);
3754 return (error);
3755 }
3756
3757 static int
linux_ioctl_hidraw(struct thread * td,struct linux_ioctl_args * args)3758 linux_ioctl_hidraw(struct thread *td, struct linux_ioctl_args *args)
3759 {
3760 int len = (args->cmd & 0x3fff0000) >> 16;
3761 if (len > 8192)
3762 return (EINVAL);
3763
3764 switch (args->cmd & 0xffff) {
3765 case LINUX_HIDIOCGRDESCSIZE:
3766 args->cmd = HIDIOCGRDESCSIZE;
3767 break;
3768 case LINUX_HIDIOCGRDESC:
3769 args->cmd = HIDIOCGRDESC;
3770 break;
3771 case LINUX_HIDIOCGRAWINFO:
3772 args->cmd = HIDIOCGRAWINFO;
3773 break;
3774 case LINUX_HIDIOCGRAWNAME:
3775 args->cmd = HIDIOCGRAWNAME(len);
3776 break;
3777 case LINUX_HIDIOCGRAWPHYS:
3778 args->cmd = HIDIOCGRAWPHYS(len);
3779 break;
3780 case LINUX_HIDIOCSFEATURE:
3781 args->cmd = HIDIOCSFEATURE(len);
3782 break;
3783 case LINUX_HIDIOCGFEATURE:
3784 args->cmd = HIDIOCGFEATURE(len);
3785 break;
3786 case LINUX_HIDIOCGRAWUNIQ:
3787 args->cmd = HIDIOCGRAWUNIQ(len);
3788 break;
3789 case LINUX_HIDIOCSINPUT:
3790 args->cmd = HIDIOCSINPUT(len);
3791 break;
3792 case LINUX_HIDIOCGINPUT:
3793 args->cmd = HIDIOCGINPUT(len);
3794 break;
3795 case LINUX_HIDIOCSOUTPUT:
3796 args->cmd = HIDIOCSOUTPUT(len);
3797 break;
3798 case LINUX_HIDIOCGOUTPUT:
3799 args->cmd = HIDIOCGOUTPUT(len);
3800 break;
3801 }
3802
3803 return (sys_ioctl(td, (struct ioctl_args *)args));
3804 }
3805
3806 /*
3807 * main ioctl syscall function
3808 */
3809
3810 static int
linux_ioctl_fallback(struct thread * td,struct linux_ioctl_args * args)3811 linux_ioctl_fallback(struct thread *td, struct linux_ioctl_args *args)
3812 {
3813 struct file *fp;
3814 struct linux_ioctl_handler_element *he;
3815 int error, cmd;
3816
3817 error = fget(td, args->fd, &cap_ioctl_rights, &fp);
3818 if (error != 0)
3819 return (error);
3820 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
3821 fdrop(fp, td);
3822 return (EBADF);
3823 }
3824
3825 /* Iterate over the ioctl handlers */
3826 cmd = args->cmd & 0xffff;
3827 sx_slock(&linux_ioctl_sx);
3828 mtx_lock(&Giant);
3829 #ifdef COMPAT_LINUX32
3830 TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
3831 if (cmd >= he->low && cmd <= he->high) {
3832 error = (*he->func)(td, args);
3833 if (error != ENOIOCTL) {
3834 mtx_unlock(&Giant);
3835 sx_sunlock(&linux_ioctl_sx);
3836 fdrop(fp, td);
3837 return (error);
3838 }
3839 }
3840 }
3841 #endif
3842 TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3843 if (cmd >= he->low && cmd <= he->high) {
3844 error = (*he->func)(td, args);
3845 if (error != ENOIOCTL) {
3846 mtx_unlock(&Giant);
3847 sx_sunlock(&linux_ioctl_sx);
3848 fdrop(fp, td);
3849 return (error);
3850 }
3851 }
3852 }
3853 mtx_unlock(&Giant);
3854 sx_sunlock(&linux_ioctl_sx);
3855 fdrop(fp, td);
3856
3857 switch (args->cmd & 0xffff) {
3858 case LINUX_BTRFS_IOC_CLONE:
3859 case LINUX_F2FS_IOC_GET_FEATURES:
3860 case LINUX_FS_IOC_FIEMAP:
3861 return (ENOTSUP);
3862
3863 default:
3864 linux_msg(td, "%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
3865 __func__, args->fd, args->cmd,
3866 (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
3867 break;
3868 }
3869
3870 return (EINVAL);
3871 }
3872
3873 int
linux_ioctl(struct thread * td,struct linux_ioctl_args * args)3874 linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
3875 {
3876 struct linux_ioctl_handler *handler;
3877 int error, cmd, i;
3878
3879 cmd = args->cmd & 0xffff;
3880
3881 /*
3882 * array of ioctls known at compilation time. Elides a lot of work on
3883 * each call compared to the list variant. Everything frequently used
3884 * should be moved here.
3885 *
3886 * Arguably the magic creating the list should create an array instead.
3887 *
3888 * For now just a linear scan.
3889 */
3890 for (i = 0; i < nitems(linux_ioctls); i++) {
3891 handler = &linux_ioctls[i];
3892 if (cmd >= handler->low && cmd <= handler->high) {
3893 error = (*handler->func)(td, args);
3894 if (error != ENOIOCTL) {
3895 return (error);
3896 }
3897 }
3898 }
3899 return (linux_ioctl_fallback(td, args));
3900 }
3901
3902 int
linux_ioctl_register_handler(struct linux_ioctl_handler * h)3903 linux_ioctl_register_handler(struct linux_ioctl_handler *h)
3904 {
3905 struct linux_ioctl_handler_element *he, *cur;
3906
3907 if (h == NULL || h->func == NULL)
3908 return (EINVAL);
3909
3910 /*
3911 * Reuse the element if the handler is already on the list, otherwise
3912 * create a new element.
3913 */
3914 sx_xlock(&linux_ioctl_sx);
3915 TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3916 if (he->func == h->func)
3917 break;
3918 }
3919 if (he == NULL) {
3920 he = malloc(sizeof(*he),
3921 M_LINUX, M_WAITOK);
3922 he->func = h->func;
3923 } else
3924 TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
3925
3926 /* Initialize range information. */
3927 he->low = h->low;
3928 he->high = h->high;
3929 he->span = h->high - h->low + 1;
3930
3931 /* Add the element to the list, sorted on span. */
3932 TAILQ_FOREACH(cur, &linux_ioctl_handlers, list) {
3933 if (cur->span > he->span) {
3934 TAILQ_INSERT_BEFORE(cur, he, list);
3935 sx_xunlock(&linux_ioctl_sx);
3936 return (0);
3937 }
3938 }
3939 TAILQ_INSERT_TAIL(&linux_ioctl_handlers, he, list);
3940 sx_xunlock(&linux_ioctl_sx);
3941
3942 return (0);
3943 }
3944
3945 int
linux_ioctl_unregister_handler(struct linux_ioctl_handler * h)3946 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
3947 {
3948 struct linux_ioctl_handler_element *he;
3949
3950 if (h == NULL || h->func == NULL)
3951 return (EINVAL);
3952
3953 sx_xlock(&linux_ioctl_sx);
3954 TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3955 if (he->func == h->func) {
3956 TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
3957 sx_xunlock(&linux_ioctl_sx);
3958 free(he, M_LINUX);
3959 return (0);
3960 }
3961 }
3962 sx_xunlock(&linux_ioctl_sx);
3963
3964 return (EINVAL);
3965 }
3966
3967 #ifdef COMPAT_LINUX32
3968 int
linux32_ioctl_register_handler(struct linux_ioctl_handler * h)3969 linux32_ioctl_register_handler(struct linux_ioctl_handler *h)
3970 {
3971 struct linux_ioctl_handler_element *he, *cur;
3972
3973 if (h == NULL || h->func == NULL)
3974 return (EINVAL);
3975
3976 /*
3977 * Reuse the element if the handler is already on the list, otherwise
3978 * create a new element.
3979 */
3980 sx_xlock(&linux_ioctl_sx);
3981 TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
3982 if (he->func == h->func)
3983 break;
3984 }
3985 if (he == NULL) {
3986 he = malloc(sizeof(*he), M_LINUX, M_WAITOK);
3987 he->func = h->func;
3988 } else
3989 TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
3990
3991 /* Initialize range information. */
3992 he->low = h->low;
3993 he->high = h->high;
3994 he->span = h->high - h->low + 1;
3995
3996 /* Add the element to the list, sorted on span. */
3997 TAILQ_FOREACH(cur, &linux32_ioctl_handlers, list) {
3998 if (cur->span > he->span) {
3999 TAILQ_INSERT_BEFORE(cur, he, list);
4000 sx_xunlock(&linux_ioctl_sx);
4001 return (0);
4002 }
4003 }
4004 TAILQ_INSERT_TAIL(&linux32_ioctl_handlers, he, list);
4005 sx_xunlock(&linux_ioctl_sx);
4006
4007 return (0);
4008 }
4009
4010 int
linux32_ioctl_unregister_handler(struct linux_ioctl_handler * h)4011 linux32_ioctl_unregister_handler(struct linux_ioctl_handler *h)
4012 {
4013 struct linux_ioctl_handler_element *he;
4014
4015 if (h == NULL || h->func == NULL)
4016 return (EINVAL);
4017
4018 sx_xlock(&linux_ioctl_sx);
4019 TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
4020 if (he->func == h->func) {
4021 TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
4022 sx_xunlock(&linux_ioctl_sx);
4023 free(he, M_LINUX);
4024 return (0);
4025 }
4026 }
4027 sx_xunlock(&linux_ioctl_sx);
4028
4029 return (EINVAL);
4030 }
4031 #endif
4032