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 * 12*45423Smckusick * from: Utah $Hdr: hpux_tty.c 1.1 90/07/09$ 1341486Smckusick * 14*45423Smckusick * @(#)hpux_tty.c 7.5 (Berkeley) 10/24/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 /* 3844341Shibler * 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 { 4444341Shibler struct termios tios; 4544341Shibler 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: 5244341Shibler /* 5344341Shibler * Get BSD terminal state 5444341Shibler */ 5541486Smckusick bzero(data, sizeof(struct hpuxtermio)); 5644341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 5741486Smckusick break; 5844341Shibler /* 5944341Shibler * Set iflag. 6044341Shibler * Same through ICRNL, no BSD equivs for IUCLC, IENQAK 6144341Shibler */ 6244341Shibler tiop->c_iflag = tios.c_iflag & 0x1ff; 6344341Shibler if (tios.c_iflag & IXON) 6444341Shibler tiop->c_iflag |= TIO_IXON; 6544341Shibler if (tios.c_iflag & IXOFF) 6644341Shibler tiop->c_iflag |= TIO_IXOFF; 6744341Shibler if (tios.c_iflag & IXANY) 6844341Shibler tiop->c_iflag |= TIO_IXANY; 6944341Shibler /* 7044341Shibler * Set oflag. 7144341Shibler * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL 7244341Shibler * or any of the delays. 7344341Shibler */ 7444341Shibler if (tios.c_oflag & OPOST) 7544341Shibler tiop->c_oflag |= TIO_OPOST; 7644341Shibler if (tios.c_oflag & ONLCR) 7744341Shibler tiop->c_oflag |= TIO_ONLCR; 7844341Shibler if (tios.c_oflag & OXTABS) 7941486Smckusick tiop->c_oflag |= TIO_TAB3; 8044341Shibler /* 8144341Shibler * Set cflag. 8244341Shibler * Baud from ospeed, rest from cflag. 8344341Shibler */ 8444341Shibler tiop->c_cflag = bsdtohpuxbaud(tios.c_ospeed); 8544341Shibler switch (tios.c_cflag & CSIZE) { 8644341Shibler case CS5: 8744341Shibler tiop->c_cflag |= TIO_CS5; break; 8844341Shibler case CS6: 8944341Shibler tiop->c_cflag |= TIO_CS6; break; 9044341Shibler case CS7: 9144341Shibler tiop->c_cflag |= TIO_CS7; break; 9244341Shibler case CS8: 9344341Shibler tiop->c_cflag |= TIO_CS8; break; 9441486Smckusick } 9544341Shibler if (tios.c_cflag & CSTOPB) 9644341Shibler tiop->c_cflag |= TIO_CSTOPB; 9744341Shibler if (tios.c_cflag & CREAD) 9844341Shibler tiop->c_cflag |= TIO_CREAD; 9944341Shibler if (tios.c_cflag & PARENB) 10044341Shibler tiop->c_cflag |= TIO_PARENB; 10144341Shibler if (tios.c_cflag & PARODD) 10244341Shibler tiop->c_cflag |= TIO_PARODD; 10344341Shibler if (tios.c_cflag & HUPCL) 10444341Shibler tiop->c_cflag |= TIO_HUPCL; 10544341Shibler if (tios.c_cflag & CLOCAL) 10644341Shibler tiop->c_cflag |= TIO_CLOCAL; 10744341Shibler /* 10844341Shibler * Set lflag. 10944341Shibler * No BSD equiv for XCASE. 11044341Shibler */ 11144341Shibler if (tios.c_lflag & ECHOE) 11244341Shibler tiop->c_lflag |= TIO_ECHOE; 11344341Shibler if (tios.c_lflag & ECHOK) 11444341Shibler tiop->c_lflag |= TIO_ECHOK; 11544341Shibler if (tios.c_lflag & ECHO) 11641486Smckusick tiop->c_lflag |= TIO_ECHO; 11744341Shibler if (tios.c_lflag & ECHONL) 11844341Shibler tiop->c_lflag |= TIO_ECHONL; 11944341Shibler if (tios.c_lflag & ISIG) 12044341Shibler tiop->c_lflag |= TIO_ISIG; 12144341Shibler if (tios.c_lflag & ICANON) 12244341Shibler tiop->c_lflag |= TIO_ICANON; 12344341Shibler if (tios.c_lflag & NOFLSH) 12444341Shibler tiop->c_lflag |= TIO_NOFLSH; 12544341Shibler /* 12644341Shibler * Line discipline 12744341Shibler */ 12844341Shibler line = 0; 12944341Shibler (void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line); 13044341Shibler tiop->c_line = line; 13144341Shibler /* 13244341Shibler * Set editing chars 13344341Shibler */ 13444341Shibler tiop->c_cc[HPUXVINTR] = tios.c_cc[VINTR]; 13544341Shibler tiop->c_cc[HPUXVQUIT] = tios.c_cc[VQUIT]; 13644341Shibler tiop->c_cc[HPUXVERASE] = tios.c_cc[VERASE]; 13744341Shibler tiop->c_cc[HPUXVKILL] = tios.c_cc[VKILL]; 13844341Shibler if (tiop->c_lflag & TIO_ICANON) { 13944341Shibler tiop->c_cc[HPUXVEOF] = tios.c_cc[VEOF]; 14044341Shibler tiop->c_cc[HPUXVEOL] = tios.c_cc[VEOL]; 14141486Smckusick } else { 14244341Shibler tiop->c_cc[HPUXVMIN] = tios.c_cc[VMIN]; 14344341Shibler tiop->c_cc[HPUXVTIME] = tios.c_cc[VTIME]; 14441486Smckusick } 14541486Smckusick break; 14641486Smckusick 14741486Smckusick case HPUXTCSETA: 14841486Smckusick case HPUXTCSETAW: 14941486Smckusick case HPUXTCSETAF: 15044341Shibler /* 15144341Shibler * Get old characteristics and determine if we are a tty. 15244341Shibler */ 15344341Shibler if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios)) 15441486Smckusick break; 15544341Shibler /* 15644341Shibler * Set iflag. 15744341Shibler * Same through ICRNL, no HP-UX equiv for IMAXBEL 15844341Shibler */ 15944341Shibler tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff); 16044341Shibler tios.c_iflag |= tiop->c_iflag & 0x1ff; 16144341Shibler if (tiop->c_iflag & TIO_IXON) 16244341Shibler tios.c_iflag |= IXON; 16344341Shibler if (tiop->c_iflag & TIO_IXOFF) 16444341Shibler tios.c_iflag |= IXOFF; 16544341Shibler if (tiop->c_iflag & TIO_IXANY) 16644341Shibler tios.c_iflag |= IXANY; 16744341Shibler /* 16844341Shibler * Set oflag. 16944341Shibler * No HP-UX equiv for ONOEOT 17044341Shibler */ 17144341Shibler tios.c_oflag &= ~(OPOST|ONLCR|OXTABS); 17244341Shibler if (tiop->c_oflag & TIO_OPOST) 17344341Shibler tios.c_oflag |= OPOST; 17444341Shibler if (tiop->c_oflag & TIO_ONLCR) 17544341Shibler tios.c_oflag |= ONLCR; 17644341Shibler if (tiop->c_oflag & TIO_TAB3) 17744341Shibler tios.c_oflag |= OXTABS; 17844341Shibler /* 17944341Shibler * Set cflag. 18044341Shibler * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF 18144341Shibler */ 18244341Shibler tios.c_cflag &= 18344341Shibler ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL); 18444341Shibler switch (tiop->c_cflag & TIO_CSIZE) { 18544341Shibler case TIO_CS5: 18644341Shibler tios.c_cflag |= CS5; break; 18744341Shibler case TIO_CS6: 18844341Shibler tios.c_cflag |= CS6; break; 18944341Shibler case TIO_CS7: 19044341Shibler tios.c_cflag |= CS7; break; 19144341Shibler case TIO_CS8: 19244341Shibler tios.c_cflag |= CS8; break; 19341486Smckusick } 19444341Shibler if (tiop->c_cflag & TIO_CSTOPB) 19544341Shibler tios.c_cflag |= CSTOPB; 19644341Shibler if (tiop->c_cflag & TIO_CREAD) 19744341Shibler tios.c_cflag |= CREAD; 19844341Shibler if (tiop->c_cflag & TIO_PARENB) 19944341Shibler tios.c_cflag |= PARENB; 20044341Shibler if (tiop->c_cflag & TIO_PARODD) 20144341Shibler tios.c_cflag |= PARODD; 20244341Shibler if (tiop->c_cflag & TIO_HUPCL) 20344341Shibler tios.c_cflag |= HUPCL; 20444341Shibler if (tiop->c_cflag & TIO_CLOCAL) 20544341Shibler tios.c_cflag |= CLOCAL; 20644341Shibler /* 20744341Shibler * Set lflag. 20844341Shibler * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL 20944341Shibler * IEXTEN treated as part of ICANON 21044341Shibler */ 21144341Shibler tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH); 21244341Shibler if (tiop->c_lflag & TIO_ECHOE) 21344341Shibler tios.c_lflag |= ECHOE; 21444341Shibler if (tiop->c_lflag & TIO_ECHOK) 21544341Shibler tios.c_lflag |= ECHOK; 21641486Smckusick if (tiop->c_lflag & TIO_ECHO) 21744341Shibler tios.c_lflag |= ECHO; 21844341Shibler if (tiop->c_lflag & TIO_ECHONL) 21944341Shibler tios.c_lflag |= ECHONL; 22044341Shibler if (tiop->c_lflag & TIO_ISIG) 22144341Shibler tios.c_lflag |= ISIG; 22244341Shibler if (tiop->c_lflag & TIO_ICANON) 22344341Shibler tios.c_lflag |= (ICANON|IEXTEN); 22444341Shibler if (tiop->c_lflag & TIO_NOFLSH) 22544341Shibler tios.c_lflag |= NOFLSH; 22644341Shibler /* 22744341Shibler * Set editing chars. 22844341Shibler * No HP-UX equivs of VEOL2/VWERASE/VREPRINT/VSUSP/VDSUSP 22944341Shibler * VSTOP/VLNEXT/VDISCARD/VMIN/VTIME/VSTATUS/VERASE2 23044341Shibler */ 23144341Shibler tios.c_cc[VINTR] = tiop->c_cc[HPUXVINTR]; 23244341Shibler tios.c_cc[VQUIT] = tiop->c_cc[HPUXVQUIT]; 23344341Shibler tios.c_cc[VERASE] = tiop->c_cc[HPUXVERASE]; 23444341Shibler tios.c_cc[VKILL] = tiop->c_cc[HPUXVKILL]; 23544341Shibler if (tios.c_lflag & ICANON) { 23644341Shibler tios.c_cc[VEOF] = tiop->c_cc[HPUXVEOF]; 23744341Shibler tios.c_cc[VEOL] = tiop->c_cc[HPUXVEOL]; 23844341Shibler } else { 23944341Shibler tios.c_cc[VMIN] = tiop->c_cc[HPUXVMIN]; 24044341Shibler tios.c_cc[VTIME] = tiop->c_cc[HPUXVTIME]; 24141486Smckusick } 24244341Shibler /* 24344341Shibler * Set the new stuff 24444341Shibler */ 24541486Smckusick if (com == HPUXTCSETA) 24644341Shibler com = TIOCSETA; 24744341Shibler else if (com == HPUXTCSETAW) 24844341Shibler com = TIOCSETAW; 24941486Smckusick else 25044341Shibler com = TIOCSETAF; 25144341Shibler error = (*ioctlrout)(fp, com, (caddr_t)&tios); 25244341Shibler if (error == 0) { 25344341Shibler /* 25444341Shibler * Set line discipline 25544341Shibler */ 25644341Shibler line = tiop->c_line; 25744341Shibler (void) (*ioctlrout)(fp, TIOCSETD, (caddr_t)&line); 25844341Shibler /* 25944341Shibler * Set non-blocking IO if VMIN == VTIME == 0. 26044341Shibler * Should handle the other cases as well. It also 26144341Shibler * isn't correct to just turn it off as it could be 26244341Shibler * on as the result of a fcntl operation. 26344341Shibler * XXX - wouldn't need to do this at all if VMIN/VTIME 26444341Shibler * were implemented. 26544341Shibler */ 26644341Shibler line = (tiop->c_cc[HPUXVMIN] == 0 && 26744341Shibler tiop->c_cc[HPUXVTIME] == 0); 26844341Shibler (void) fset(fp, FNDELAY, line); 26944341Shibler } 27041486Smckusick break; 27141486Smckusick 27241486Smckusick default: 27343453Shibler error = EINVAL; 27441486Smckusick break; 27541486Smckusick } 27643453Shibler return(error); 27741486Smckusick } 27841486Smckusick 27944341Shibler bsdtohpuxbaud(bsdspeed) 28044341Shibler long bsdspeed; 28144341Shibler { 28244341Shibler switch (bsdspeed) { 28344341Shibler case B0: return(TIO_B0); 28444341Shibler case B50: return(TIO_B50); 28544341Shibler case B75: return(TIO_B75); 28644341Shibler case B110: return(TIO_B110); 28744341Shibler case B134: return(TIO_B134); 28844341Shibler case B150: return(TIO_B150); 28944341Shibler case B200: return(TIO_B200); 29044341Shibler case B300: return(TIO_B300); 29144341Shibler case B600: return(TIO_B600); 29244341Shibler case B1200: return(TIO_B1200); 29344341Shibler case B1800: return(TIO_B1800); 29444341Shibler case B2400: return(TIO_B2400); 29544341Shibler case B4800: return(TIO_B4800); 29644341Shibler case B9600: return(TIO_B9600); 29744341Shibler case B19200: return(TIO_B19200); 29844341Shibler case B38400: return(TIO_B38400); 29944341Shibler default: return(TIO_B0); 30044341Shibler } 30144341Shibler } 30244341Shibler 30344341Shibler hpuxtobsdbaud(hpuxspeed) 30444341Shibler int hpuxspeed; 30544341Shibler { 30644341Shibler static char hpuxtobsdbaudtab[32] = { 30744341Shibler B0, B50, B75, B110, B134, B150, B200, B300, 30844341Shibler B600, B0, B1200, B1800, B2400, B0, B4800, B0, 30944341Shibler B9600, B19200, B38400, B0, B0, B0, B0, B0, 31044341Shibler B0, B0, B0, B0, B0, B0, EXTA, EXTB 31144341Shibler }; 31244341Shibler 31344341Shibler return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]); 31444341Shibler } 31544341Shibler 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