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