1 /*-
2 * Copyright (c) 1994-1995 Søren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "opt_compat.h"
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: src/sys/compat/linux/linux_ioctl.c,v 1.146 2008/12/02 21:37:28 bz Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/sysproto.h>
37 #include <sys/cdio.h>
38 #include <sys/dvdio.h>
39 #include <sys/conf.h>
40 #include <sys/disk.h>
41 #include <sys/consio.h>
42 #include <sys/ctype.h>
43 #include <sys/fcntl.h>
44 #include <sys/file.h>
45 #include <sys/filedesc.h>
46 #include <sys/filio.h>
47 #include <sys/kbio.h>
48 #include <sys/kernel.h>
49 #include <sys/linker_set.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/proc.h>
53 #include <sys/sbuf.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56 #include <sys/soundcard.h>
57 #include <sys/stdint.h>
58 #include <sys/sx.h>
59 #include <sys/tty.h>
60 #include <sys/uio.h>
61 #include <sys/vimage.h>
62
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_types.h>
66 #include <net/vnet.h>
67
68 #ifdef COMPAT_LINUX32
69 #include <machine/../linux32/linux.h>
70 #include <machine/../linux32/linux32_proto.h>
71 #else
72 #include <machine/../linux/linux.h>
73 #include <machine/../linux/linux_proto.h>
74 #endif
75
76 #include <compat/linux/linux_ioctl.h>
77 #include <compat/linux/linux_mib.h>
78 #include <compat/linux/linux_util.h>
79
80 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ);
81
82 static linux_ioctl_function_t linux_ioctl_cdrom;
83 static linux_ioctl_function_t linux_ioctl_vfat;
84 static linux_ioctl_function_t linux_ioctl_console;
85 static linux_ioctl_function_t linux_ioctl_hdio;
86 static linux_ioctl_function_t linux_ioctl_disk;
87 static linux_ioctl_function_t linux_ioctl_socket;
88 static linux_ioctl_function_t linux_ioctl_sound;
89 static linux_ioctl_function_t linux_ioctl_termio;
90 static linux_ioctl_function_t linux_ioctl_private;
91 static linux_ioctl_function_t linux_ioctl_drm;
92 static linux_ioctl_function_t linux_ioctl_sg;
93 static linux_ioctl_function_t linux_ioctl_special;
94
95 static struct linux_ioctl_handler cdrom_handler =
96 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
97 static struct linux_ioctl_handler vfat_handler =
98 { linux_ioctl_vfat, LINUX_IOCTL_VFAT_MIN, LINUX_IOCTL_VFAT_MAX };
99 static struct linux_ioctl_handler console_handler =
100 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX };
101 static struct linux_ioctl_handler hdio_handler =
102 { linux_ioctl_hdio, LINUX_IOCTL_HDIO_MIN, LINUX_IOCTL_HDIO_MAX };
103 static struct linux_ioctl_handler disk_handler =
104 { linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX };
105 static struct linux_ioctl_handler socket_handler =
106 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX };
107 static struct linux_ioctl_handler sound_handler =
108 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
109 static struct linux_ioctl_handler termio_handler =
110 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
111 static struct linux_ioctl_handler private_handler =
112 { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
113 static struct linux_ioctl_handler drm_handler =
114 { linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX };
115 static struct linux_ioctl_handler sg_handler =
116 { linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX };
117
118 DATA_SET(linux_ioctl_handler_set, cdrom_handler);
119 DATA_SET(linux_ioctl_handler_set, vfat_handler);
120 DATA_SET(linux_ioctl_handler_set, console_handler);
121 DATA_SET(linux_ioctl_handler_set, hdio_handler);
122 DATA_SET(linux_ioctl_handler_set, disk_handler);
123 DATA_SET(linux_ioctl_handler_set, socket_handler);
124 DATA_SET(linux_ioctl_handler_set, sound_handler);
125 DATA_SET(linux_ioctl_handler_set, termio_handler);
126 DATA_SET(linux_ioctl_handler_set, private_handler);
127 DATA_SET(linux_ioctl_handler_set, drm_handler);
128 DATA_SET(linux_ioctl_handler_set, sg_handler);
129
130 struct handler_element
131 {
132 TAILQ_ENTRY(handler_element) list;
133 int (*func)(struct thread *, struct linux_ioctl_args *);
134 int low, high, span;
135 };
136
137 static TAILQ_HEAD(, handler_element) handlers =
138 TAILQ_HEAD_INITIALIZER(handlers);
139 static struct sx linux_ioctl_sx;
140 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "linux ioctl handlers");
141
142 /*
143 * hdio related ioctls for VMWare support
144 */
145
146 struct linux_hd_geometry {
147 u_int8_t heads;
148 u_int8_t sectors;
149 u_int16_t cylinders;
150 u_int32_t start;
151 };
152
153 struct linux_hd_big_geometry {
154 u_int8_t heads;
155 u_int8_t sectors;
156 u_int32_t cylinders;
157 u_int32_t start;
158 };
159
160 static int
161 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
162 {
163 struct file *fp;
164 int error;
165 u_int sectorsize, fwcylinders, fwheads, fwsectors;
166 off_t mediasize, bytespercyl;
167
168 if ((error = fget(td, args->fd, &fp)) != 0)
169 return (error);
170 switch (args->cmd & 0xffff) {
171 case LINUX_HDIO_GET_GEO:
172 case LINUX_HDIO_GET_GEO_BIG:
173 error = fo_ioctl(fp, DIOCGMEDIASIZE,
174 (caddr_t)&mediasize, td->td_ucred, td);
175 if (!error)
176 error = fo_ioctl(fp, DIOCGSECTORSIZE,
177 (caddr_t)§orsize, td->td_ucred, td);
178 if (!error)
179 error = fo_ioctl(fp, DIOCGFWHEADS,
180 (caddr_t)&fwheads, td->td_ucred, td);
181 if (!error)
182 error = fo_ioctl(fp, DIOCGFWSECTORS,
183 (caddr_t)&fwsectors, td->td_ucred, td);
184 /*
185 * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
186 * so pretend that GEOM always says 0. This is NOT VALID
187 * for slices or partitions, only the per-disk raw devices.
188 */
189
190 fdrop(fp, td);
191 if (error)
192 return (error);
193 /*
194 * 1. Calculate the number of bytes in a cylinder,
195 * given the firmware's notion of heads and sectors
196 * per cylinder.
197 * 2. Calculate the number of cylinders, given the total
198 * size of the media.
199 * All internal calculations should have 64-bit precision.
200 */
201 bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
202 fwcylinders = mediasize / bytespercyl;
203 #if defined(DEBUG)
204 linux_msg(td, "HDIO_GET_GEO: mediasize %jd, c/h/s %d/%d/%d, "
205 "bpc %jd",
206 (intmax_t)mediasize, fwcylinders, fwheads, fwsectors,
207 (intmax_t)bytespercyl);
208 #endif
209 if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
210 struct linux_hd_geometry hdg;
211
212 hdg.cylinders = fwcylinders;
213 hdg.heads = fwheads;
214 hdg.sectors = fwsectors;
215 hdg.start = 0;
216 error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
217 } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
218 struct linux_hd_big_geometry hdbg;
219
220 hdbg.cylinders = fwcylinders;
221 hdbg.heads = fwheads;
222 hdbg.sectors = fwsectors;
223 hdbg.start = 0;
224 error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
225 }
226 return (error);
227 break;
228 default:
229 /* XXX */
230 linux_msg(td,
231 "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
232 args->fd, (int)(args->cmd & 0xffff),
233 (int)(args->cmd & 0xff00) >> 8,
234 (int)(args->cmd & 0xff));
235 break;
236 }
237 fdrop(fp, td);
238 return (ENOIOCTL);
239 }
240
241 static int
242 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
243 {
244 struct file *fp;
245 int error;
246 u_int sectorsize;
247 off_t mediasize;
248
249 if ((error = fget(td, args->fd, &fp)) != 0)
250 return (error);
251 switch (args->cmd & 0xffff) {
252 case LINUX_BLKGETSIZE:
253 error = fo_ioctl(fp, DIOCGSECTORSIZE,
254 (caddr_t)§orsize, td->td_ucred, td);
255 if (!error)
256 error = fo_ioctl(fp, DIOCGMEDIASIZE,
257 (caddr_t)&mediasize, td->td_ucred, td);
258 fdrop(fp, td);
259 if (error)
260 return (error);
261 sectorsize = mediasize / sectorsize;
262 /*
263 * XXX: How do we know we return the right size of integer ?
264 */
265 return (copyout(§orsize, (void *)args->arg,
266 sizeof(sectorsize)));
267 break;
268 }
269 fdrop(fp, td);
270 return (ENOIOCTL);
271 }
272
273 /*
274 * termio related ioctls
275 */
276
277 struct linux_termio {
278 unsigned short c_iflag;
279 unsigned short c_oflag;
280 unsigned short c_cflag;
281 unsigned short c_lflag;
282 unsigned char c_line;
283 unsigned char c_cc[LINUX_NCC];
284 };
285
286 struct linux_termios {
287 unsigned int c_iflag;
288 unsigned int c_oflag;
289 unsigned int c_cflag;
290 unsigned int c_lflag;
291 unsigned char c_line;
292 unsigned char c_cc[LINUX_NCCS];
293 };
294
295 struct linux_winsize {
296 unsigned short ws_row, ws_col;
297 unsigned short ws_xpixel, ws_ypixel;
298 };
299
300 struct speedtab {
301 int sp_speed; /* Speed. */
302 int sp_code; /* Code. */
303 };
304
305 static struct speedtab sptab[] = {
306 { B0, LINUX_B0 }, { B50, LINUX_B50 },
307 { B75, LINUX_B75 }, { B110, LINUX_B110 },
308 { B134, LINUX_B134 }, { B150, LINUX_B150 },
309 { B200, LINUX_B200 }, { B300, LINUX_B300 },
310 { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
311 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
312 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
313 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
314 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
315 {-1, -1 }
316 };
317
318 struct linux_serial_struct {
319 int type;
320 int line;
321 int port;
322 int irq;
323 int flags;
324 int xmit_fifo_size;
325 int custom_divisor;
326 int baud_base;
327 unsigned short close_delay;
328 char reserved_char[2];
329 int hub6;
330 unsigned short closing_wait;
331 unsigned short closing_wait2;
332 int reserved[4];
333 };
334
335 static int
336 linux_to_bsd_speed(int code, struct speedtab *table)
337 {
338 for ( ; table->sp_code != -1; table++)
339 if (table->sp_code == code)
340 return (table->sp_speed);
341 return -1;
342 }
343
344 static int
345 bsd_to_linux_speed(int speed, struct speedtab *table)
346 {
347 for ( ; table->sp_speed != -1; table++)
348 if (table->sp_speed == speed)
349 return (table->sp_code);
350 return -1;
351 }
352
353 static void
354 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
355 {
356 int i;
357
358 #ifdef DEBUG
359 if (ldebug(ioctl)) {
360 printf("LINUX: BSD termios structure (input):\n");
361 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
362 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
363 bios->c_ispeed, bios->c_ospeed);
364 printf("c_cc ");
365 for (i=0; i<NCCS; i++)
366 printf("%02x ", bios->c_cc[i]);
367 printf("\n");
368 }
369 #endif
370
371 lios->c_iflag = 0;
372 if (bios->c_iflag & IGNBRK)
373 lios->c_iflag |= LINUX_IGNBRK;
374 if (bios->c_iflag & BRKINT)
375 lios->c_iflag |= LINUX_BRKINT;
376 if (bios->c_iflag & IGNPAR)
377 lios->c_iflag |= LINUX_IGNPAR;
378 if (bios->c_iflag & PARMRK)
379 lios->c_iflag |= LINUX_PARMRK;
380 if (bios->c_iflag & INPCK)
381 lios->c_iflag |= LINUX_INPCK;
382 if (bios->c_iflag & ISTRIP)
383 lios->c_iflag |= LINUX_ISTRIP;
384 if (bios->c_iflag & INLCR)
385 lios->c_iflag |= LINUX_INLCR;
386 if (bios->c_iflag & IGNCR)
387 lios->c_iflag |= LINUX_IGNCR;
388 if (bios->c_iflag & ICRNL)
389 lios->c_iflag |= LINUX_ICRNL;
390 if (bios->c_iflag & IXON)
391 lios->c_iflag |= LINUX_IXON;
392 if (bios->c_iflag & IXANY)
393 lios->c_iflag |= LINUX_IXANY;
394 if (bios->c_iflag & IXOFF)
395 lios->c_iflag |= LINUX_IXOFF;
396 if (bios->c_iflag & IMAXBEL)
397 lios->c_iflag |= LINUX_IMAXBEL;
398
399 lios->c_oflag = 0;
400 if (bios->c_oflag & OPOST)
401 lios->c_oflag |= LINUX_OPOST;
402 if (bios->c_oflag & ONLCR)
403 lios->c_oflag |= LINUX_ONLCR;
404 if (bios->c_oflag & TAB3)
405 lios->c_oflag |= LINUX_XTABS;
406
407 lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
408 lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
409 if (bios->c_cflag & CSTOPB)
410 lios->c_cflag |= LINUX_CSTOPB;
411 if (bios->c_cflag & CREAD)
412 lios->c_cflag |= LINUX_CREAD;
413 if (bios->c_cflag & PARENB)
414 lios->c_cflag |= LINUX_PARENB;
415 if (bios->c_cflag & PARODD)
416 lios->c_cflag |= LINUX_PARODD;
417 if (bios->c_cflag & HUPCL)
418 lios->c_cflag |= LINUX_HUPCL;
419 if (bios->c_cflag & CLOCAL)
420 lios->c_cflag |= LINUX_CLOCAL;
421 if (bios->c_cflag & CRTSCTS)
422 lios->c_cflag |= LINUX_CRTSCTS;
423
424 lios->c_lflag = 0;
425 if (bios->c_lflag & ISIG)
426 lios->c_lflag |= LINUX_ISIG;
427 if (bios->c_lflag & ICANON)
428 lios->c_lflag |= LINUX_ICANON;
429 if (bios->c_lflag & ECHO)
430 lios->c_lflag |= LINUX_ECHO;
431 if (bios->c_lflag & ECHOE)
432 lios->c_lflag |= LINUX_ECHOE;
433 if (bios->c_lflag & ECHOK)
434 lios->c_lflag |= LINUX_ECHOK;
435 if (bios->c_lflag & ECHONL)
436 lios->c_lflag |= LINUX_ECHONL;
437 if (bios->c_lflag & NOFLSH)
438 lios->c_lflag |= LINUX_NOFLSH;
439 if (bios->c_lflag & TOSTOP)
440 lios->c_lflag |= LINUX_TOSTOP;
441 if (bios->c_lflag & ECHOCTL)
442 lios->c_lflag |= LINUX_ECHOCTL;
443 if (bios->c_lflag & ECHOPRT)
444 lios->c_lflag |= LINUX_ECHOPRT;
445 if (bios->c_lflag & ECHOKE)
446 lios->c_lflag |= LINUX_ECHOKE;
447 if (bios->c_lflag & FLUSHO)
448 lios->c_lflag |= LINUX_FLUSHO;
449 if (bios->c_lflag & PENDIN)
450 lios->c_lflag |= LINUX_PENDIN;
451 if (bios->c_lflag & IEXTEN)
452 lios->c_lflag |= LINUX_IEXTEN;
453
454 for (i=0; i<LINUX_NCCS; i++)
455 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
456 lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
457 lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
458 lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
459 lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
460 lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
461 lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
462 lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
463 lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
464 lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
465 lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
466 lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
467 lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
468 lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
469 lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
470 lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
471 lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
472
473 for (i=0; i<LINUX_NCCS; i++) {
474 if (i != LINUX_VMIN && i != LINUX_VTIME &&
475 lios->c_cc[i] == _POSIX_VDISABLE)
476 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
477 }
478 lios->c_line = 0;
479
480 #ifdef DEBUG
481 if (ldebug(ioctl)) {
482 printf("LINUX: LINUX termios structure (output):\n");
483 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
484 lios->c_iflag, lios->c_oflag, lios->c_cflag,
485 lios->c_lflag, (int)lios->c_line);
486 printf("c_cc ");
487 for (i=0; i<LINUX_NCCS; i++)
488 printf("%02x ", lios->c_cc[i]);
489 printf("\n");
490 }
491 #endif
492 }
493
494 static void
495 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
496 {
497 int i;
498
499 #ifdef DEBUG
500 if (ldebug(ioctl)) {
501 printf("LINUX: LINUX termios structure (input):\n");
502 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
503 lios->c_iflag, lios->c_oflag, lios->c_cflag,
504 lios->c_lflag, (int)lios->c_line);
505 printf("c_cc ");
506 for (i=0; i<LINUX_NCCS; i++)
507 printf("%02x ", lios->c_cc[i]);
508 printf("\n");
509 }
510 #endif
511
512 bios->c_iflag = 0;
513 if (lios->c_iflag & LINUX_IGNBRK)
514 bios->c_iflag |= IGNBRK;
515 if (lios->c_iflag & LINUX_BRKINT)
516 bios->c_iflag |= BRKINT;
517 if (lios->c_iflag & LINUX_IGNPAR)
518 bios->c_iflag |= IGNPAR;
519 if (lios->c_iflag & LINUX_PARMRK)
520 bios->c_iflag |= PARMRK;
521 if (lios->c_iflag & LINUX_INPCK)
522 bios->c_iflag |= INPCK;
523 if (lios->c_iflag & LINUX_ISTRIP)
524 bios->c_iflag |= ISTRIP;
525 if (lios->c_iflag & LINUX_INLCR)
526 bios->c_iflag |= INLCR;
527 if (lios->c_iflag & LINUX_IGNCR)
528 bios->c_iflag |= IGNCR;
529 if (lios->c_iflag & LINUX_ICRNL)
530 bios->c_iflag |= ICRNL;
531 if (lios->c_iflag & LINUX_IXON)
532 bios->c_iflag |= IXON;
533 if (lios->c_iflag & LINUX_IXANY)
534 bios->c_iflag |= IXANY;
535 if (lios->c_iflag & LINUX_IXOFF)
536 bios->c_iflag |= IXOFF;
537 if (lios->c_iflag & LINUX_IMAXBEL)
538 bios->c_iflag |= IMAXBEL;
539
540 bios->c_oflag = 0;
541 if (lios->c_oflag & LINUX_OPOST)
542 bios->c_oflag |= OPOST;
543 if (lios->c_oflag & LINUX_ONLCR)
544 bios->c_oflag |= ONLCR;
545 if (lios->c_oflag & LINUX_XTABS)
546 bios->c_oflag |= TAB3;
547
548 bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
549 if (lios->c_cflag & LINUX_CSTOPB)
550 bios->c_cflag |= CSTOPB;
551 if (lios->c_cflag & LINUX_CREAD)
552 bios->c_cflag |= CREAD;
553 if (lios->c_cflag & LINUX_PARENB)
554 bios->c_cflag |= PARENB;
555 if (lios->c_cflag & LINUX_PARODD)
556 bios->c_cflag |= PARODD;
557 if (lios->c_cflag & LINUX_HUPCL)
558 bios->c_cflag |= HUPCL;
559 if (lios->c_cflag & LINUX_CLOCAL)
560 bios->c_cflag |= CLOCAL;
561 if (lios->c_cflag & LINUX_CRTSCTS)
562 bios->c_cflag |= CRTSCTS;
563
564 bios->c_lflag = 0;
565 if (lios->c_lflag & LINUX_ISIG)
566 bios->c_lflag |= ISIG;
567 if (lios->c_lflag & LINUX_ICANON)
568 bios->c_lflag |= ICANON;
569 if (lios->c_lflag & LINUX_ECHO)
570 bios->c_lflag |= ECHO;
571 if (lios->c_lflag & LINUX_ECHOE)
572 bios->c_lflag |= ECHOE;
573 if (lios->c_lflag & LINUX_ECHOK)
574 bios->c_lflag |= ECHOK;
575 if (lios->c_lflag & LINUX_ECHONL)
576 bios->c_lflag |= ECHONL;
577 if (lios->c_lflag & LINUX_NOFLSH)
578 bios->c_lflag |= NOFLSH;
579 if (lios->c_lflag & LINUX_TOSTOP)
580 bios->c_lflag |= TOSTOP;
581 if (lios->c_lflag & LINUX_ECHOCTL)
582 bios->c_lflag |= ECHOCTL;
583 if (lios->c_lflag & LINUX_ECHOPRT)
584 bios->c_lflag |= ECHOPRT;
585 if (lios->c_lflag & LINUX_ECHOKE)
586 bios->c_lflag |= ECHOKE;
587 if (lios->c_lflag & LINUX_FLUSHO)
588 bios->c_lflag |= FLUSHO;
589 if (lios->c_lflag & LINUX_PENDIN)
590 bios->c_lflag |= PENDIN;
591 if (lios->c_lflag & LINUX_IEXTEN)
592 bios->c_lflag |= IEXTEN;
593
594 for (i=0; i<NCCS; i++)
595 bios->c_cc[i] = _POSIX_VDISABLE;
596 bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
597 bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
598 bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
599 bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
600 bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
601 bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
602 bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
603 bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
604 bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
605 bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
606 bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
607 bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
608 bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
609 bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
610 bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
611 bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
612
613 for (i=0; i<NCCS; i++) {
614 if (i != VMIN && i != VTIME &&
615 bios->c_cc[i] == LINUX_POSIX_VDISABLE)
616 bios->c_cc[i] = _POSIX_VDISABLE;
617 }
618
619 bios->c_ispeed = bios->c_ospeed =
620 linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
621
622 #ifdef DEBUG
623 if (ldebug(ioctl)) {
624 printf("LINUX: BSD termios structure (output):\n");
625 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
626 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
627 bios->c_ispeed, bios->c_ospeed);
628 printf("c_cc ");
629 for (i=0; i<NCCS; i++)
630 printf("%02x ", bios->c_cc[i]);
631 printf("\n");
632 }
633 #endif
634 }
635
636 static void
637 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
638 {
639 struct linux_termios lios;
640
641 bsd_to_linux_termios(bios, &lios);
642 lio->c_iflag = lios.c_iflag;
643 lio->c_oflag = lios.c_oflag;
644 lio->c_cflag = lios.c_cflag;
645 lio->c_lflag = lios.c_lflag;
646 lio->c_line = lios.c_line;
647 memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
648 }
649
650 static void
651 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
652 {
653 struct linux_termios lios;
654 int i;
655
656 lios.c_iflag = lio->c_iflag;
657 lios.c_oflag = lio->c_oflag;
658 lios.c_cflag = lio->c_cflag;
659 lios.c_lflag = lio->c_lflag;
660 for (i=LINUX_NCC; i<LINUX_NCCS; i++)
661 lios.c_cc[i] = LINUX_POSIX_VDISABLE;
662 memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
663 linux_to_bsd_termios(&lios, bios);
664 }
665
666 static int
667 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
668 {
669 struct termios bios;
670 struct linux_termios lios;
671 struct linux_termio lio;
672 struct file *fp;
673 int error;
674
675 if ((error = fget(td, args->fd, &fp)) != 0)
676 return (error);
677
678 switch (args->cmd & 0xffff) {
679
680 case LINUX_TCGETS:
681 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
682 td);
683 if (error)
684 break;
685 bsd_to_linux_termios(&bios, &lios);
686 error = copyout(&lios, (void *)args->arg, sizeof(lios));
687 break;
688
689 case LINUX_TCSETS:
690 error = copyin((void *)args->arg, &lios, sizeof(lios));
691 if (error)
692 break;
693 linux_to_bsd_termios(&lios, &bios);
694 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
695 td));
696 break;
697
698 case LINUX_TCSETSW:
699 error = copyin((void *)args->arg, &lios, sizeof(lios));
700 if (error)
701 break;
702 linux_to_bsd_termios(&lios, &bios);
703 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
704 td));
705 break;
706
707 case LINUX_TCSETSF:
708 error = copyin((void *)args->arg, &lios, sizeof(lios));
709 if (error)
710 break;
711 linux_to_bsd_termios(&lios, &bios);
712 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
713 td));
714 break;
715
716 case LINUX_TCGETA:
717 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
718 td);
719 if (error)
720 break;
721 bsd_to_linux_termio(&bios, &lio);
722 error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
723 break;
724
725 case LINUX_TCSETA:
726 error = copyin((void *)args->arg, &lio, sizeof(lio));
727 if (error)
728 break;
729 linux_to_bsd_termio(&lio, &bios);
730 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
731 td));
732 break;
733
734 case LINUX_TCSETAW:
735 error = copyin((void *)args->arg, &lio, sizeof(lio));
736 if (error)
737 break;
738 linux_to_bsd_termio(&lio, &bios);
739 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
740 td));
741 break;
742
743 case LINUX_TCSETAF:
744 error = copyin((void *)args->arg, &lio, sizeof(lio));
745 if (error)
746 break;
747 linux_to_bsd_termio(&lio, &bios);
748 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
749 td));
750 break;
751
752 /* LINUX_TCSBRK */
753
754 case LINUX_TCXONC: {
755 switch (args->arg) {
756 case LINUX_TCOOFF:
757 args->cmd = TIOCSTOP;
758 break;
759 case LINUX_TCOON:
760 args->cmd = TIOCSTART;
761 break;
762 case LINUX_TCIOFF:
763 case LINUX_TCION: {
764 int c;
765 struct write_args wr;
766 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
767 td->td_ucred, td);
768 if (error)
769 break;
770 fdrop(fp, td);
771 c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
772 c = bios.c_cc[c];
773 if (c != _POSIX_VDISABLE) {
774 wr.fd = args->fd;
775 wr.buf = &c;
776 wr.nbyte = sizeof(c);
777 return (write(td, &wr));
778 } else
779 return (0);
780 }
781 default:
782 fdrop(fp, td);
783 return (EINVAL);
784 }
785 args->arg = 0;
786 error = (ioctl(td, (struct ioctl_args *)args));
787 break;
788 }
789
790 case LINUX_TCFLSH: {
791 int val;
792 switch (args->arg) {
793 case LINUX_TCIFLUSH:
794 val = FREAD;
795 break;
796 case LINUX_TCOFLUSH:
797 val = FWRITE;
798 break;
799 case LINUX_TCIOFLUSH:
800 val = FREAD | FWRITE;
801 break;
802 default:
803 fdrop(fp, td);
804 return (EINVAL);
805 }
806 error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
807 break;
808 }
809
810 case LINUX_TIOCEXCL:
811 args->cmd = TIOCEXCL;
812 error = (ioctl(td, (struct ioctl_args *)args));
813 break;
814
815 case LINUX_TIOCNXCL:
816 args->cmd = TIOCNXCL;
817 error = (ioctl(td, (struct ioctl_args *)args));
818 break;
819
820 case LINUX_TIOCSCTTY:
821 args->cmd = TIOCSCTTY;
822 error = (ioctl(td, (struct ioctl_args *)args));
823 break;
824
825 case LINUX_TIOCGPGRP:
826 args->cmd = TIOCGPGRP;
827 error = (ioctl(td, (struct ioctl_args *)args));
828 break;
829
830 case LINUX_TIOCSPGRP:
831 args->cmd = TIOCSPGRP;
832 error = (ioctl(td, (struct ioctl_args *)args));
833 break;
834
835 /* LINUX_TIOCOUTQ */
836 /* LINUX_TIOCSTI */
837
838 case LINUX_TIOCGWINSZ:
839 args->cmd = TIOCGWINSZ;
840 error = (ioctl(td, (struct ioctl_args *)args));
841 break;
842
843 case LINUX_TIOCSWINSZ:
844 args->cmd = TIOCSWINSZ;
845 error = (ioctl(td, (struct ioctl_args *)args));
846 break;
847
848 case LINUX_TIOCMGET:
849 args->cmd = TIOCMGET;
850 error = (ioctl(td, (struct ioctl_args *)args));
851 break;
852
853 case LINUX_TIOCMBIS:
854 args->cmd = TIOCMBIS;
855 error = (ioctl(td, (struct ioctl_args *)args));
856 break;
857
858 case LINUX_TIOCMBIC:
859 args->cmd = TIOCMBIC;
860 error = (ioctl(td, (struct ioctl_args *)args));
861 break;
862
863 case LINUX_TIOCMSET:
864 args->cmd = TIOCMSET;
865 error = (ioctl(td, (struct ioctl_args *)args));
866 break;
867
868 /* TIOCGSOFTCAR */
869 /* TIOCSSOFTCAR */
870
871 case LINUX_FIONREAD: /* LINUX_TIOCINQ */
872 args->cmd = FIONREAD;
873 error = (ioctl(td, (struct ioctl_args *)args));
874 break;
875
876 /* LINUX_TIOCLINUX */
877
878 case LINUX_TIOCCONS:
879 args->cmd = TIOCCONS;
880 error = (i |