1 /* $NetBSD: linux_ioctl.c,v 1.9 1995/11/16 18:42:05 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Frank van der Linden 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Frank van der Linden 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/proc.h> 36 #include <sys/systm.h> 37 #include <sys/file.h> 38 #include <sys/filedesc.h> 39 #include <sys/ioctl.h> 40 #include <sys/termios.h> 41 #include <sys/tty.h> 42 #include <sys/socket.h> 43 #include <sys/ioctl.h> 44 #include <sys/mount.h> 45 #include <net/if.h> 46 #include <sys/sockio.h> 47 48 #include <sys/syscallargs.h> 49 50 #include <compat/linux/linux_types.h> 51 #include <compat/linux/linux_ioctl.h> 52 #include <compat/linux/linux_sockio.h> 53 #include <compat/linux/linux_util.h> 54 #include <compat/linux/linux_signal.h> 55 #include <compat/linux/linux_syscallargs.h> 56 57 static speed_t linux_speeds[] = { 58 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 59 9600, 19200, 38400, 57600, 115200 60 }; 61 62 static int linux_spmasks[] = { 63 LINUX_B0, LINUX_B50, LINUX_B75, LINUX_B110, LINUX_B134, LINUX_B150, 64 LINUX_B200, LINUX_B300, LINUX_B600, LINUX_B1200, LINUX_B1800, 65 LINUX_B2400, LINUX_B4800, LINUX_B9600, LINUX_B19200, LINUX_B38400, 66 LINUX_B57600, LINUX_B115200, LINUX_B230400 67 }; 68 69 /* 70 * Deal with termio ioctl cruft. This doesn't look very good.. 71 * XXX too much code duplication, obviously.. 72 * 73 * The conversion routines between Linux and BSD structures assume 74 * that the fields are already filled with the current values, 75 * so that fields present in BSD but not in Linux keep their current 76 * values. 77 */ 78 79 static int 80 linux_termio_to_bsd_termios(lt, bts) 81 register struct linux_termio *lt; 82 register struct termios *bts; 83 { 84 int index; 85 86 bts->c_iflag = 0; 87 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNBRK, IGNBRK); 88 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_BRKINT, BRKINT); 89 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNPAR, IGNPAR); 90 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INPCK, INPCK); 91 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ISTRIP, ISTRIP); 92 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INLCR, INLCR); 93 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNCR, IGNCR); 94 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ICRNL, ICRNL); 95 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXON, IXON); 96 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXANY, IXANY); 97 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXOFF, IXOFF); 98 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IMAXBEL, IMAXBEL); 99 100 bts->c_oflag = 0; 101 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_OPOST, OPOST); 102 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_ONLCR, ONLCR); 103 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_XTABS, OXTABS); 104 105 /* 106 * This could have been: 107 * bts->c_cflag = (lt->c_flag & LINUX_CSIZE) << 4 108 * But who knows, those values might perhaps change one day. 109 */ 110 switch (lt->c_cflag & LINUX_CSIZE) { 111 case LINUX_CS5: 112 bts->c_cflag = CS5; 113 break; 114 case LINUX_CS6: 115 bts->c_cflag = CS6; 116 break; 117 case LINUX_CS7: 118 bts->c_cflag = CS7; 119 break; 120 case LINUX_CS8: 121 bts->c_cflag = CS8; 122 break; 123 } 124 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CSTOPB, CSTOPB); 125 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CREAD, CREAD); 126 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARENB, PARENB); 127 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARODD, PARODD); 128 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_HUPCL, HUPCL); 129 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CLOCAL, CLOCAL); 130 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CRTSCTS, CRTSCTS); 131 132 bts->c_lflag = 0; 133 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ISIG, ISIG); 134 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ICANON, ICANON); 135 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHO, ECHO); 136 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOE, ECHOE); 137 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOK, ECHOK); 138 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHONL, ECHONL); 139 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_NOFLSH, NOFLSH); 140 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_TOSTOP, TOSTOP); 141 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOCTL, ECHOCTL); 142 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOPRT, ECHOPRT); 143 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOKE, ECHOKE); 144 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_FLUSHO, FLUSHO); 145 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_PENDIN, PENDIN); 146 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_IEXTEN, IEXTEN); 147 148 index = lt->c_cflag & LINUX_CBAUD; 149 if (index & LINUX_CBAUDEX) 150 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 151 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 152 153 bts->c_cc[VINTR] = lt->c_cc[LINUX_VINTR]; 154 bts->c_cc[VQUIT] = lt->c_cc[LINUX_VQUIT]; 155 bts->c_cc[VERASE] = lt->c_cc[LINUX_VERASE]; 156 bts->c_cc[VKILL] = lt->c_cc[LINUX_VKILL]; 157 bts->c_cc[VEOF] = lt->c_cc[LINUX_VEOF]; 158 bts->c_cc[VTIME] = lt->c_cc[LINUX_VTIME]; 159 bts->c_cc[VMIN] = lt->c_cc[LINUX_VMIN]; 160 } 161 162 static int 163 bsd_termios_to_linux_termio(bts, lt) 164 register struct termios *bts; 165 register struct linux_termio *lt; 166 { 167 int i, mask; 168 169 lt->c_iflag = 0; 170 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 171 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 172 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 173 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 174 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 175 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 176 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 177 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 178 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 179 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 180 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 181 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 182 183 lt->c_oflag = 0; 184 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 185 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 186 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 187 188 switch (bts->c_cflag & CSIZE) { 189 case CS5: 190 lt->c_cflag = LINUX_CS5; 191 break; 192 case CS6: 193 lt->c_cflag = LINUX_CS6; 194 break; 195 case CS7: 196 lt->c_cflag = LINUX_CS7; 197 break; 198 case CS8: 199 lt->c_cflag = LINUX_CS8; 200 break; 201 } 202 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 203 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 204 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 205 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 206 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 207 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 208 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 209 210 lt->c_lflag = 0; 211 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 212 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 213 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 214 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 215 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 216 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 217 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 218 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 219 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 220 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 221 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 222 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 223 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 224 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 225 226 mask = LINUX_B9600; /* XXX default value should this be 0? */ 227 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 228 if (bts->c_ospeed == linux_speeds[i]) { 229 mask = linux_spmasks[i]; 230 break; 231 } 232 } 233 lt->c_cflag |= mask; 234 235 lt->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 236 lt->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 237 lt->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 238 lt->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 239 lt->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 240 lt->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 241 lt->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 242 lt->c_cc[LINUX_VSWTC] = 0; 243 244 /* XXX should be fixed someday */ 245 lt->c_line = 0; 246 } 247 248 static int 249 linux_termios_to_bsd_termios(lts, bts) 250 register struct linux_termios *lts; 251 register struct termios *bts; 252 { 253 int index; 254 255 bts->c_iflag = 0; 256 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNBRK, IGNBRK); 257 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_BRKINT, BRKINT); 258 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNPAR, IGNPAR); 259 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INPCK, INPCK); 260 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ISTRIP, ISTRIP); 261 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INLCR, INLCR); 262 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNCR, IGNCR); 263 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ICRNL, ICRNL); 264 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXON, IXON); 265 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXANY, IXANY); 266 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXOFF, IXOFF); 267 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IMAXBEL, IMAXBEL); 268 269 bts->c_oflag = 0; 270 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_OPOST, OPOST); 271 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_ONLCR, ONLCR); 272 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_XTABS, OXTABS); 273 274 bts->c_cflag = 0; 275 switch (lts->c_cflag & LINUX_CSIZE) { 276 case LINUX_CS5: 277 bts->c_cflag = CS5; 278 break; 279 case LINUX_CS6: 280 bts->c_cflag = CS6; 281 break; 282 case LINUX_CS7: 283 bts->c_cflag = CS7; 284 break; 285 case LINUX_CS8: 286 bts->c_cflag = CS8; 287 break; 288 } 289 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CSTOPB, CSTOPB); 290 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CREAD, CREAD); 291 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARENB, PARENB); 292 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARODD, PARODD); 293 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_HUPCL, HUPCL); 294 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CLOCAL, CLOCAL); 295 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CRTSCTS, CRTSCTS); 296 297 bts->c_lflag = 0; 298 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ISIG, ISIG); 299 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ICANON, ICANON); 300 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHO, ECHO); 301 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOE, ECHOE); 302 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOK, ECHOK); 303 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHONL, ECHONL); 304 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_NOFLSH, NOFLSH); 305 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_TOSTOP, TOSTOP); 306 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOCTL, ECHOCTL); 307 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOPRT, ECHOPRT); 308 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOKE, ECHOKE); 309 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_FLUSHO, FLUSHO); 310 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_PENDIN, PENDIN); 311 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_IEXTEN, IEXTEN); 312 313 index = lts->c_cflag & LINUX_CBAUD; 314 if (index & LINUX_CBAUDEX) 315 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 316 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 317 318 bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR]; 319 bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT]; 320 bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE]; 321 bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL]; 322 bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF]; 323 bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME]; 324 bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN]; 325 bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL]; 326 bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2]; 327 bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE]; 328 bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP]; 329 bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART]; 330 bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP]; 331 bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT]; 332 bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD]; 333 bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT]; 334 } 335 336 static int 337 bsd_termios_to_linux_termios(bts, lts) 338 register struct termios *bts; 339 register struct linux_termios *lts; 340 { 341 int i, mask; 342 343 lts->c_iflag = 0; 344 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 345 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 346 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 347 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 348 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 349 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 350 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 351 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 352 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 353 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 354 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 355 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 356 357 lts->c_oflag = 0; 358 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 359 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 360 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 361 362 switch (bts->c_cflag & CSIZE) { 363 case CS5: 364 lts->c_cflag = LINUX_CS5; 365 break; 366 case CS6: 367 lts->c_cflag = LINUX_CS6; 368 break; 369 case CS7: 370 lts->c_cflag = LINUX_CS7; 371 break; 372 case CS8: 373 lts->c_cflag = LINUX_CS8; 374 break; 375 } 376 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5); 377 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6); 378 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7); 379 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8); 380 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 381 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 382 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 383 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 384 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 385 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 386 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 387 388 lts->c_lflag = 0; 389 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 390 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 391 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 392 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 393 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 394 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 395 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 396 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 397 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 398 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 399 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 400 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 401 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 402 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 403 404 mask = LINUX_B9600; /* XXX default value */ 405 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 406 if (bts->c_ospeed == linux_speeds[i]) { 407 mask = linux_spmasks[i]; 408 break; 409 } 410 } 411 lts->c_cflag |= mask; 412 413 lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 414 lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 415 lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 416 lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 417 lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 418 lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 419 lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 420 lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL]; 421 lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2]; 422 lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE]; 423 lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP]; 424 lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART]; 425 lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP]; 426 lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT]; 427 lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD]; 428 lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT]; 429 lts->c_cc[LINUX_VSWTC] = 0; 430 431 /* XXX should be fixed someday */ 432 lts->c_line = 0; 433 } 434 435 /* 436 * Most ioctl command are just converted to their NetBSD values, 437 * and passed on. The ones that take structure pointers and (flag) 438 * values need some massaging. This is done the usual way by 439 * allocating stackgap memory, letting the actual ioctl call do its 440 * work their and converting back the data afterwards. 441 */ 442 int 443 linux_sys_ioctl(p, v, retval) 444 register struct proc *p; 445 void *v; 446 register_t *retval; 447 { 448 register struct linux_sys_ioctl_args /* { 449 syscallarg(int) fd; 450 syscallarg(u_long) com; 451 syscallarg(caddr_t) data; 452 } */ *uap = v; 453 int fd; 454 unsigned long com; 455 caddr_t data, sg; 456 struct file *fp; 457 struct filedesc *fdp; 458 struct linux_termio tmplt, *alt; 459 struct linux_termios tmplts, *alts; 460 struct termios tmpbts, *abts; 461 struct sys_ioctl_args ia; 462 int error, idat, *idatp; 463 464 fd = SCARG(&ia, fd) = SCARG(uap, fd); 465 com = SCARG(uap, com); 466 data = SCARG(&ia, data) = SCARG(uap, data); 467 retval[0] = 0; 468 469 fdp = p->p_fd; 470 if ((u_int)fd >= fdp->fd_nfiles || 471 (fp = fdp->fd_ofiles[fd]) == NULL) 472 return (EBADF); 473 474 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 475 return (EBADF); 476 477 sg = stackgap_init(p->p_emul); 478 479 switch (com) { 480 case LINUX_TCGETS: 481 SCARG(&ia, com) = TIOCGETA; 482 abts = stackgap_alloc(&sg, sizeof (*abts)); 483 SCARG(&ia, data) = (caddr_t) abts; 484 if ((error = sys_ioctl(p, &ia, retval)) != 0) 485 return error; 486 if ((error = copyin(abts, &tmpbts, sizeof tmpbts))) 487 return error; 488 bsd_termios_to_linux_termios(&tmpbts, &tmplts); 489 return copyout(&tmplts, data, sizeof tmplts); 490 case LINUX_TCSETS: 491 case LINUX_TCSETSW: 492 case LINUX_TCSETSF: 493 switch (com) { 494 case LINUX_TCSETS: 495 SCARG(&ia, com) = TIOCSETA; 496 break; 497 case LINUX_TCSETSW: 498 SCARG(&ia, com) = TIOCSETAW; 499 break; 500 case LINUX_TCSETSF: 501 SCARG(&ia, com) = TIOCSETAF; 502 break; 503 } 504 if ((error = copyin(data, &tmplts, sizeof tmplts))) 505 return error; 506 abts = stackgap_alloc(&sg, sizeof tmpbts); 507 /* 508 * First fill in all fields, so that we keep the current 509 * values for fields that Linux doesn't know about. 510 */ 511 if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, 512 (caddr_t) &tmpbts, p))) 513 return error; 514 linux_termios_to_bsd_termios(&tmplts, &tmpbts); 515 if ((error = copyout(&tmpbts, abts, sizeof tmpbts))) 516 return error; 517 SCARG(&ia, data) = (caddr_t) abts; 518 return sys_ioctl(p, &ia, retval); 519 case LINUX_TCGETA: 520 SCARG(&ia, com) = TIOCGETA; 521 abts = stackgap_alloc(&sg, sizeof (*abts)); 522 SCARG(&ia, data) = (caddr_t) abts; 523 if ((error = sys_ioctl(p, &ia, retval)) != 0) 524 return error; 525 if ((error = copyin(abts, &tmpbts, sizeof tmpbts))) 526 return error; 527 bsd_termios_to_linux_termio(&tmpbts, &tmplt); 528 return copyout(&tmplt, data, sizeof tmplt); 529 case LINUX_TCSETA: 530 case LINUX_TCSETAW: 531 case LINUX_TCSETAF: 532 switch (com) { 533 case LINUX_TCSETA: 534 SCARG(&ia, com) = TIOCSETA; 535 break; 536 case LINUX_TCSETAW: 537 SCARG(&ia, com) = TIOCSETAW; 538 break; 539 case LINUX_TCSETAF: 540 SCARG(&ia, com) = TIOCSETAF; 541 break; 542 } 543 if ((error = copyin(data, &tmplt, sizeof tmplt))) 544 return error; 545 abts = stackgap_alloc(&sg, sizeof tmpbts); 546 /* 547 * First fill in all fields, so that we keep the current 548 * values for fields that Linux doesn't know about. 549 */ 550 if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, 551 (caddr_t) &tmpbts, p))) 552 return error; 553 linux_termio_to_bsd_termios(&tmplt, &tmpbts); 554 if ((error = copyout(&tmpbts, abts, sizeof tmpbts))) 555 return error; 556 SCARG(&ia, data) = (caddr_t) abts; 557 return sys_ioctl(p, &ia, retval); 558 case LINUX_TIOCSETD: 559 if ((error = copyin(data, (caddr_t) &idat, sizeof idat))) 560 return error; 561 switch (idat) { 562 case LINUX_N_TTY: 563 idat = TTYDISC; 564 break; 565 case LINUX_N_SLIP: 566 idat = SLIPDISC; 567 break; 568 case LINUX_N_PPP: 569 idat = PPPDISC; 570 break; 571 /* 572 * We can't handle the mouse line discipline Linux has. 573 */ 574 case LINUX_N_MOUSE: 575 default: 576 return EINVAL; 577 } 578 579 idatp = (int *) stackgap_alloc(&sg, sizeof (int)); 580 if ((error = copyout(&idat, idatp, sizeof (int)))) 581 return error; 582 SCARG(&ia, com) = TIOCSETD; 583 SCARG(&ia, data) = (caddr_t) idatp; 584 break; 585 case LINUX_TIOCGETD: 586 idatp = (int *) stackgap_alloc(&sg, sizeof (int)); 587 SCARG(&ia, com) = TIOCGETD; 588 SCARG(&ia, data) = (caddr_t) idatp; 589 if ((error = sys_ioctl(p, &ia, retval))) 590 return error; 591 if ((error = copyin(idatp, (caddr_t) &idat, sizeof (int)))) 592 return error; 593 switch (idat) { 594 case TTYDISC: 595 idat = LINUX_N_TTY; 596 break; 597 case SLIPDISC: 598 idat = LINUX_N_SLIP; 599 break; 600 case PPPDISC: 601 idat = LINUX_N_PPP; 602 break; 603 /* 604 * Linux does not have the tablet line discipline. 605 */ 606 case TABLDISC: 607 default: 608 idat = -1; /* XXX What should this be? */ 609 break; 610 } 611 return copyout(&idat, data, sizeof (int)); 612 case LINUX_TIOCGWINSZ: 613 SCARG(&ia, com) = TIOCGWINSZ; 614 break; 615 case LINUX_TIOCSWINSZ: 616 SCARG(&ia, com) = TIOCSWINSZ; 617 break; 618 case LINUX_TIOCGPGRP: 619 SCARG(&ia, com) = TIOCGPGRP; 620 break; 621 case LINUX_TIOCSPGRP: 622 SCARG(&ia, com) = TIOCSPGRP; 623 break; 624 case LINUX_FIONREAD: 625 SCARG(&ia, com) = FIONREAD; 626 break; 627 case LINUX_FIONBIO: 628 SCARG(&ia, com) = FIONBIO; 629 break; 630 case LINUX_FIOASYNC: 631 SCARG(&ia, com) = FIOASYNC; 632 break; 633 case LINUX_TIOCEXCL: 634 SCARG(&ia, com) = TIOCEXCL; 635 break; 636 case LINUX_TIOCNXCL: 637 SCARG(&ia, com) = TIOCNXCL; 638 break; 639 case LINUX_TIOCCONS: 640 SCARG(&ia, com) = TIOCCONS; 641 break; 642 case LINUX_TIOCNOTTY: 643 SCARG(&ia, com) = TIOCNOTTY; 644 break; 645 case LINUX_SIOCADDMULTI: 646 SCARG(&ia, com) = SIOCADDMULTI; 647 break; 648 case LINUX_SIOCDELMULTI: 649 SCARG(&ia, com) = SIOCDELMULTI; 650 break; 651 default: 652 return linux_machdepioctl(p, uap, retval); 653 } 654 655 return sys_ioctl(p, &ia, retval); 656 } 657