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.1 90/07/09$ 13 * 14 * @(#)hpux_tty.c 7.13 (Berkeley) 10/11/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 ohpuxgtty(p, uap, retval) 401 struct proc *p; 402 struct args { 403 int fdes; 404 caddr_t cmarg; 405 } *uap; 406 int *retval; 407 { 408 409 return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg)); 410 } 411 412 ohpuxstty(p, uap, retval) 413 struct proc *p; 414 struct args { 415 int fdes; 416 caddr_t cmarg; 417 } *uap; 418 int *retval; 419 { 420 421 return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg)); 422 } 423 424 /* 425 * Simplified version of ioctl() for use by 426 * gtty/stty and TIOCGETP/TIOCSETP. 427 */ 428 getsettty(p, fdes, com, cmarg) 429 struct proc *p; 430 int fdes, com; 431 caddr_t cmarg; 432 { 433 register struct filedesc *fdp = p->p_fd; 434 register struct file *fp; 435 struct hpuxsgttyb hsb; 436 struct sgttyb sb; 437 int error; 438 439 if (((unsigned)fdes) >= fdp->fd_nfiles || 440 (fp = fdp->fd_ofiles[fdes]) == NULL) 441 return (EBADF); 442 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 443 return (EBADF); 444 if (com == HPUXTIOCSETP) { 445 if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb)) 446 return (error); 447 sb.sg_ispeed = hsb.sg_ispeed; 448 sb.sg_ospeed = hsb.sg_ospeed; 449 sb.sg_erase = hsb.sg_erase; 450 sb.sg_kill = hsb.sg_kill; 451 sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 452 if (hsb.sg_flags & V7_XTABS) 453 sb.sg_flags |= XTABS; 454 if (hsb.sg_flags & V7_HUPCL) 455 (void)(*fp->f_ops->fo_ioctl) 456 (fp, TIOCHPCL, (caddr_t)0, p); 457 com = TIOCSETP; 458 } else { 459 bzero((caddr_t)&hsb, sizeof hsb); 460 com = TIOCGETP; 461 } 462 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb, p); 463 if (error == 0 && com == TIOCGETP) { 464 hsb.sg_ispeed = sb.sg_ispeed; 465 hsb.sg_ospeed = sb.sg_ospeed; 466 hsb.sg_erase = sb.sg_erase; 467 hsb.sg_kill = sb.sg_kill; 468 hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 469 if (sb.sg_flags & XTABS) 470 hsb.sg_flags |= V7_XTABS; 471 error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 472 } 473 return (error); 474 } 475 #endif 476 #endif 477