1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: hpux_tty.c 1.14 93/08/05$ 13 * 14 * @(#)hpux_tty.c 8.4 (Berkeley) 02/19/95 15 */ 16 17 /* 18 * stty/gtty/termio emulation stuff 19 */ 20 #ifdef HPUXCOMPAT 21 #ifndef COMPAT_43 22 #define COMPAT_43 23 #endif 24 25 #include <sys/param.h> 26 #include <sys/systm.h> 27 #include <sys/filedesc.h> 28 #include <sys/ioctl.h> 29 #include <sys/proc.h> 30 #include <sys/tty.h> 31 #include <sys/file.h> 32 #include <sys/conf.h> 33 #include <sys/buf.h> 34 #include <sys/kernel.h> 35 36 #include <hp/hpux/hpux.h> 37 #include <hp/hpux/hpux_termio.h> 38 39 /* 40 * Map BSD/POSIX style termios info to and from SYS5 style termio stuff. 41 */ 42 hpuxtermio(fd, com, data, p) 43 int fd, com; 44 caddr_t data; 45 struct proc *p; 46 { 47 struct file *fp; 48 struct termios tios; 49 struct hpuxtermios htios; 50 int line, error, (*ioctlrout)(); 51 int newi = 0; 52 53 fp = p->p_fd->fd_ofiles[fd]; 54 ioctlrout = fp->f_ops->fo_ioctl; 55 switch (com) { 56 case HPUXTCGETATTR: 57 newi = 1; 58 /* fall into ... */ 59 case HPUXTCGETA: 60 /* 61 * Get BSD terminal state 62 */ 63 if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p)) 64 break; 65 bzero((char *)&htios, sizeof htios); 66 /* 67 * Set iflag. 68 * Same through ICRNL, no BSD equivs for IUCLC, IENQAK 69 */ 70 htios.c_iflag = tios.c_iflag & 0x1ff; 71 if (tios.c_iflag & IXON) 72 htios.c_iflag |= TIO_IXON; 73 if (tios.c_iflag & IXOFF) 74 htios.c_iflag |= TIO_IXOFF; 75 if (tios.c_iflag & IXANY) 76 htios.c_iflag |= TIO_IXANY; 77 /* 78 * Set oflag. 79 * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL 80 * or any of the delays. 81 */ 82 if (tios.c_oflag & OPOST) 83 htios.c_oflag |= TIO_OPOST; 84 if (tios.c_oflag & ONLCR) 85 htios.c_oflag |= TIO_ONLCR; 86 if (tios.c_oflag & OXTABS) 87 htios.c_oflag |= TIO_TAB3; 88 /* 89 * Set cflag. 90 * Baud from ospeed, rest from cflag. 91 */ 92 htios.c_cflag = bsdtohpuxbaud(tios.c_ospeed); 93 switch (tios.c_cflag & CSIZE) { 94 case CS5: 95 htios.c_cflag |= TIO_CS5; break; 96 case CS6: 97 htios.c_cflag |= TIO_CS6; break; 98 case CS7: 99 htios.c_cflag |= TIO_CS7; break; 100 case CS8: 101 htios.c_cflag |= TIO_CS8; break; 102 } 103 if (tios.c_cflag & CSTOPB) 104 htios.c_cflag |= TIO_CSTOPB; 105 if (tios.c_cflag & CREAD) 106 htios.c_cflag |= TIO_CREAD; 107 if (tios.c_cflag & PARENB) 108 htios.c_cflag |= TIO_PARENB; 109 if (tios.c_cflag & PARODD) 110 htios.c_cflag |= TIO_PARODD; 111 if (tios.c_cflag & HUPCL) 112 htios.c_cflag |= TIO_HUPCL; 113 if (tios.c_cflag & CLOCAL) 114 htios.c_cflag |= TIO_CLOCAL; 115 /* 116 * Set lflag. 117 * No BSD equiv for XCASE. 118 */ 119 if (tios.c_lflag & ECHOE) 120 htios.c_lflag |= TIO_ECHOE; 121 if (tios.c_lflag & ECHOK) 122 htios.c_lflag |= TIO_ECHOK; 123 if (tios.c_lflag & ECHO) 124 htios.c_lflag |= TIO_ECHO; 125 if (tios.c_lflag & ECHONL) 126 htios.c_lflag |= TIO_ECHONL; 127 if (tios.c_lflag & ISIG) 128 htios.c_lflag |= TIO_ISIG; 129 if (tios.c_lflag & ICANON) 130 htios.c_lflag |= TIO_ICANON; 131 if (tios.c_lflag & NOFLSH) 132 htios.c_lflag |= TIO_NOFLSH; 133 /* 134 * Line discipline 135 */ 136 if (!newi) { 137 line = 0; 138 (void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line, p); 139 htios.c_reserved = line; 140 } 141 /* 142 * Set editing chars. 143 * No BSD equiv for VSWTCH. 144 */ 145 htios.c_cc[HPUXVINTR] = tios.c_cc[VINTR]; 146 htios.c_cc[HPUXVQUIT] = tios.c_cc[VQUIT]; 147 htios.c_cc[HPUXVERASE] = tios.c_cc[VERASE]; 148 htios.c_cc[HPUXVKILL] = tios.c_cc[VKILL]; 149 htios.c_cc[HPUXVEOF] = tios.c_cc[VEOF]; 150 htios.c_cc[HPUXVEOL] = tios.c_cc[VEOL]; 151 htios.c_cc[HPUXVEOL2] = tios.c_cc[VEOL2]; 152 htios.c_cc[HPUXVSWTCH] = 0; 153 #if 1 154 /* 155 * XXX since VMIN and VTIME are not implemented, 156 * we need to return something reasonable. 157 * Otherwise a GETA/SETA combo would always put 158 * the tty in non-blocking mode (since VMIN == VTIME == 0). 159 */ 160 if (fp->f_flag & FNONBLOCK) { 161 htios.c_cc[HPUXVMINS] = 0; 162 htios.c_cc[HPUXVTIMES] = 0; 163 } else { 164 htios.c_cc[HPUXVMINS] = 6; 165 htios.c_cc[HPUXVTIMES] = 1; 166 } 167 #else 168 htios.c_cc[HPUXVMINS] = tios.c_cc[VMIN]; 169 htios.c_cc[HPUXVTIMES] = tios.c_cc[VTIME]; 170 #endif 171 htios.c_cc[HPUXVSUSP] = tios.c_cc[VSUSP]; 172 htios.c_cc[HPUXVSTART] = tios.c_cc[VSTART]; 173 htios.c_cc[HPUXVSTOP] = tios.c_cc[VSTOP]; 174 if (newi) 175 bcopy((char *)&htios, data, sizeof htios); 176 else 177 termiostotermio(&htios, (struct hpuxtermio *)data); 178 break; 179 180 case HPUXTCSETATTR: 181 case HPUXTCSETATTRD: 182 case HPUXTCSETATTRF: 183 newi = 1; 184 /* fall into ... */ 185 case HPUXTCSETA: 186 case HPUXTCSETAW: 187 case HPUXTCSETAF: 188 /* 189 * Get old characteristics and determine if we are a tty. 190 */ 191 if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p)) 192 break; 193 if (newi) 194 bcopy(data, (char *)&htios, sizeof htios); 195 else 196 termiototermios((struct termio *)data, &htios, &tios); 197 /* 198 * Set iflag. 199 * Same through ICRNL, no HP-UX equiv for IMAXBEL 200 */ 201 tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff); 202 tios.c_iflag |= htios.c_iflag & 0x1ff; 203 if (htios.c_iflag & TIO_IXON) 204 tios.c_iflag |= IXON; 205 if (htios.c_iflag & TIO_IXOFF) 206 tios.c_iflag |= IXOFF; 207 if (htios.c_iflag & TIO_IXANY) 208 tios.c_iflag |= IXANY; 209 /* 210 * Set oflag. 211 * No HP-UX equiv for ONOEOT 212 */ 213 tios.c_oflag &= ~(OPOST|ONLCR|OXTABS); 214 if (htios.c_oflag & TIO_OPOST) 215 tios.c_oflag |= OPOST; 216 if (htios.c_oflag & TIO_ONLCR) 217 tios.c_oflag |= ONLCR; 218 if (htios.c_oflag & TIO_TAB3) 219 tios.c_oflag |= OXTABS; 220 /* 221 * Set cflag. 222 * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF 223 */ 224 tios.c_cflag &= 225 ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL); 226 switch (htios.c_cflag & TIO_CSIZE) { 227 case TIO_CS5: 228 tios.c_cflag |= CS5; break; 229 case TIO_CS6: 230 tios.c_cflag |= CS6; break; 231 case TIO_CS7: 232 tios.c_cflag |= CS7; break; 233 case TIO_CS8: 234 tios.c_cflag |= CS8; break; 235 } 236 if (htios.c_cflag & TIO_CSTOPB) 237 tios.c_cflag |= CSTOPB; 238 if (htios.c_cflag & TIO_CREAD) 239 tios.c_cflag |= CREAD; 240 if (htios.c_cflag & TIO_PARENB) 241 tios.c_cflag |= PARENB; 242 if (htios.c_cflag & TIO_PARODD) 243 tios.c_cflag |= PARODD; 244 if (htios.c_cflag & TIO_HUPCL) 245 tios.c_cflag |= HUPCL; 246 if (htios.c_cflag & TIO_CLOCAL) 247 tios.c_cflag |= CLOCAL; 248 /* 249 * Set lflag. 250 * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL 251 * IEXTEN treated as part of ICANON 252 */ 253 tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH); 254 if (htios.c_lflag & TIO_ECHOE) 255 tios.c_lflag |= ECHOE; 256 if (htios.c_lflag & TIO_ECHOK) 257 tios.c_lflag |= ECHOK; 258 if (htios.c_lflag & TIO_ECHO) 259 tios.c_lflag |= ECHO; 260 if (htios.c_lflag & TIO_ECHONL) 261 tios.c_lflag |= ECHONL; 262 if (htios.c_lflag & TIO_ISIG) 263 tios.c_lflag |= ISIG; 264 if (htios.c_lflag & TIO_ICANON) 265 tios.c_lflag |= (ICANON|IEXTEN); 266 if (htios.c_lflag & TIO_NOFLSH) 267 tios.c_lflag |= NOFLSH; 268 /* 269 * Set editing chars. 270 * No HP-UX equivs of VWERASE/VREPRINT/VDSUSP/VLNEXT 271 * /VDISCARD/VSTATUS/VERASE2 272 */ 273 tios.c_cc[VINTR] = htios.c_cc[HPUXVINTR]; 274 tios.c_cc[VQUIT] = htios.c_cc[HPUXVQUIT]; 275 tios.c_cc[VERASE] = htios.c_cc[HPUXVERASE]; 276 tios.c_cc[VKILL] = htios.c_cc[HPUXVKILL]; 277 tios.c_cc[VEOF] = htios.c_cc[HPUXVEOF]; 278 tios.c_cc[VEOL] = htios.c_cc[HPUXVEOL]; 279 tios.c_cc[VEOL2] = htios.c_cc[HPUXVEOL2]; 280 tios.c_cc[VMIN] = htios.c_cc[HPUXVMINS]; 281 tios.c_cc[VTIME] = htios.c_cc[HPUXVTIMES]; 282 tios.c_cc[VSUSP] = htios.c_cc[HPUXVSUSP]; 283 tios.c_cc[VSTART] = htios.c_cc[HPUXVSTART]; 284 tios.c_cc[VSTOP] = htios.c_cc[HPUXVSTOP]; 285 286 /* 287 * Set the new stuff 288 */ 289 if (com == HPUXTCSETA || com == HPUXTCSETATTR) 290 com = TIOCSETA; 291 else if (com == HPUXTCSETAW || com == HPUXTCSETATTRD) 292 com = TIOCSETAW; 293 else 294 com = TIOCSETAF; 295 error = (*ioctlrout)(fp, com, (caddr_t)&tios, p); 296 if (error == 0) { 297 /* 298 * Set line discipline 299 */ 300 if (!newi) { 301 line = htios.c_reserved; 302 (void) (*ioctlrout)(fp, TIOCSETD, 303 (caddr_t)&line, p); 304 } 305 /* 306 * Set non-blocking IO if VMIN == VTIME == 0, clear 307 * if not. Should handle the other cases as well. 308 * Note it isn't correct to just turn NBIO off like 309 * we do as it could be on as the result of a fcntl 310 * operation. 311 * 312 * XXX - wouldn't need to do this at all if VMIN/VTIME 313 * were implemented. 314 */ 315 { 316 struct hpuxfcntl_args { 317 int fdes, cmd, arg; 318 } args; 319 int flags, nbio; 320 321 nbio = (htios.c_cc[HPUXVMINS] == 0 && 322 htios.c_cc[HPUXVTIMES] == 0); 323 if (nbio && (fp->f_flag & FNONBLOCK) == 0 || 324 !nbio && (fp->f_flag & FNONBLOCK)) { 325 args.fdes = fd; 326 args.cmd = F_GETFL; 327 args.arg = 0; 328 (void) hpuxfcntl(p, &args, &flags); 329 if (nbio) 330 flags |= HPUXNDELAY; 331 else 332 flags &= ~HPUXNDELAY; 333 args.cmd = F_SETFL; 334 args.arg = flags; 335 (void) hpuxfcntl(p, &args, &flags); 336 } 337 } 338 } 339 break; 340 341 default: 342 error = EINVAL; 343 break; 344 } 345 return(error); 346 } 347 348 termiototermios(tio, tios, bsdtios) 349 struct hpuxtermio *tio; 350 struct hpuxtermios *tios; 351 struct termios *bsdtios; 352 { 353 int i; 354 355 bzero((char *)tios, sizeof *tios); 356 tios->c_iflag = tio->c_iflag; 357 tios->c_oflag = tio->c_oflag; 358 tios->c_cflag = tio->c_cflag; 359 tios->c_lflag = tio->c_lflag; 360 tios->c_reserved = tio->c_line; 361 for (i = 0; i <= HPUXVSWTCH; i++) 362 tios->c_cc[i] = tio->c_cc[i]; 363 if (tios->c_lflag & TIO_ICANON) { 364 tios->c_cc[HPUXVEOF] = tio->c_cc[HPUXVEOF]; 365 tios->c_cc[HPUXVEOL] = tio->c_cc[HPUXVEOL]; 366 tios->c_cc[HPUXVMINS] = 0; 367 tios->c_cc[HPUXVTIMES] = 0; 368 } else { 369 tios->c_cc[HPUXVEOF] = 0; 370 tios->c_cc[HPUXVEOL] = 0; 371 tios->c_cc[HPUXVMINS] = tio->c_cc[HPUXVMIN]; 372 tios->c_cc[HPUXVTIMES] = tio->c_cc[HPUXVTIME]; 373 } 374 tios->c_cc[HPUXVSUSP] = bsdtios->c_cc[VSUSP]; 375 tios->c_cc[HPUXVSTART] = bsdtios->c_cc[VSTART]; 376 tios->c_cc[HPUXVSTOP] = bsdtios->c_cc[VSTOP]; 377 } 378 379 termiostotermio(tios, tio) 380 struct hpuxtermios *tios; 381 struct hpuxtermio *tio; 382 { 383 int i; 384 385 tio->c_iflag = tios->c_iflag; 386 tio->c_oflag = tios->c_oflag; 387 tio->c_cflag = tios->c_cflag; 388 tio->c_lflag = tios->c_lflag; 389 tio->c_line = tios->c_reserved; 390 for (i = 0; i <= HPUXVSWTCH; i++) 391 tio->c_cc[i] = tios->c_cc[i]; 392 if (tios->c_lflag & TIO_ICANON) { 393 tio->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOF]; 394 tio->c_cc[HPUXVEOL] = tios->c_cc[HPUXVEOL]; 395 } else { 396 tio->c_cc[HPUXVMIN] = tios->c_cc[HPUXVMINS]; 397 tio->c_cc[HPUXVTIME] = tios->c_cc[HPUXVTIMES]; 398 } 399 } 400 401 bsdtohpuxbaud(bsdspeed) 402 long bsdspeed; 403 { 404 switch (bsdspeed) { 405 case B0: return(TIO_B0); 406 case B50: return(TIO_B50); 407 case B75: return(TIO_B75); 408 case B110: return(TIO_B110); 409 case B134: return(TIO_B134); 410 case B150: return(TIO_B150); 411 case B200: return(TIO_B200); 412 case B300: return(TIO_B300); 413 case B600: return(TIO_B600); 414 case B1200: return(TIO_B1200); 415 case B1800: return(TIO_B1800); 416 case B2400: return(TIO_B2400); 417 case B4800: return(TIO_B4800); 418 case B9600: return(TIO_B9600); 419 case B19200: return(TIO_B19200); 420 case B38400: return(TIO_B38400); 421 default: return(TIO_B0); 422 } 423 } 424 425 hpuxtobsdbaud(hpuxspeed) 426 int hpuxspeed; 427 { 428 static char hpuxtobsdbaudtab[32] = { 429 B0, B50, B75, B110, B134, B150, B200, B300, 430 B600, B0, B1200, B1800, B2400, B0, B4800, B0, 431 B9600, B19200, B38400, B0, B0, B0, B0, B0, 432 B0, B0, B0, B0, B0, B0, EXTA, EXTB 433 }; 434 435 return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]); 436 } 437 438 #ifdef COMPAT_OHPUX 439 struct ohpuxsgtty_args { 440 int fdes; 441 caddr_t cmarg; 442 }; 443 compat_43_hpuxgtty(p, uap, retval) 444 struct proc *p; 445 struct ohpuxsgtty_args *uap; 446 int *retval; 447 { 448 449 return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg)); 450 } 451 452 compat_43_hpuxstty(p, uap, retval) 453 struct proc *p; 454 struct ohpuxsgtty_args *uap; 455 int *retval; 456 { 457 458 return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg)); 459 } 460 461 /* 462 * Simplified version of ioctl() for use by 463 * gtty/stty and TIOCGETP/TIOCSETP. 464 */ 465 getsettty(p, fdes, com, cmarg) 466 struct proc *p; 467 int fdes, com; 468 caddr_t cmarg; 469 { 470 register struct filedesc *fdp = p->p_fd; 471 register struct file *fp; 472 struct hpuxsgttyb hsb; 473 struct sgttyb sb; 474 int error; 475 476 if (((unsigned)fdes) >= fdp->fd_nfiles || 477 (fp = fdp->fd_ofiles[fdes]) == NULL) 478 return (EBADF); 479 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 480 return (EBADF); 481 if (com == HPUXTIOCSETP) { 482 if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb)) 483 return (error); 484 sb.sg_ispeed = hsb.sg_ispeed; 485 sb.sg_ospeed = hsb.sg_ospeed; 486 sb.sg_erase = hsb.sg_erase; 487 sb.sg_kill = hsb.sg_kill; 488 sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 489 if (hsb.sg_flags & V7_XTABS) 490 sb.sg_flags |= XTABS; 491 if (hsb.sg_flags & V7_HUPCL) 492 (void)(*fp->f_ops->fo_ioctl) 493 (fp, TIOCHPCL, (caddr_t)0, p); 494 com = TIOCSETP; 495 } else { 496 bzero((caddr_t)&hsb, sizeof hsb); 497 com = TIOCGETP; 498 } 499 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb, p); 500 if (error == 0 && com == TIOCGETP) { 501 hsb.sg_ispeed = sb.sg_ispeed; 502 hsb.sg_ospeed = sb.sg_ospeed; 503 hsb.sg_erase = sb.sg_erase; 504 hsb.sg_kill = sb.sg_kill; 505 hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 506 if (sb.sg_flags & XTABS) 507 hsb.sg_flags |= V7_XTABS; 508 error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 509 } 510 return (error); 511 } 512 #endif 513 #endif 514