1 /* $NetBSD: linux_termios.c,v 1.7 2000/03/30 11:27:18 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/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 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 bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR]; 330 bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT]; 331 bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE]; 332 bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL]; 333 bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF]; 334 bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME]; 335 bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN]; 336 bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL]; 337 bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2]; 338 bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE]; 339 bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP]; 340 bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART]; 341 bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP]; 342 bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT]; 343 bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD]; 344 bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT]; 345 } 346 347 static void 348 bsd_termios_to_linux_termios(bts, lts) 349 struct termios *bts; 350 struct linux_termios *lts; 351 { 352 int i, mask; 353 354 lts->c_iflag = 0; 355 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 356 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 357 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 358 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 359 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 360 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 361 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 362 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 363 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 364 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 365 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 366 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 367 368 lts->c_oflag = 0; 369 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 370 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 371 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 372 373 switch (bts->c_cflag & CSIZE) { 374 case CS5: 375 lts->c_cflag = LINUX_CS5; 376 break; 377 case CS6: 378 lts->c_cflag = LINUX_CS6; 379 break; 380 case CS7: 381 lts->c_cflag = LINUX_CS7; 382 break; 383 case CS8: 384 lts->c_cflag = LINUX_CS8; 385 break; 386 } 387 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5); 388 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6); 389 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7); 390 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8); 391 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 392 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 393 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 394 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 395 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 396 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 397 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 398 399 lts->c_lflag = 0; 400 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 401 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 402 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 403 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 404 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 405 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 406 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 407 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 408 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 409 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 410 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 411 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 412 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 413 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 414 415 mask = LINUX_B9600; /* XXX default value */ 416 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 417 if (bts->c_ospeed == linux_speeds[i]) { 418 mask = linux_spmasks[i]; 419 break; 420 } 421 } 422 lts->c_cflag |= mask; 423 424 lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 425 lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 426 lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 427 lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 428 lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 429 lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 430 lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 431 lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL]; 432 lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2]; 433 lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE]; 434 lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP]; 435 lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART]; 436 lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP]; 437 lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT]; 438 lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD]; 439 lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT]; 440 lts->c_cc[LINUX_VSWTC] = 0; 441 442 /* XXX should be fixed someday */ 443 lts->c_line = 0; 444 } 445 446 int 447 linux_ioctl_termios(p, uap, retval) 448 struct proc *p; 449 struct linux_sys_ioctl_args /* { 450 syscallarg(int) fd; 451 syscallarg(u_long) com; 452 syscallarg(caddr_t) data; 453 } */ *uap; 454 register_t *retval; 455 { 456 struct file *fp; 457 struct filedesc *fdp; 458 u_long com; 459 struct linux_termio tmplt; 460 struct linux_termios tmplts; 461 struct termios tmpbts; 462 int idat; 463 struct sys_ioctl_args ia; 464 int error; 465 466 fdp = p->p_fd; 467 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 468 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 469 return (EBADF); 470 471 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 472 return (EBADF); 473 474 com = SCARG(uap, com); 475 retval[0] = 0; 476 477 switch (com) { 478 case LINUX_TCGETS: 479 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 480 if (error) 481 return error; 482 bsd_termios_to_linux_termios(&tmpbts, &tmplts); 483 error = copyout(&tmplts, SCARG(uap, data), sizeof tmplts); 484 if (error) 485 return error; 486 return 0; 487 case LINUX_TCSETS: 488 case LINUX_TCSETSW: 489 case LINUX_TCSETSF: 490 /* 491 * First fill in all fields, so that we keep the current 492 * values for fields that Linux doesn't know about. 493 */ 494 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 495 if (error) 496 return error; 497 error = copyin(SCARG(uap, data), &tmplts, sizeof tmplts); 498 if (error) 499 return error; 500 linux_termios_to_bsd_termios(&tmplts, &tmpbts); 501 switch (com) { 502 case LINUX_TCSETS: 503 com = TIOCSETA; 504 break; 505 case LINUX_TCSETSW: 506 com = TIOCSETAW; 507 break; 508 case LINUX_TCSETSF: 509 com = TIOCSETAF; 510 break; 511 } 512 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&tmpbts, p); 513 if (error) 514 return error; 515 return 0; 516 case LINUX_TCGETA: 517 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 518 if (error) 519 return error; 520 bsd_termios_to_linux_termio(&tmpbts, &tmplt); 521 error = copyout(&tmplt, SCARG(uap, data), sizeof tmplt); 522 if (error) 523 return error; 524 return 0; 525 case LINUX_TCSETA: 526 case LINUX_TCSETAW: 527 case LINUX_TCSETAF: 528 /* 529 * First fill in all fields, so that we keep the current 530 * values for fields that Linux doesn't know about. 531 */ 532 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, p); 533 if (error) 534 return error; 535 error = copyin(SCARG(uap, data), &tmplt, sizeof tmplt); 536 if (error) 537 return error; 538 linux_termio_to_bsd_termios(&tmplt, &tmpbts); 539 switch (com) { 540 case LINUX_TCSETA: 541 com = TIOCSETA; 542 break; 543 case LINUX_TCSETAW: 544 com = TIOCSETAW; 545 break; 546 case LINUX_TCSETAF: 547 com = TIOCSETAF; 548 break; 549 } 550 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&tmpbts, p); 551 if (error) 552 return error; 553 return 0; 554 case LINUX_TIOCGETD: 555 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETD, (caddr_t)&idat, p); 556 if (error) 557 return error; 558 switch (idat) { 559 case TTYDISC: 560 idat = LINUX_N_TTY; 561 break; 562 case SLIPDISC: 563 idat = LINUX_N_SLIP; 564 break; 565 case PPPDISC: 566 idat = LINUX_N_PPP; 567 break; 568 case STRIPDISC: 569 idat = LINUX_N_STRIP; 570 break; 571 /* 572 * Linux does not have the tablet line discipline. 573 */ 574 case TABLDISC: 575 default: 576 idat = -1; /* XXX What should this be? */ 577 break; 578 } 579 error = copyout(&idat, SCARG(uap, data), sizeof idat); 580 if (error) 581 return error; 582 return 0; 583 case LINUX_TIOCSETD: 584 error = copyin(SCARG(uap, data), &idat, sizeof idat); 585 if (error) 586 return error; 587 switch (idat) { 588 case LINUX_N_TTY: 589 idat = TTYDISC; 590 break; 591 case LINUX_N_SLIP: 592 idat = SLIPDISC; 593 break; 594 case LINUX_N_PPP: 595 idat = PPPDISC; 596 break; 597 case LINUX_N_STRIP: 598 idat = STRIPDISC; 599 break; 600 /* 601 * We can't handle the mouse line discipline Linux has. 602 */ 603 case LINUX_N_MOUSE: 604 case LINUX_N_AX25: 605 case LINUX_N_X25: 606 case LINUX_N_6PACK: 607 default: 608 return EINVAL; 609 } 610 error = (*fp->f_ops->fo_ioctl)(fp, TIOCSETD, (caddr_t)&idat, p); 611 if (error) 612 return error; 613 return 0; 614 case LINUX_TIOCGWINSZ: 615 SCARG(&ia, com) = TIOCGWINSZ; 616 break; 617 case LINUX_TIOCSWINSZ: 618 SCARG(&ia, com) = TIOCSWINSZ; 619 break; 620 case LINUX_TIOCGPGRP: 621 SCARG(&ia, com) = TIOCGPGRP; 622 break; 623 case LINUX_TIOCSPGRP: 624 SCARG(&ia, com) = TIOCSPGRP; 625 break; 626 case LINUX_FIONREAD: 627 SCARG(&ia, com) = FIONREAD; 628 break; 629 case LINUX_FIONBIO: 630 SCARG(&ia, com) = FIONBIO; 631 break; 632 case LINUX_FIOASYNC: 633 SCARG(&ia, com) = FIOASYNC; 634 break; 635 case LINUX_TIOCEXCL: 636 SCARG(&ia, com) = TIOCEXCL; 637 break; 638 case LINUX_TIOCNXCL: 639 SCARG(&ia, com) = TIOCNXCL; 640 break; 641 case LINUX_TIOCCONS: 642 SCARG(&ia, com) = TIOCCONS; 643 break; 644 case LINUX_TIOCNOTTY: 645 SCARG(&ia, com) = TIOCNOTTY; 646 break; 647 default: 648 return EINVAL; 649 } 650 651 SCARG(&ia, fd) = SCARG(uap, fd); 652 SCARG(&ia, data) = SCARG(uap, data); 653 return sys_ioctl(p, &ia, retval); 654 } 655