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