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 * 1245423Smckusick * from: Utah $Hdr: hpux_tty.c 1.1 90/07/09$ 1341486Smckusick * 14*45923Smckusick * @(#)hpux_tty.c 7.7 (Berkeley) 01/11/91 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * stty/gtty/termio emulation stuff 1941486Smckusick */ 2041486Smckusick #ifdef HPUXCOMPAT 2141486Smckusick 2245788Sbostic #include "sys/param.h" 2345788Sbostic #include "sys/systm.h" 2445788Sbostic #include "sys/user.h" 25*45923Smckusick #include "sys/filedesc.h" 2645788Sbostic #include "sys/ioctl.h" 2745788Sbostic #include "sys/tty.h" 2845788Sbostic #include "sys/proc.h" 2945788Sbostic #include "sys/file.h" 3045788Sbostic #include "sys/conf.h" 3145788Sbostic #include "sys/buf.h" 3245788Sbostic #include "sys/uio.h" 3345788Sbostic #include "sys/kernel.h" 3441486Smckusick 3541486Smckusick #include "hpux.h" 3641486Smckusick #include "hpux_termio.h" 3741486Smckusick 3841486Smckusick /* 3944341Shibler * Map BSD/POSIX style termios info to and from SYS5 style termio stuff. 4041486Smckusick */ 4141486Smckusick hpuxtermio(fp, com, data) 4241486Smckusick struct file *fp; 4341486Smckusick caddr_t data; 4441486Smckusick { 4544341Shibler struct termios tios; 4644341Shibler int line, error, (*ioctlrout)(); 4741486Smckusick register struct hpuxtermio *tiop; 4841486Smckusick 4941486Smckusick ioctlrout = fp->f_ops->fo_ioctl; 5041486Smckusick tiop = (struct hpuxtermio *)data; 5141486Smckusick switch (com) { 5241486Smckusick case HPUXTCGETA: 5344341Shibler /* 5444341Shibler * Get BSD terminal state 5544341Shibler */ 5641486Smckusick bzero(data, sizeof(struct hpuxtermio)); 5744341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 5841486Smckusick break; 5944341Shibler /* 6044341Shibler * Set iflag. 6144341Shibler * Same through ICRNL, no BSD equivs for IUCLC, IENQAK 6244341Shibler */ 6344341Shibler tiop->c_iflag = tios.c_iflag & 0x1ff; 6444341Shibler if (tios.c_iflag & IXON) 6544341Shibler tiop->c_iflag |= TIO_IXON; 6644341Shibler if (tios.c_iflag & IXOFF) 6744341Shibler tiop->c_iflag |= TIO_IXOFF; 6844341Shibler if (tios.c_iflag & IXANY) 6944341Shibler tiop->c_iflag |= TIO_IXANY; 7044341Shibler /* 7144341Shibler * Set oflag. 7244341Shibler * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL 7344341Shibler * or any of the delays. 7444341Shibler */ 7544341Shibler if (tios.c_oflag & OPOST) 7644341Shibler tiop->c_oflag |= TIO_OPOST; 7744341Shibler if (tios.c_oflag & ONLCR) 7844341Shibler tiop->c_oflag |= TIO_ONLCR; 7944341Shibler if (tios.c_oflag & OXTABS) 8041486Smckusick tiop->c_oflag |= TIO_TAB3; 8144341Shibler /* 8244341Shibler * Set cflag. 8344341Shibler * Baud from ospeed, rest from cflag. 8444341Shibler */ 8544341Shibler tiop->c_cflag = bsdtohpuxbaud(tios.c_ospeed); 8644341Shibler switch (tios.c_cflag & CSIZE) { 8744341Shibler case CS5: 8844341Shibler tiop->c_cflag |= TIO_CS5; break; 8944341Shibler case CS6: 9044341Shibler tiop->c_cflag |= TIO_CS6; break; 9144341Shibler case CS7: 9244341Shibler tiop->c_cflag |= TIO_CS7; break; 9344341Shibler case CS8: 9444341Shibler tiop->c_cflag |= TIO_CS8; break; 9541486Smckusick } 9644341Shibler if (tios.c_cflag & CSTOPB) 9744341Shibler tiop->c_cflag |= TIO_CSTOPB; 9844341Shibler if (tios.c_cflag & CREAD) 9944341Shibler tiop->c_cflag |= TIO_CREAD; 10044341Shibler if (tios.c_cflag & PARENB) 10144341Shibler tiop->c_cflag |= TIO_PARENB; 10244341Shibler if (tios.c_cflag & PARODD) 10344341Shibler tiop->c_cflag |= TIO_PARODD; 10444341Shibler if (tios.c_cflag & HUPCL) 10544341Shibler tiop->c_cflag |= TIO_HUPCL; 10644341Shibler if (tios.c_cflag & CLOCAL) 10744341Shibler tiop->c_cflag |= TIO_CLOCAL; 10844341Shibler /* 10944341Shibler * Set lflag. 11044341Shibler * No BSD equiv for XCASE. 11144341Shibler */ 11244341Shibler if (tios.c_lflag & ECHOE) 11344341Shibler tiop->c_lflag |= TIO_ECHOE; 11444341Shibler if (tios.c_lflag & ECHOK) 11544341Shibler tiop->c_lflag |= TIO_ECHOK; 11644341Shibler if (tios.c_lflag & ECHO) 11741486Smckusick tiop->c_lflag |= TIO_ECHO; 11844341Shibler if (tios.c_lflag & ECHONL) 11944341Shibler tiop->c_lflag |= TIO_ECHONL; 12044341Shibler if (tios.c_lflag & ISIG) 12144341Shibler tiop->c_lflag |= TIO_ISIG; 12244341Shibler if (tios.c_lflag & ICANON) 12344341Shibler tiop->c_lflag |= TIO_ICANON; 12444341Shibler if (tios.c_lflag & NOFLSH) 12544341Shibler tiop->c_lflag |= TIO_NOFLSH; 12644341Shibler /* 12744341Shibler * Line discipline 12844341Shibler */ 12944341Shibler line = 0; 13044341Shibler (void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line); 13144341Shibler tiop->c_line = line; 13244341Shibler /* 13344341Shibler * Set editing chars 13444341Shibler */ 13544341Shibler tiop->c_cc[HPUXVINTR] = tios.c_cc[VINTR]; 13644341Shibler tiop->c_cc[HPUXVQUIT] = tios.c_cc[VQUIT]; 13744341Shibler tiop->c_cc[HPUXVERASE] = tios.c_cc[VERASE]; 13844341Shibler tiop->c_cc[HPUXVKILL] = tios.c_cc[VKILL]; 13944341Shibler if (tiop->c_lflag & TIO_ICANON) { 14044341Shibler tiop->c_cc[HPUXVEOF] = tios.c_cc[VEOF]; 14144341Shibler tiop->c_cc[HPUXVEOL] = tios.c_cc[VEOL]; 14241486Smckusick } else { 14344341Shibler tiop->c_cc[HPUXVMIN] = tios.c_cc[VMIN]; 14444341Shibler tiop->c_cc[HPUXVTIME] = tios.c_cc[VTIME]; 14541486Smckusick } 14641486Smckusick break; 14741486Smckusick 14841486Smckusick case HPUXTCSETA: 14941486Smckusick case HPUXTCSETAW: 15041486Smckusick case HPUXTCSETAF: 15144341Shibler /* 15244341Shibler * Get old characteristics and determine if we are a tty. 15344341Shibler */ 15444341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 15541486Smckusick break; 15644341Shibler /* 15744341Shibler * Set iflag. 15844341Shibler * Same through ICRNL, no HP-UX equiv for IMAXBEL 15944341Shibler */ 16044341Shibler tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff); 16144341Shibler tios.c_iflag |= tiop->c_iflag & 0x1ff; 16244341Shibler if (tiop->c_iflag & TIO_IXON) 16344341Shibler tios.c_iflag |= IXON; 16444341Shibler if (tiop->c_iflag & TIO_IXOFF) 16544341Shibler tios.c_iflag |= IXOFF; 16644341Shibler if (tiop->c_iflag & TIO_IXANY) 16744341Shibler tios.c_iflag |= IXANY; 16844341Shibler /* 16944341Shibler * Set oflag. 17044341Shibler * No HP-UX equiv for ONOEOT 17144341Shibler */ 17244341Shibler tios.c_oflag &= ~(OPOST|ONLCR|OXTABS); 17344341Shibler if (tiop->c_oflag & TIO_OPOST) 17444341Shibler tios.c_oflag |= OPOST; 17544341Shibler if (tiop->c_oflag & TIO_ONLCR) 17644341Shibler tios.c_oflag |= ONLCR; 17744341Shibler if (tiop->c_oflag & TIO_TAB3) 17844341Shibler tios.c_oflag |= OXTABS; 17944341Shibler /* 18044341Shibler * Set cflag. 18144341Shibler * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF 18244341Shibler */ 18344341Shibler tios.c_cflag &= 18444341Shibler ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL); 18544341Shibler switch (tiop->c_cflag & TIO_CSIZE) { 18644341Shibler case TIO_CS5: 18744341Shibler tios.c_cflag |= CS5; break; 18844341Shibler case TIO_CS6: 18944341Shibler tios.c_cflag |= CS6; break; 19044341Shibler case TIO_CS7: 19144341Shibler tios.c_cflag |= CS7; break; 19244341Shibler case TIO_CS8: 19344341Shibler tios.c_cflag |= CS8; break; 19441486Smckusick } 19544341Shibler if (tiop->c_cflag & TIO_CSTOPB) 19644341Shibler tios.c_cflag |= CSTOPB; 19744341Shibler if (tiop->c_cflag & TIO_CREAD) 19844341Shibler tios.c_cflag |= CREAD; 19944341Shibler if (tiop->c_cflag & TIO_PARENB) 20044341Shibler tios.c_cflag |= PARENB; 20144341Shibler if (tiop->c_cflag & TIO_PARODD) 20244341Shibler tios.c_cflag |= PARODD; 20344341Shibler if (tiop->c_cflag & TIO_HUPCL) 20444341Shibler tios.c_cflag |= HUPCL; 20544341Shibler if (tiop->c_cflag & TIO_CLOCAL) 20644341Shibler tios.c_cflag |= CLOCAL; 20744341Shibler /* 20844341Shibler * Set lflag. 20944341Shibler * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL 21044341Shibler * IEXTEN treated as part of ICANON 21144341Shibler */ 21244341Shibler tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH); 21344341Shibler if (tiop->c_lflag & TIO_ECHOE) 21444341Shibler tios.c_lflag |= ECHOE; 21544341Shibler if (tiop->c_lflag & TIO_ECHOK) 21644341Shibler tios.c_lflag |= ECHOK; 21741486Smckusick if (tiop->c_lflag & TIO_ECHO) 21844341Shibler tios.c_lflag |= ECHO; 21944341Shibler if (tiop->c_lflag & TIO_ECHONL) 22044341Shibler tios.c_lflag |= ECHONL; 22144341Shibler if (tiop->c_lflag & TIO_ISIG) 22244341Shibler tios.c_lflag |= ISIG; 22344341Shibler if (tiop->c_lflag & TIO_ICANON) 22444341Shibler tios.c_lflag |= (ICANON|IEXTEN); 22544341Shibler if (tiop->c_lflag & TIO_NOFLSH) 22644341Shibler tios.c_lflag |= NOFLSH; 22744341Shibler /* 22844341Shibler * Set editing chars. 22944341Shibler * No HP-UX equivs of VEOL2/VWERASE/VREPRINT/VSUSP/VDSUSP 23044341Shibler * VSTOP/VLNEXT/VDISCARD/VMIN/VTIME/VSTATUS/VERASE2 23144341Shibler */ 23244341Shibler tios.c_cc[VINTR] = tiop->c_cc[HPUXVINTR]; 23344341Shibler tios.c_cc[VQUIT] = tiop->c_cc[HPUXVQUIT]; 23444341Shibler tios.c_cc[VERASE] = tiop->c_cc[HPUXVERASE]; 23544341Shibler tios.c_cc[VKILL] = tiop->c_cc[HPUXVKILL]; 23644341Shibler if (tios.c_lflag & ICANON) { 23744341Shibler tios.c_cc[VEOF] = tiop->c_cc[HPUXVEOF]; 23844341Shibler tios.c_cc[VEOL] = tiop->c_cc[HPUXVEOL]; 23944341Shibler } else { 24044341Shibler tios.c_cc[VMIN] = tiop->c_cc[HPUXVMIN]; 24144341Shibler tios.c_cc[VTIME] = tiop->c_cc[HPUXVTIME]; 24241486Smckusick } 24344341Shibler /* 24444341Shibler * Set the new stuff 24544341Shibler */ 24641486Smckusick if (com == HPUXTCSETA) 24744341Shibler com = TIOCSETA; 24844341Shibler else if (com == HPUXTCSETAW) 24944341Shibler com = TIOCSETAW; 25041486Smckusick else 25144341Shibler com = TIOCSETAF; 25244341Shibler error = (*ioctlrout)(fp, com, (caddr_t)&tios); 25344341Shibler if (error == 0) { 25444341Shibler /* 25544341Shibler * Set line discipline 25644341Shibler */ 25744341Shibler line = tiop->c_line; 25844341Shibler (void) (*ioctlrout)(fp, TIOCSETD, (caddr_t)&line); 25944341Shibler /* 26044341Shibler * Set non-blocking IO if VMIN == VTIME == 0. 26144341Shibler * Should handle the other cases as well. It also 26244341Shibler * isn't correct to just turn it off as it could be 26344341Shibler * on as the result of a fcntl operation. 26444341Shibler * XXX - wouldn't need to do this at all if VMIN/VTIME 26544341Shibler * were implemented. 26644341Shibler */ 26744341Shibler line = (tiop->c_cc[HPUXVMIN] == 0 && 26844341Shibler tiop->c_cc[HPUXVTIME] == 0); 26944341Shibler (void) fset(fp, FNDELAY, line); 27044341Shibler } 27141486Smckusick break; 27241486Smckusick 27341486Smckusick default: 27443453Shibler error = EINVAL; 27541486Smckusick break; 27641486Smckusick } 27743453Shibler return(error); 27841486Smckusick } 27941486Smckusick 28044341Shibler bsdtohpuxbaud(bsdspeed) 28144341Shibler long bsdspeed; 28244341Shibler { 28344341Shibler switch (bsdspeed) { 28444341Shibler case B0: return(TIO_B0); 28544341Shibler case B50: return(TIO_B50); 28644341Shibler case B75: return(TIO_B75); 28744341Shibler case B110: return(TIO_B110); 28844341Shibler case B134: return(TIO_B134); 28944341Shibler case B150: return(TIO_B150); 29044341Shibler case B200: return(TIO_B200); 29144341Shibler case B300: return(TIO_B300); 29244341Shibler case B600: return(TIO_B600); 29344341Shibler case B1200: return(TIO_B1200); 29444341Shibler case B1800: return(TIO_B1800); 29544341Shibler case B2400: return(TIO_B2400); 29644341Shibler case B4800: return(TIO_B4800); 29744341Shibler case B9600: return(TIO_B9600); 29844341Shibler case B19200: return(TIO_B19200); 29944341Shibler case B38400: return(TIO_B38400); 30044341Shibler default: return(TIO_B0); 30144341Shibler } 30244341Shibler } 30344341Shibler 30444341Shibler hpuxtobsdbaud(hpuxspeed) 30544341Shibler int hpuxspeed; 30644341Shibler { 30744341Shibler static char hpuxtobsdbaudtab[32] = { 30844341Shibler B0, B50, B75, B110, B134, B150, B200, B300, 30944341Shibler B600, B0, B1200, B1800, B2400, B0, B4800, B0, 31044341Shibler B9600, B19200, B38400, B0, B0, B0, B0, B0, 31144341Shibler B0, B0, B0, B0, B0, B0, EXTA, EXTB 31244341Shibler }; 31344341Shibler 31444341Shibler return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]); 31544341Shibler } 31644341Shibler 31741486Smckusick /* #ifdef COMPAT */ 31843453Shibler ohpuxgtty(p, uap, retval) 31943453Shibler struct proc *p; 32043453Shibler struct args { 32141486Smckusick int fdes; 32241486Smckusick caddr_t cmarg; 32343453Shibler } *uap; 32443453Shibler int *retval; 32543453Shibler { 32641486Smckusick 327*45923Smckusick return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg)); 32841486Smckusick } 32941486Smckusick 33043453Shibler ohpuxstty(p, uap, retval) 33143453Shibler struct proc *p; 33243453Shibler struct args { 33341486Smckusick int fdes; 33441486Smckusick caddr_t cmarg; 33543453Shibler } *uap; 33643453Shibler int *retval; 33743453Shibler { 33841486Smckusick 339*45923Smckusick return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg)); 34041486Smckusick } 34141486Smckusick 34241486Smckusick /* 34341486Smckusick * Simplified version of ioctl() for use by 34441486Smckusick * gtty/stty and TIOCGETP/TIOCSETP. 34541486Smckusick */ 346*45923Smckusick getsettty(p, fdes, com, cmarg) 347*45923Smckusick struct proc *p; 34841486Smckusick int fdes, com; 34941486Smckusick caddr_t cmarg; 35041486Smckusick { 351*45923Smckusick register struct filedesc *fdp = p->p_fd; 35241486Smckusick register struct file *fp; 35341486Smckusick struct hpuxsgttyb hsb; 35441486Smckusick struct sgttyb sb; 35543453Shibler int error; 35641486Smckusick 357*45923Smckusick if (((unsigned)fdes) >= fdp->fd_maxfiles || 358*45923Smckusick (fp = OFILE(fdp, fdes)) == NULL) 35943453Shibler return (EBADF); 36043453Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 36143453Shibler return (EBADF); 36241486Smckusick if (com == HPUXTIOCSETP) { 36343453Shibler if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb)) 36443453Shibler return (error); 36541486Smckusick sb.sg_ispeed = hsb.sg_ispeed; 36641486Smckusick sb.sg_ospeed = hsb.sg_ospeed; 36741486Smckusick sb.sg_erase = hsb.sg_erase; 36841486Smckusick sb.sg_kill = hsb.sg_kill; 36943453Shibler sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 37043453Shibler if (hsb.sg_flags & V7_XTABS) 37143453Shibler sb.sg_flags |= XTABS; 37243453Shibler if (hsb.sg_flags & V7_HUPCL) 37343453Shibler (void)(*fp->f_ops->fo_ioctl)(fp, TIOCHPCL, (caddr_t)0); 37441486Smckusick com = TIOCSETP; 37541486Smckusick } else { 37641486Smckusick bzero((caddr_t)&hsb, sizeof hsb); 37741486Smckusick com = TIOCGETP; 37841486Smckusick } 37943453Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb); 38043453Shibler if (error == 0 && com == TIOCGETP) { 38141486Smckusick hsb.sg_ispeed = sb.sg_ispeed; 38241486Smckusick hsb.sg_ospeed = sb.sg_ospeed; 38341486Smckusick hsb.sg_erase = sb.sg_erase; 38441486Smckusick hsb.sg_kill = sb.sg_kill; 38543453Shibler hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL); 38643453Shibler if (sb.sg_flags & XTABS) 38743453Shibler hsb.sg_flags |= V7_XTABS; 38843453Shibler error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 38941486Smckusick } 39043453Shibler return (error); 39141486Smckusick } 39241486Smckusick /* #endif */ 39341486Smckusick #endif 394