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