xref: /csrg-svn/sys/hp/hpux/hpux_tty.c (revision 45923)
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