1 /* $NetBSD: linux_termios.c,v 1.18 2003/03/21 21:13:53 dsl 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.18 2003/03/21 21:13:53 dsl 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)(struct file *, u_long, void *, 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 error = EBADF; 492 goto out; 493 } 494 495 FILE_USE(fp); 496 497 bsdioctl = fp->f_ops->fo_ioctl; 498 com = SCARG(uap, com); 499 retval[0] = 0; 500 501 switch (com) { 502 case LINUX_TCGETS: 503 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 504 if (error) 505 goto out; 506 bsd_termios_to_linux_termios(&tmpbts, &tmplts); 507 error = copyout(&tmplts, SCARG(uap, data), sizeof tmplts); 508 goto out; 509 case LINUX_TCSETS: 510 case LINUX_TCSETSW: 511 case LINUX_TCSETSF: 512 /* 513 * First fill in all fields, so that we keep the current 514 * values for fields that Linux doesn't know about. 515 */ 516 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 517 if (error) 518 goto out; 519 error = copyin(SCARG(uap, data), &tmplts, sizeof tmplts); 520 if (error) 521 goto out; 522 linux_termios_to_bsd_termios(&tmplts, &tmpbts); 523 switch (com) { 524 case LINUX_TCSETS: 525 com = TIOCSETA; 526 break; 527 case LINUX_TCSETSW: 528 com = TIOCSETAW; 529 break; 530 case LINUX_TCSETSF: 531 com = TIOCSETAF; 532 break; 533 } 534 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, p); 535 goto out; 536 case LINUX_TCGETA: 537 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 538 if (error) 539 goto out; 540 bsd_termios_to_linux_termio(&tmpbts, &tmplt); 541 error = copyout(&tmplt, SCARG(uap, data), sizeof tmplt); 542 goto out; 543 case LINUX_TCSETA: 544 case LINUX_TCSETAW: 545 case LINUX_TCSETAF: 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 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 551 if (error) 552 goto out; 553 error = copyin(SCARG(uap, data), &tmplt, sizeof tmplt); 554 if (error) 555 goto out; 556 linux_termio_to_bsd_termios(&tmplt, &tmpbts); 557 switch (com) { 558 case LINUX_TCSETA: 559 com = TIOCSETA; 560 break; 561 case LINUX_TCSETAW: 562 com = TIOCSETAW; 563 break; 564 case LINUX_TCSETAF: 565 com = TIOCSETAF; 566 break; 567 } 568 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, p); 569 goto out; 570 case LINUX_TCFLSH: 571 switch((u_long)SCARG(uap, data)) { 572 case 0: 573 idat = FREAD; 574 break; 575 case 1: 576 idat = FWRITE; 577 break; 578 case 2: 579 idat = 0; 580 break; 581 default: 582 error = EINVAL; 583 goto out; 584 } 585 error = (*bsdioctl)(fp, TIOCFLUSH, (caddr_t)&idat, p); 586 goto out; 587 case LINUX_TIOCGETD: 588 error = (*bsdioctl)(fp, TIOCGETD, (caddr_t)&idat, p); 589 if (error) 590 goto out; 591 switch (idat) { 592 case TTYDISC: 593 idat = LINUX_N_TTY; 594 break; 595 case SLIPDISC: 596 idat = LINUX_N_SLIP; 597 break; 598 case PPPDISC: 599 idat = LINUX_N_PPP; 600 break; 601 case STRIPDISC: 602 idat = LINUX_N_STRIP; 603 break; 604 /* 605 * Linux does not have the tablet line discipline. 606 */ 607 case TABLDISC: 608 default: 609 idat = -1; /* XXX What should this be? */ 610 break; 611 } 612 error = copyout(&idat, SCARG(uap, data), sizeof idat); 613 goto out; 614 case LINUX_TIOCSETD: 615 error = copyin(SCARG(uap, data), &idat, sizeof idat); 616 if (error) 617 goto out; 618 switch (idat) { 619 case LINUX_N_TTY: 620 idat = TTYDISC; 621 break; 622 case LINUX_N_SLIP: 623 idat = SLIPDISC; 624 break; 625 case LINUX_N_PPP: 626 idat = PPPDISC; 627 break; 628 case LINUX_N_STRIP: 629 idat = STRIPDISC; 630 break; 631 /* 632 * We can't handle the mouse line discipline Linux has. 633 */ 634 case LINUX_N_MOUSE: 635 case LINUX_N_AX25: 636 case LINUX_N_X25: 637 case LINUX_N_6PACK: 638 default: 639 error = EINVAL; 640 goto out; 641 } 642 error = (*bsdioctl)(fp, TIOCSETD, (caddr_t)&idat, p); 643 goto out; 644 case LINUX_TIOCLINUX: 645 error = copyin(SCARG(uap, data), &tioclinux, sizeof tioclinux); 646 if (error != 0) 647 goto out; 648 switch (tioclinux) { 649 case LINUX_TIOCLINUX_KERNMSG: 650 /* 651 * XXX needed to not fail for some things. Could 652 * try to use TIOCCONS, but the char argument 653 * specifies the VT #, not an fd. 654 */ 655 error = 0; 656 goto out; 657 case LINUX_TIOCLINUX_COPY: 658 case LINUX_TIOCLINUX_PASTE: 659 case LINUX_TIOCLINUX_UNBLANK: 660 case LINUX_TIOCLINUX_LOADLUT: 661 case LINUX_TIOCLINUX_READSHIFT: 662 case LINUX_TIOCLINUX_READMOUSE: 663 case LINUX_TIOCLINUX_VESABLANK: 664 case LINUX_TIOCLINUX_CURCONS: /* could use VT_GETACTIVE */ 665 error = EINVAL; 666 goto out; 667 } 668 break; 669 case LINUX_TIOCGWINSZ: 670 SCARG(&ia, com) = TIOCGWINSZ; 671 break; 672 case LINUX_TIOCSWINSZ: 673 SCARG(&ia, com) = TIOCSWINSZ; 674 break; 675 case LINUX_TIOCGPGRP: 676 SCARG(&ia, com) = TIOCGPGRP; 677 break; 678 case LINUX_TIOCSPGRP: 679 SCARG(&ia, com) = TIOCSPGRP; 680 break; 681 case LINUX_FIONREAD: 682 SCARG(&ia, com) = FIONREAD; 683 break; 684 case LINUX_FIONBIO: 685 SCARG(&ia, com) = FIONBIO; 686 break; 687 case LINUX_FIOASYNC: 688 SCARG(&ia, com) = FIOASYNC; 689 break; 690 case LINUX_TIOCEXCL: 691 SCARG(&ia, com) = TIOCEXCL; 692 break; 693 case LINUX_TIOCNXCL: 694 SCARG(&ia, com) = TIOCNXCL; 695 break; 696 case LINUX_TIOCCONS: 697 SCARG(&ia, com) = TIOCCONS; 698 break; 699 case LINUX_TIOCNOTTY: 700 SCARG(&ia, com) = TIOCNOTTY; 701 break; 702 case LINUX_TCSBRK: 703 SCARG(&ia, com) = SCARG(uap, data) ? TIOCDRAIN : TIOCSBRK; 704 break; 705 case LINUX_TIOCMGET: 706 SCARG(&ia, com) = TIOCMGET; 707 break; 708 case LINUX_TIOCMSET: 709 SCARG(&ia, com) = TIOCMSET; 710 break; 711 default: 712 error = EINVAL; 713 goto out; 714 } 715 716 SCARG(&ia, fd) = SCARG(uap, fd); 717 SCARG(&ia, data) = SCARG(uap, data); 718 /* XXX NJWLWP */ 719 error = sys_ioctl(curlwp, &ia, retval); 720 out: 721 FILE_UNUSE(fp, p); 722 return error; 723 } 724