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