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