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