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.11 (Berkeley) 08/03/92 15 */ 16 17 /* 18 * stty/gtty/termio emulation stuff 19 */ 20 #ifdef HPUXCOMPAT 21 22 #include "param.h" 23 #include "systm.h" 24 #include "filedesc.h" 25 #include "ioctl.h" 26 #include "proc.h" 27 #include "tty.h" 28 #include "file.h" 29 #include "conf.h" 30 #include "buf.h" 31 #include "kernel.h" 32 33 #include "hpux.h" 34 #include "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 if (newi) 168 bcopy(data, (char *)&htios, sizeof htios); 169 else 170 termiototermios((struct termio *)data, &htios); 171 /* 172 * Get old characteristics and determine if we are a tty. 173 */ 174 if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p)) 175 break; 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) 310 struct hpuxtermio *tio; 311 struct hpuxtermios *tios; 312 { 313 int i; 314 315 bzero((char *)tios, sizeof *tios); 316 tios->c_iflag = tio->c_iflag; 317 tios->c_oflag = tio->c_oflag; 318 tios->c_cflag = tio->c_cflag; 319 tios->c_lflag = tio->c_lflag; 320 tios->c_reserved = tio->c_line; 321 for (i = 0; i <= HPUXVSWTCH; i++) 322 tios->c_cc[i] = tio->c_cc[i]; 323 if (tios->c_lflag & TIO_ICANON) { 324 tios->c_cc[HPUXVEOF] = tio->c_cc[HPUXVEOF]; 325 tios->c_cc[HPUXVEOL] = tio->c_cc[HPUXVEOL]; 326 tios->c_cc[HPUXVMINS] = tios->c_cc[HPUXVTIMES] = 0; 327 } else { 328 tios->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOL] = 0; 329 tios->c_cc[HPUXVMINS] = tio->c_cc[HPUXVMIN]; 330 tios->c_cc[HPUXVTIMES] = tio->c_cc[HPUXVTIME]; 331 } 332 } 333 334 termiostotermio(tios, tio) 335 struct hpuxtermios *tios; 336 struct hpuxtermio *tio; 337 { 338 int i; 339 340 tio->c_iflag = tios->c_iflag; 341 tio->c_oflag = tios->c_oflag; 342 tio->c_cflag = tios->c_cflag; 343 tio->c_lflag = tios->c_lflag; 344 tio->c_line = tios->c_reserved; 345 for (i = 0; i <= HPUXVSWTCH; i++) 346 tio->c_cc[i] = tios->c_cc[i]; 347 if (tios->c_lflag & ICANON) { 348 tio->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOF]; 349 tio->c_cc[HPUXVEOL] = tios->c_cc[HPUXVEOL]; 350 } else { 351 tio->c_cc[HPUXVMIN] = tios->c_cc[HPUXVMINS]; 352 tio->c_cc[HPUXVTIME] = tios->c_cc[HPUXVTIMES]; 353 } 354 } 355 356 bsdtohpuxbaud(bsdspeed) 357 long bsdspeed; 358 { 359 switch (bsdspeed) { 360 case B0: return(TIO_B0); 361 case B50: return(TIO_B50); 362 case B75: return(TIO_B75); 363 case B110: return(TIO_B110); 364 case B134: return(TIO_B134); 365 case B150: return(TIO_B150); 366 case B200: return(TIO_B200); 367 case B300: return(TIO_B300); 368 case B600: return(TIO_B600); 369 case B1200: return(TIO_B1200); 370 case B1800: return(TIO_B1800); 371 case B2400: return(TIO_B2400); 372 case B4800: return(TIO_B4800); 373 case B9600: return(TIO_B9600); 374 case B19200: return(TIO_B19200); 375 case B38400: return(TIO_B38400); 376 default: return(TIO_B0); 377 } 378 } 379 380 hpuxtobsdbaud(hpuxspeed) 381 int hpuxspeed; 382 { 383 static char hpuxtobsdbaudtab[32] = { 384 B0, B50, B75, B110, B134, B150, B200, B300, 385 B600, B0, B1200, B1800, B2400, B0, B4800, B0, 386 B9600, B19200, B38400, B0, B0, B0, B0, B0, 387 B0, B0, B0, B0, B0, B0, EXTA, EXTB 388 }; 389 390 return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]); 391 } 392 393 #ifdef COMPAT_OHPUX 394 ohpuxgtty(p, uap, retval) 395 struct proc *p; 396 struct args { 397 int fdes; 398 caddr_t cmarg; 399 } *uap; 400 int *retval; 401 { 402 403 return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg)); 404 } 405 406 ohpuxstty(p, uap, retval) 407 struct proc *p; 408 struct args { 409 int fdes; 410 caddr_t cmarg; 411 } *uap; 412 int *retval; 413 { 414 415 return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg)); 416 } 417 418 /* 419 * Simplified version of ioctl() for use by 420 * gtty/stty and TIOCGETP/TIOCSETP. 421 */ 422 getsettty(p, fdes, com, cmarg) 423 struct proc *p; 424 int fdes, com; 425 caddr_t cmarg; 426 { 427 register struct filedesc *fdp = p->p_fd; 428 register struct file *fp; 429 struct hpuxsgttyb hsb; 430 struct sgttyb sb; 431 int error; 432 433 if (((unsigned)fdes) >= fdp->fd_nfiles || 434 (fp = fdp->fd_ofiles[fdes]) == NULL) 435 return (EBADF); 436 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 437 return (EBADF); 438 if (com == HPUXTIOCSETP) { 439 if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb)) 440 return (error); 441 sb.sg_ispeed = hsb.sg_ispeed; 442 sb.sg_ospeed = hsb.sg_ospeed; 443 sb.sg_erase = hsb.sg_erase; 444 sb.sg_kill = hsb.sg_kill; 445 sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 446 if (hsb.sg_flags & V7_XTABS) 447 sb.sg_flags |= XTABS; 448 if (hsb.sg_flags & V7_HUPCL) 449 (void)(*fp->f_ops->fo_ioctl) 450 (fp, TIOCHPCL, (caddr_t)0, p); 451 com = TIOCSETP; 452 } else { 453 bzero((caddr_t)&hsb, sizeof hsb); 454 com = TIOCGETP; 455 } 456 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb, p); 457 if (error == 0 && com == TIOCGETP) { 458 hsb.sg_ispeed = sb.sg_ispeed; 459 hsb.sg_ospeed = sb.sg_ospeed; 460 hsb.sg_erase = sb.sg_erase; 461 hsb.sg_kill = sb.sg_kill; 462 hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 463 if (sb.sg_flags & XTABS) 464 hsb.sg_flags |= V7_XTABS; 465 error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 466 } 467 return (error); 468 } 469 #endif 470 #endif 471