1 /* $NetBSD: linux_ioctl.c,v 1.1 1995/02/28 23:24:58 fvdl 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/termios.h> 41 #include <sys/tty.h> 42 #include <sys/socket.h> 43 #include <sys/ioctl.h> 44 #include <sys/mount.h> 45 46 #include <sys/syscallargs.h> 47 #include <compat/linux/linux_types.h> 48 #include <compat/linux/linux_ioctl.h> 49 #include <compat/linux/linux_util.h> 50 #include <compat/linux/linux_syscallargs.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 62 }; 63 64 /* 65 * Deal with termio ioctl cruft. This doesn't look very good.. 66 * XXX too much code duplication, obviously.. 67 * 68 * The conversion routines between Linux and BSD structures assume 69 * that the fields are already filled with the current values, 70 * so that fields present in BSD but not in Linux keep their current 71 * values. 72 */ 73 74 static int 75 linux_termio_to_bsd_termios(lt, bts) 76 register struct linux_termio *lt; 77 register struct termios *bts; 78 { 79 int index; 80 81 bts->c_iflag = 0; 82 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNBRK, IGNBRK); 83 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_BRKINT, BRKINT); 84 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNPAR, IGNPAR); 85 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INPCK, INPCK); 86 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ISTRIP, ISTRIP); 87 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INLCR, INLCR); 88 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNCR, IGNCR); 89 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ICRNL, ICRNL); 90 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXON, IXON); 91 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXANY, IXANY); 92 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXOFF, IXOFF); 93 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IMAXBEL, IMAXBEL); 94 95 bts->c_oflag = 0; 96 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_OPOST, OPOST); 97 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_ONLCR, ONLCR); 98 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_XTABS, OXTABS); 99 100 /* 101 * This could have been: 102 * bts->c_cflag = (lt->c_flag & LINUX_CSIZE) << 4 103 * But who knows, those values might perhaps change one day. 104 */ 105 switch (lt->c_cflag & LINUX_CSIZE) { 106 case LINUX_CS5: 107 bts->c_cflag = CS5; 108 break; 109 case LINUX_CS6: 110 bts->c_cflag = CS6; 111 break; 112 case LINUX_CS7: 113 bts->c_cflag = CS7; 114 break; 115 case LINUX_CS8: 116 bts->c_cflag = CS8; 117 break; 118 } 119 120 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CSTOPB, CSTOPB); 121 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CREAD, CREAD); 122 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARENB, PARENB); 123 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARODD, PARODD); 124 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_HUPCL, HUPCL); 125 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CLOCAL, CLOCAL); 126 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CRTSCTS, CRTSCTS); 127 128 bts->c_lflag = 0; 129 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ISIG, ISIG); 130 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ICANON, ICANON); 131 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHO, ECHO); 132 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOE, ECHOE); 133 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOK, ECHOK); 134 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHONL, ECHONL); 135 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_NOFLSH, NOFLSH); 136 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_TOSTOP, TOSTOP); 137 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOCTL, ECHOCTL); 138 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOPRT, ECHOPRT); 139 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOKE, ECHOKE); 140 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_FLUSHO, FLUSHO); 141 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_PENDIN, PENDIN); 142 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_IEXTEN, IEXTEN); 143 144 index = lt->c_cflag & LINUX_CBAUD; 145 if (index & LINUX_CBAUDEX) 146 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 147 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 148 149 bts->c_cc[VINTR] = lt->c_cc[LINUX_VINTR]; 150 bts->c_cc[VQUIT] = lt->c_cc[LINUX_VQUIT]; 151 bts->c_cc[VERASE] = lt->c_cc[LINUX_VERASE]; 152 bts->c_cc[VKILL] = lt->c_cc[LINUX_VKILL]; 153 bts->c_cc[VEOF] = lt->c_cc[LINUX_VEOF]; 154 bts->c_cc[VTIME] = lt->c_cc[LINUX_VTIME]; 155 bts->c_cc[VMIN] = lt->c_cc[LINUX_VMIN]; 156 } 157 158 static int 159 bsd_termios_to_linux_termio(bts, lt) 160 register struct termios *bts; 161 register struct linux_termio *lt; 162 { 163 int i, mask; 164 165 lt->c_iflag = 0; 166 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 167 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 168 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 169 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 170 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 171 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 172 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 173 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 174 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 175 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 176 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 177 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 178 179 lt->c_oflag = 0; 180 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 181 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 182 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 183 184 switch (bts->c_cflag & CSIZE) { 185 case CS5: 186 lt->c_cflag = LINUX_CS5; 187 break; 188 case CS6: 189 lt->c_cflag = LINUX_CS6; 190 break; 191 case CS7: 192 lt->c_cflag = LINUX_CS7; 193 break; 194 case CS8: 195 lt->c_cflag = LINUX_CS8; 196 break; 197 } 198 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 199 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 200 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 201 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 202 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 203 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 204 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 205 206 lt->c_lflag = 0; 207 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 208 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 209 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 210 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 211 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 212 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 213 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 214 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 215 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 216 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 217 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 218 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 219 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 220 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 221 222 mask = LINUX_B9600; /* XXX default value should this be 0? */ 223 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 224 if (bts->c_ospeed == linux_speeds[i]) { 225 mask = linux_spmasks[i]; 226 break; 227 } 228 } 229 lt->c_cflag |= mask; 230 231 lt->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 232 lt->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 233 lt->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 234 lt->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 235 lt->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 236 lt->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 237 lt->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 238 lt->c_cc[LINUX_VSWTC] = 0; 239 240 /* XXX should be fixed someday */ 241 lt->c_line = 0; 242 } 243 244 static int 245 linux_termios_to_bsd_termios(lts, bts) 246 register struct linux_termios *lts; 247 register struct termios *bts; 248 { 249 int index; 250 251 bts->c_iflag = 0; 252 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNBRK, IGNBRK); 253 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_BRKINT, BRKINT); 254 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNPAR, IGNPAR); 255 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INPCK, INPCK); 256 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ISTRIP, ISTRIP); 257 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INLCR, INLCR); 258 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNCR, IGNCR); 259 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ICRNL, ICRNL); 260 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXON, IXON); 261 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXANY, IXANY); 262 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXOFF, IXOFF); 263 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IMAXBEL, IMAXBEL); 264 265 bts->c_oflag = 0; 266 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_OPOST, OPOST); 267 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_ONLCR, ONLCR); 268 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_XTABS, OXTABS); 269 270 bts->c_cflag = 0; 271 switch (lts->c_cflag & LINUX_CSIZE) { 272 case LINUX_CS5: 273 bts->c_cflag = CS5; 274 break; 275 case LINUX_CS6: 276 bts->c_cflag = CS6; 277 break; 278 case LINUX_CS7: 279 bts->c_cflag = CS7; 280 break; 281 case LINUX_CS8: 282 bts->c_cflag = CS8; 283 break; 284 } 285 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CSTOPB, CSTOPB); 286 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CREAD, CREAD); 287 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARENB, PARENB); 288 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARODD, PARODD); 289 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_HUPCL, HUPCL); 290 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CLOCAL, CLOCAL); 291 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CRTSCTS, CRTSCTS); 292 293 bts->c_lflag = 0; 294 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ISIG, ISIG); 295 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ICANON, ICANON); 296 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHO, ECHO); 297 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOE, ECHOE); 298 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOK, ECHOK); 299 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHONL, ECHONL); 300 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_NOFLSH, NOFLSH); 301 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_TOSTOP, TOSTOP); 302 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOCTL, ECHOCTL); 303 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOPRT, ECHOPRT); 304 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOKE, ECHOKE); 305 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_FLUSHO, FLUSHO); 306 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_PENDIN, PENDIN); 307 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_IEXTEN, IEXTEN); 308 309 index = lts->c_cflag & LINUX_CBAUD; 310 if (index & LINUX_CBAUDEX) 311 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 312 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 313 314 bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR]; 315 bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT]; 316 bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE]; 317 bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL]; 318 bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF]; 319 bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME]; 320 bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN]; 321 bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL]; 322 bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2]; 323 bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE]; 324 bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP]; 325 bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART]; 326 bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP]; 327 bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT]; 328 bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD]; 329 bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT]; 330 } 331 332 static int 333 bsd_termios_to_linux_termios(bts, lts) 334 register struct termios *bts; 335 register struct linux_termios *lts; 336 { 337 int i, mask; 338 339 lts->c_iflag = 0; 340 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 341 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 342 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 343 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 344 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 345 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 346 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 347 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 348 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 349 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 350 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 351 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 352 353 lts->c_oflag = 0; 354 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 355 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 356 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 357 358 switch (bts->c_cflag & CSIZE) { 359 case CS5: 360 lts->c_cflag = LINUX_CS5; 361 break; 362 case CS6: 363 lts->c_cflag = LINUX_CS6; 364 break; 365 case CS7: 366 lts->c_cflag = LINUX_CS7; 367 break; 368 case CS8: 369 lts->c_cflag = LINUX_CS8; 370 break; 371 } 372 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5); 373 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6); 374 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7); 375 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8); 376 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 377 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 378 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 379 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 380 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 381 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 382 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 383 384 lts->c_lflag = 0; 385 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 386 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 387 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 388 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 389 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 390 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 391 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 392 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 393 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 394 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 395 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 396 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 397 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 398 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 399 400 mask = LINUX_B9600; /* XXX default value */ 401 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 402 if (bts->c_ospeed == linux_speeds[i]) { 403 mask = linux_spmasks[i]; 404 break; 405 } 406 } 407 lts->c_cflag |= mask; 408 409 lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 410 lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 411 lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 412 lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 413 lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 414 lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 415 lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 416 lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL]; 417 lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2]; 418 lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE]; 419 lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP]; 420 lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART]; 421 lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP]; 422 lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT]; 423 lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD]; 424 lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT]; 425 lts->c_cc[LINUX_VSWTC] = 0; 426 427 /* XXX should be fixed someday */ 428 lts->c_line = 0; 429 } 430 431 /* 432 * Most ioctl command are just converted to their NetBSD values, 433 * and passed on. The ones that take structure pointers and (flag) 434 * values need some massaging. This is done the usual way by 435 * allocating stackgap memory, letting the actual ioctl call do its 436 * work their and converting back the data afterwards. 437 */ 438 int 439 linux_ioctl(p, uap, retval) 440 register struct proc *p; 441 register struct linux_ioctl_args /* { 442 syscallarg(int) fd; 443 syscallarg(u_long) com; 444 syscallarg(caddr_t) data; 445 } */ *uap; 446 register_t *retval; 447 { 448 int fd; 449 unsigned long com; 450 caddr_t data, sg; 451 struct file *fp; 452 struct filedesc *fdp; 453 struct linux_termio tmplt, *alt; 454 struct linux_termios tmplts, *alts; 455 struct termios tmpbts, *abts; 456 struct ioctl_args ia; 457 int error, idat, *idatp; 458 459 fd = SCARG(&ia, fd) = SCARG(uap, fd); 460 com = SCARG(uap, com); 461 data = SCARG(&ia, data) = SCARG(uap, data); 462 retval[0] = 0; 463 464 fdp = p->p_fd; 465 if ((u_int)fd >= fdp->fd_nfiles || 466 (fp = fdp->fd_ofiles[fd]) == NULL) 467 return (EBADF); 468 469 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 470 return (EBADF); 471 472 sg = stackgap_init(); 473 474 switch (com) { 475 case LINUX_TCGETS: 476 SCARG(&ia, com) = TIOCGETA; 477 abts = stackgap_alloc(&sg, sizeof (*abts)); 478 SCARG(&ia, data) = (caddr_t) abts; 479 if ((error = ioctl(p, &ia, retval)) != 0) 480 return error; 481 if ((error = copyin(abts, &tmpbts, sizeof tmpbts))) 482 return error; 483 bsd_termios_to_linux_termios(&tmpbts, &tmplts); 484 return copyout(&tmplts, data, sizeof tmplts); 485 case LINUX_TCSETS: 486 case LINUX_TCSETSW: 487 case LINUX_TCSETSF: 488 switch (com) { 489 case LINUX_TCSETS: 490 SCARG(&ia, com) = TIOCSETA; 491 break; 492 case LINUX_TCSETSW: 493 SCARG(&ia, com) = TIOCSETAW; 494 break; 495 case LINUX_TCSETSF: 496 SCARG(&ia, com) = TIOCSETAF; 497 break; 498 } 499 if ((error = copyin(data, &tmplts, sizeof tmplts))) 500 return error; 501 abts = stackgap_alloc(&sg, sizeof tmpbts); 502 /* 503 * First fill in all fields, so that we keep the current 504 * values for fields that Linux doesn't know about. 505 */ 506 if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, 507 (caddr_t) &tmpbts, p))) 508 return error; 509 linux_termios_to_bsd_termios(&tmplts, &tmpbts); 510 if ((error = copyout(&tmpbts, abts, sizeof tmpbts))) 511 return error; 512 SCARG(&ia, data) = (caddr_t) abts; 513 return ioctl(p, &ia, retval); 514 case LINUX_TCGETA: 515 SCARG(&ia, com) = TIOCGETA; 516 abts = stackgap_alloc(&sg, sizeof (*abts)); 517 SCARG(&ia, data) = (caddr_t) abts; 518 if ((error = ioctl(p, &ia, retval)) != 0) 519 return error; 520 if ((error = copyin(abts, &tmpbts, sizeof tmpbts))) 521 return error; 522 bsd_termios_to_linux_termio(&tmpbts, &tmplt); 523 return copyout(&tmplt, data, sizeof tmplt); 524 case LINUX_TCSETA: 525 case LINUX_TCSETAW: 526 case LINUX_TCSETAF: 527 switch (com) { 528 case LINUX_TCSETA: 529 SCARG(&ia, com) = TIOCSETA; 530 break; 531 case LINUX_TCSETAW: 532 SCARG(&ia, com) = TIOCSETAW; 533 break; 534 case LINUX_TCSETAF: 535 SCARG(&ia, com) = TIOCSETAF; 536 break; 537 } 538 if ((error = copyin(&tmplt, data, sizeof tmplt))) 539 return error; 540 abts = stackgap_alloc(&sg, sizeof tmpbts); 541 /* 542 * First fill in all fields, so that we keep the current 543 * values for fields that Linux doesn't know about. 544 */ 545 if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, 546 (caddr_t) &tmpbts, p))) 547 return error; 548 linux_termio_to_bsd_termios(&tmplt, &tmpbts); 549 if ((error = copyout(&tmpbts, abts, sizeof tmpbts))) 550 return error; 551 SCARG(&ia, data) = (caddr_t) abts; 552 return ioctl(p, &ia, retval); 553 case LINUX_TIOCSETD: 554 if ((error = copyin(data, (caddr_t) &idat, sizeof idat))) 555 return error; 556 switch (idat) { 557 case LINUX_N_TTY: 558 idat = TTYDISC; 559 break; 560 case LINUX_N_SLIP: 561 idat = SLIPDISC; 562 break; 563 case LINUX_N_PPP: 564 idat = PPPDISC; 565 break; 566 /* 567 * We can't handle the mouse line discipline Linux has. 568 */ 569 case LINUX_N_MOUSE: 570 default: 571 return EINVAL; 572 } 573 574 idatp = (int *) stackgap_alloc(&sg, sizeof (int)); 575 if ((error = copyout(&idat, idatp, sizeof (int)))) 576 return error; 577 SCARG(&ia, com) = TIOCSETD; 578 SCARG(&ia, data) = (caddr_t) idatp; 579 break; 580 case LINUX_TIOCGETD: 581 idatp = (int *) stackgap_alloc(&sg, sizeof (int)); 582 SCARG(&ia, com) = TIOCGETD; 583 SCARG(&ia, data) = (caddr_t) idatp; 584 if ((error = ioctl(p, &ia, retval))) 585 return error; 586 if ((error = copyin(idatp, (caddr_t) &idat, sizeof (int)))) 587 return error; 588 switch (idat) { 589 case TTYDISC: 590 idat = LINUX_N_TTY; 591 break; 592 case SLIPDISC: 593 idat = LINUX_N_SLIP; 594 break; 595 case PPPDISC: 596 idat = LINUX_N_PPP; 597 break; 598 /* 599 * Linux does not have the tablet line discipline. 600 */ 601 case TABLDISC: 602 default: 603 idat = -1; /* XXX What should this be? */ 604 break; 605 } 606 return copyout(&idat, data, sizeof (int)); 607 case LINUX_TIOCGWINSZ: 608 SCARG(&ia, com) = TIOCGWINSZ; 609 break; 610 case LINUX_TIOCSWINSZ: 611 SCARG(&ia, com) = TIOCSWINSZ; 612 break; 613 case LINUX_TIOCGPGRP: 614 SCARG(&ia, com) = TIOCGPGRP; 615 break; 616 case LINUX_TIOCSPGRP: 617 SCARG(&ia, com) = TIOCSPGRP; 618 break; 619 case LINUX_FIONREAD: 620 SCARG(&ia, com) = FIONREAD; 621 break; 622 case LINUX_FIONBIO: 623 SCARG(&ia, com) = FIONBIO; 624 break; 625 case LINUX_FIOASYNC: 626 SCARG(&ia, com) = FIOASYNC; 627 break; 628 case LINUX_TIOCEXCL: 629 SCARG(&ia, com) = TIOCEXCL; 630 break; 631 case LINUX_TIOCNXCL: 632 SCARG(&ia, com) = TIOCNXCL; 633 break; 634 case LINUX_TIOCCONS: 635 SCARG(&ia, com) = TIOCCONS; 636 break; 637 case LINUX_TIOCNOTTY: 638 SCARG(&ia, com) = TIOCNOTTY; 639 break; 640 default: 641 return EINVAL; 642 } 643 644 return ioctl(p, &ia, retval); 645 } 646