141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 341486Smckusick * Copyright (c) 1990 The Regents of the University of California. 441486Smckusick * All rights reserved. 541486Smckusick * 641486Smckusick * This code is derived from software contributed to Berkeley by 741486Smckusick * the Systems Programming Group of the University of Utah Computer 841486Smckusick * Science Department. 941486Smckusick * 1041486Smckusick * %sccs.include.redist.c% 1141486Smckusick * 1241486Smckusick * from: Utah $Hdr: hpux_tty.c 1.7 89/04/11$ 1341486Smckusick * 14*44341Shibler * @(#)hpux_tty.c 7.4 (Berkeley) 06/27/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * stty/gtty/termio emulation stuff 1941486Smckusick */ 2041486Smckusick #ifdef HPUXCOMPAT 2141486Smckusick 2241486Smckusick #include "param.h" 2341486Smckusick #include "systm.h" 2441486Smckusick #include "user.h" 2541486Smckusick #include "ioctl.h" 2641486Smckusick #include "tty.h" 2741486Smckusick #include "proc.h" 2841486Smckusick #include "file.h" 2941486Smckusick #include "conf.h" 3041486Smckusick #include "buf.h" 3141486Smckusick #include "uio.h" 3241486Smckusick #include "kernel.h" 3341486Smckusick 3441486Smckusick #include "hpux.h" 3541486Smckusick #include "hpux_termio.h" 3641486Smckusick 3741486Smckusick /* 38*44341Shibler * Map BSD/POSIX style termios info to and from SYS5 style termio stuff. 3941486Smckusick */ 4041486Smckusick hpuxtermio(fp, com, data) 4141486Smckusick struct file *fp; 4241486Smckusick caddr_t data; 4341486Smckusick { 44*44341Shibler struct termios tios; 45*44341Shibler int line, error, (*ioctlrout)(); 4641486Smckusick register struct hpuxtermio *tiop; 4741486Smckusick 4841486Smckusick ioctlrout = fp->f_ops->fo_ioctl; 4941486Smckusick tiop = (struct hpuxtermio *)data; 5041486Smckusick switch (com) { 5141486Smckusick case HPUXTCGETA: 52*44341Shibler /* 53*44341Shibler * Get BSD terminal state 54*44341Shibler */ 5541486Smckusick bzero(data, sizeof(struct hpuxtermio)); 56*44341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 5741486Smckusick break; 58*44341Shibler /* 59*44341Shibler * Set iflag. 60*44341Shibler * Same through ICRNL, no BSD equivs for IUCLC, IENQAK 61*44341Shibler */ 62*44341Shibler tiop->c_iflag = tios.c_iflag & 0x1ff; 63*44341Shibler if (tios.c_iflag & IXON) 64*44341Shibler tiop->c_iflag |= TIO_IXON; 65*44341Shibler if (tios.c_iflag & IXOFF) 66*44341Shibler tiop->c_iflag |= TIO_IXOFF; 67*44341Shibler if (tios.c_iflag & IXANY) 68*44341Shibler tiop->c_iflag |= TIO_IXANY; 69*44341Shibler /* 70*44341Shibler * Set oflag. 71*44341Shibler * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL 72*44341Shibler * or any of the delays. 73*44341Shibler */ 74*44341Shibler if (tios.c_oflag & OPOST) 75*44341Shibler tiop->c_oflag |= TIO_OPOST; 76*44341Shibler if (tios.c_oflag & ONLCR) 77*44341Shibler tiop->c_oflag |= TIO_ONLCR; 78*44341Shibler if (tios.c_oflag & OXTABS) 7941486Smckusick tiop->c_oflag |= TIO_TAB3; 80*44341Shibler /* 81*44341Shibler * Set cflag. 82*44341Shibler * Baud from ospeed, rest from cflag. 83*44341Shibler */ 84*44341Shibler tiop->c_cflag = bsdtohpuxbaud(tios.c_ospeed); 85*44341Shibler switch (tios.c_cflag & CSIZE) { 86*44341Shibler case CS5: 87*44341Shibler tiop->c_cflag |= TIO_CS5; break; 88*44341Shibler case CS6: 89*44341Shibler tiop->c_cflag |= TIO_CS6; break; 90*44341Shibler case CS7: 91*44341Shibler tiop->c_cflag |= TIO_CS7; break; 92*44341Shibler case CS8: 93*44341Shibler tiop->c_cflag |= TIO_CS8; break; 9441486Smckusick } 95*44341Shibler if (tios.c_cflag & CSTOPB) 96*44341Shibler tiop->c_cflag |= TIO_CSTOPB; 97*44341Shibler if (tios.c_cflag & CREAD) 98*44341Shibler tiop->c_cflag |= TIO_CREAD; 99*44341Shibler if (tios.c_cflag & PARENB) 100*44341Shibler tiop->c_cflag |= TIO_PARENB; 101*44341Shibler if (tios.c_cflag & PARODD) 102*44341Shibler tiop->c_cflag |= TIO_PARODD; 103*44341Shibler if (tios.c_cflag & HUPCL) 104*44341Shibler tiop->c_cflag |= TIO_HUPCL; 105*44341Shibler if (tios.c_cflag & CLOCAL) 106*44341Shibler tiop->c_cflag |= TIO_CLOCAL; 107*44341Shibler /* 108*44341Shibler * Set lflag. 109*44341Shibler * No BSD equiv for XCASE. 110*44341Shibler */ 111*44341Shibler if (tios.c_lflag & ECHOE) 112*44341Shibler tiop->c_lflag |= TIO_ECHOE; 113*44341Shibler if (tios.c_lflag & ECHOK) 114*44341Shibler tiop->c_lflag |= TIO_ECHOK; 115*44341Shibler if (tios.c_lflag & ECHO) 11641486Smckusick tiop->c_lflag |= TIO_ECHO; 117*44341Shibler if (tios.c_lflag & ECHONL) 118*44341Shibler tiop->c_lflag |= TIO_ECHONL; 119*44341Shibler if (tios.c_lflag & ISIG) 120*44341Shibler tiop->c_lflag |= TIO_ISIG; 121*44341Shibler if (tios.c_lflag & ICANON) 122*44341Shibler tiop->c_lflag |= TIO_ICANON; 123*44341Shibler if (tios.c_lflag & NOFLSH) 124*44341Shibler tiop->c_lflag |= TIO_NOFLSH; 125*44341Shibler /* 126*44341Shibler * Line discipline 127*44341Shibler */ 128*44341Shibler line = 0; 129*44341Shibler (void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line); 130*44341Shibler tiop->c_line = line; 131*44341Shibler /* 132*44341Shibler * Set editing chars 133*44341Shibler */ 134*44341Shibler tiop->c_cc[HPUXVINTR] = tios.c_cc[VINTR]; 135*44341Shibler tiop->c_cc[HPUXVQUIT] = tios.c_cc[VQUIT]; 136*44341Shibler tiop->c_cc[HPUXVERASE] = tios.c_cc[VERASE]; 137*44341Shibler tiop->c_cc[HPUXVKILL] = tios.c_cc[VKILL]; 138*44341Shibler if (tiop->c_lflag & TIO_ICANON) { 139*44341Shibler tiop->c_cc[HPUXVEOF] = tios.c_cc[VEOF]; 140*44341Shibler tiop->c_cc[HPUXVEOL] = tios.c_cc[VEOL]; 14141486Smckusick } else { 142*44341Shibler tiop->c_cc[HPUXVMIN] = tios.c_cc[VMIN]; 143*44341Shibler tiop->c_cc[HPUXVTIME] = tios.c_cc[VTIME]; 14441486Smckusick } 14541486Smckusick break; 14641486Smckusick 14741486Smckusick case HPUXTCSETA: 14841486Smckusick case HPUXTCSETAW: 14941486Smckusick case HPUXTCSETAF: 150*44341Shibler /* 151*44341Shibler * Get old characteristics and determine if we are a tty. 152*44341Shibler */ 153*44341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 15441486Smckusick break; 155*44341Shibler /* 156*44341Shibler * Set iflag. 157*44341Shibler * Same through ICRNL, no HP-UX equiv for IMAXBEL 158*44341Shibler */ 159*44341Shibler tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff); 160*44341Shibler tios.c_iflag |= tiop->c_iflag & 0x1ff; 161*44341Shibler if (tiop->c_iflag & TIO_IXON) 162*44341Shibler tios.c_iflag |= IXON; 163*44341Shibler if (tiop->c_iflag & TIO_IXOFF) 164*44341Shibler tios.c_iflag |= IXOFF; 165*44341Shibler if (tiop->c_iflag & TIO_IXANY) 166*44341Shibler tios.c_iflag |= IXANY; 167*44341Shibler /* 168*44341Shibler * Set oflag. 169*44341Shibler * No HP-UX equiv for ONOEOT 170*44341Shibler */ 171*44341Shibler tios.c_oflag &= ~(OPOST|ONLCR|OXTABS); 172*44341Shibler if (tiop->c_oflag & TIO_OPOST) 173*44341Shibler tios.c_oflag |= OPOST; 174*44341Shibler if (tiop->c_oflag & TIO_ONLCR) 175*44341Shibler tios.c_oflag |= ONLCR; 176*44341Shibler if (tiop->c_oflag & TIO_TAB3) 177*44341Shibler tios.c_oflag |= OXTABS; 178*44341Shibler /* 179*44341Shibler * Set cflag. 180*44341Shibler * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF 181*44341Shibler */ 182*44341Shibler tios.c_cflag &= 183*44341Shibler ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL); 184*44341Shibler switch (tiop->c_cflag & TIO_CSIZE) { 185*44341Shibler case TIO_CS5: 186*44341Shibler tios.c_cflag |= CS5; break; 187*44341Shibler case TIO_CS6: 188*44341Shibler tios.c_cflag |= CS6; break; 189*44341Shibler case TIO_CS7: 190*44341Shibler tios.c_cflag |= CS7; break; 191*44341Shibler case TIO_CS8: 192*44341Shibler tios.c_cflag |= CS8; break; 19341486Smckusick } 194*44341Shibler if (tiop->c_cflag & TIO_CSTOPB) 195*44341Shibler tios.c_cflag |= CSTOPB; 196*44341Shibler if (tiop->c_cflag & TIO_CREAD) 197*44341Shibler tios.c_cflag |= CREAD; 198*44341Shibler if (tiop->c_cflag & TIO_PARENB) 199*44341Shibler tios.c_cflag |= PARENB; 200*44341Shibler if (tiop->c_cflag & TIO_PARODD) 201*44341Shibler tios.c_cflag |= PARODD; 202*44341Shibler if (tiop->c_cflag & TIO_HUPCL) 203*44341Shibler tios.c_cflag |= HUPCL; 204*44341Shibler if (tiop->c_cflag & TIO_CLOCAL) 205*44341Shibler tios.c_cflag |= CLOCAL; 206*44341Shibler /* 207*44341Shibler * Set lflag. 208*44341Shibler * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL 209*44341Shibler * IEXTEN treated as part of ICANON 210*44341Shibler */ 211*44341Shibler tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH); 212*44341Shibler if (tiop->c_lflag & TIO_ECHOE) 213*44341Shibler tios.c_lflag |= ECHOE; 214*44341Shibler if (tiop->c_lflag & TIO_ECHOK) 215*44341Shibler tios.c_lflag |= ECHOK; 21641486Smckusick if (tiop->c_lflag & TIO_ECHO) 217*44341Shibler tios.c_lflag |= ECHO; 218*44341Shibler if (tiop->c_lflag & TIO_ECHONL) 219*44341Shibler tios.c_lflag |= ECHONL; 220*44341Shibler if (tiop->c_lflag & TIO_ISIG) 221*44341Shibler tios.c_lflag |= ISIG; 222*44341Shibler if (tiop->c_lflag & TIO_ICANON) 223*44341Shibler tios.c_lflag |= (ICANON|IEXTEN); 224*44341Shibler if (tiop->c_lflag & TIO_NOFLSH) 225*44341Shibler tios.c_lflag |= NOFLSH; 226*44341Shibler /* 227*44341Shibler * Set editing chars. 228*44341Shibler * No HP-UX equivs of VEOL2/VWERASE/VREPRINT/VSUSP/VDSUSP 229*44341Shibler * VSTOP/VLNEXT/VDISCARD/VMIN/VTIME/VSTATUS/VERASE2 230*44341Shibler */ 231*44341Shibler tios.c_cc[VINTR] = tiop->c_cc[HPUXVINTR]; 232*44341Shibler tios.c_cc[VQUIT] = tiop->c_cc[HPUXVQUIT]; 233*44341Shibler tios.c_cc[VERASE] = tiop->c_cc[HPUXVERASE]; 234*44341Shibler tios.c_cc[VKILL] = tiop->c_cc[HPUXVKILL]; 235*44341Shibler if (tios.c_lflag & ICANON) { 236*44341Shibler tios.c_cc[VEOF] = tiop->c_cc[HPUXVEOF]; 237*44341Shibler tios.c_cc[VEOL] = tiop->c_cc[HPUXVEOL]; 238*44341Shibler } else { 239*44341Shibler tios.c_cc[VMIN] = tiop->c_cc[HPUXVMIN]; 240*44341Shibler tios.c_cc[VTIME] = tiop->c_cc[HPUXVTIME]; 24141486Smckusick } 242*44341Shibler /* 243*44341Shibler * Set the new stuff 244*44341Shibler */ 24541486Smckusick if (com == HPUXTCSETA) 246*44341Shibler com = TIOCSETA; 247*44341Shibler else if (com == HPUXTCSETAW) 248*44341Shibler com = TIOCSETAW; 24941486Smckusick else 250*44341Shibler com = TIOCSETAF; 251*44341Shibler error = (*ioctlrout)(fp, com, (caddr_t)&tios); 252*44341Shibler if (error == 0) { 253*44341Shibler /* 254*44341Shibler * Set line discipline 255*44341Shibler */ 256*44341Shibler line = tiop->c_line; 257*44341Shibler (void) (*ioctlrout)(fp, TIOCSETD, (caddr_t)&line); 258*44341Shibler /* 259*44341Shibler * Set non-blocking IO if VMIN == VTIME == 0. 260*44341Shibler * Should handle the other cases as well. It also 261*44341Shibler * isn't correct to just turn it off as it could be 262*44341Shibler * on as the result of a fcntl operation. 263*44341Shibler * XXX - wouldn't need to do this at all if VMIN/VTIME 264*44341Shibler * were implemented. 265*44341Shibler */ 266*44341Shibler line = (tiop->c_cc[HPUXVMIN] == 0 && 267*44341Shibler tiop->c_cc[HPUXVTIME] == 0); 268*44341Shibler (void) fset(fp, FNDELAY, line); 269*44341Shibler } 27041486Smckusick break; 27141486Smckusick 27241486Smckusick default: 27343453Shibler error = EINVAL; 27441486Smckusick break; 27541486Smckusick } 27643453Shibler return(error); 27741486Smckusick } 27841486Smckusick 279*44341Shibler bsdtohpuxbaud(bsdspeed) 280*44341Shibler long bsdspeed; 281*44341Shibler { 282*44341Shibler switch (bsdspeed) { 283*44341Shibler case B0: return(TIO_B0); 284*44341Shibler case B50: return(TIO_B50); 285*44341Shibler case B75: return(TIO_B75); 286*44341Shibler case B110: return(TIO_B110); 287*44341Shibler case B134: return(TIO_B134); 288*44341Shibler case B150: return(TIO_B150); 289*44341Shibler case B200: return(TIO_B200); 290*44341Shibler case B300: return(TIO_B300); 291*44341Shibler case B600: return(TIO_B600); 292*44341Shibler case B1200: return(TIO_B1200); 293*44341Shibler case B1800: return(TIO_B1800); 294*44341Shibler case B2400: return(TIO_B2400); 295*44341Shibler case B4800: return(TIO_B4800); 296*44341Shibler case B9600: return(TIO_B9600); 297*44341Shibler case B19200: return(TIO_B19200); 298*44341Shibler case B38400: return(TIO_B38400); 299*44341Shibler default: return(TIO_B0); 300*44341Shibler } 301*44341Shibler } 302*44341Shibler 303*44341Shibler hpuxtobsdbaud(hpuxspeed) 304*44341Shibler int hpuxspeed; 305*44341Shibler { 306*44341Shibler static char hpuxtobsdbaudtab[32] = { 307*44341Shibler B0, B50, B75, B110, B134, B150, B200, B300, 308*44341Shibler B600, B0, B1200, B1800, B2400, B0, B4800, B0, 309*44341Shibler B9600, B19200, B38400, B0, B0, B0, B0, B0, 310*44341Shibler B0, B0, B0, B0, B0, B0, EXTA, EXTB 311*44341Shibler }; 312*44341Shibler 313*44341Shibler return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]); 314*44341Shibler } 315*44341Shibler 31641486Smckusick /* #ifdef COMPAT */ 31743453Shibler ohpuxgtty(p, uap, retval) 31843453Shibler struct proc *p; 31943453Shibler struct args { 32041486Smckusick int fdes; 32141486Smckusick caddr_t cmarg; 32243453Shibler } *uap; 32343453Shibler int *retval; 32443453Shibler { 32541486Smckusick 32643711Smckusick return (getsettty(uap->fdes, HPUXTIOCGETP, uap->cmarg)); 32741486Smckusick } 32841486Smckusick 32943453Shibler ohpuxstty(p, uap, retval) 33043453Shibler struct proc *p; 33143453Shibler struct args { 33241486Smckusick int fdes; 33341486Smckusick caddr_t cmarg; 33443453Shibler } *uap; 33543453Shibler int *retval; 33643453Shibler { 33741486Smckusick 33843711Smckusick return (getsettty(uap->fdes, HPUXTIOCSETP, uap->cmarg)); 33941486Smckusick } 34041486Smckusick 34141486Smckusick /* 34241486Smckusick * Simplified version of ioctl() for use by 34341486Smckusick * gtty/stty and TIOCGETP/TIOCSETP. 34441486Smckusick */ 34541486Smckusick getsettty(fdes, com, cmarg) 34641486Smckusick int fdes, com; 34741486Smckusick caddr_t cmarg; 34841486Smckusick { 34941486Smckusick register struct file *fp; 35041486Smckusick struct hpuxsgttyb hsb; 35141486Smckusick struct sgttyb sb; 35243453Shibler int error; 35341486Smckusick 35443453Shibler if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) 35543453Shibler return (EBADF); 35643453Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 35743453Shibler return (EBADF); 35841486Smckusick if (com == HPUXTIOCSETP) { 35943453Shibler if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb)) 36043453Shibler return (error); 36141486Smckusick sb.sg_ispeed = hsb.sg_ispeed; 36241486Smckusick sb.sg_ospeed = hsb.sg_ospeed; 36341486Smckusick sb.sg_erase = hsb.sg_erase; 36441486Smckusick sb.sg_kill = hsb.sg_kill; 36543453Shibler sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 36643453Shibler if (hsb.sg_flags & V7_XTABS) 36743453Shibler sb.sg_flags |= XTABS; 36843453Shibler if (hsb.sg_flags & V7_HUPCL) 36943453Shibler (void)(*fp->f_ops->fo_ioctl)(fp, TIOCHPCL, (caddr_t)0); 37041486Smckusick com = TIOCSETP; 37141486Smckusick } else { 37241486Smckusick bzero((caddr_t)&hsb, sizeof hsb); 37341486Smckusick com = TIOCGETP; 37441486Smckusick } 37543453Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb); 37643453Shibler if (error == 0 && com == TIOCGETP) { 37741486Smckusick hsb.sg_ispeed = sb.sg_ispeed; 37841486Smckusick hsb.sg_ospeed = sb.sg_ospeed; 37941486Smckusick hsb.sg_erase = sb.sg_erase; 38041486Smckusick hsb.sg_kill = sb.sg_kill; 38143453Shibler hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 38243453Shibler if (sb.sg_flags & XTABS) 38343453Shibler hsb.sg_flags |= V7_XTABS; 38443453Shibler error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 38541486Smckusick } 38643453Shibler return (error); 38741486Smckusick } 38841486Smckusick /* #endif */ 38941486Smckusick #endif 390