[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_ioctl.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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)&sectorsize, 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)&sectorsize, 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(&sectorsize, (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