xref: /csrg-svn/sys/kern/tty_pty.c (revision 4935)
1*4935Swnj /*	tty_pty.c	4.10	81/11/18	*/
22283Stoy 
32281Stoy /*
42281Stoy  * Pseudo-teletype Driver
52281Stoy  * (Actually two drivers, requiring two entries in 'cdevsw')
62281Stoy  */
72314Stoy #include "pty.h"
82314Stoy 
93206Swnj #if NPTY > 0
102314Stoy 
112281Stoy #include "../h/param.h"
122281Stoy #include "../h/systm.h"
132281Stoy #include "../h/tty.h"
142281Stoy #include "../h/dir.h"
152281Stoy #include "../h/user.h"
162281Stoy #include "../h/conf.h"
172281Stoy #include "../h/buf.h"
182427Swnj #include "../h/file.h"
194484Swnj #include "../h/proc.h"
202281Stoy 
214484Swnj #undef	NPTY
224484Swnj #define NPTY 16
234484Swnj 
242427Swnj #define BUFSIZ 100		/* Chunk size iomoved from user */
254484Swnj 
262281Stoy /*
274484Swnj  * pts == /dev/tty[pP]?
284484Swnj  * ptc == /dev/ptp[pP]?
292281Stoy  */
304484Swnj struct	tty pt_tty[NPTY];
314484Swnj struct	pt_ioctl {
324484Swnj 	int	pti_flags;
334484Swnj 	struct	clist pti_ioctl, pti_ioans;
344484Swnj 	int	pti_gensym;
354484Swnj 	struct	proc *pti_selr;
364484Swnj } pt_ioctl[NPTY];
372281Stoy 
384484Swnj #define	PTCRCOLL	0x01
392281Stoy 
402281Stoy /*ARGSUSED*/
412281Stoy ptsopen(dev, flag)
422281Stoy dev_t dev;
434484Swnj {
442281Stoy 	register struct tty *tp;
452281Stoy 
464484Swnj 	if (minor(dev) >= NPTY) {
472281Stoy 		u.u_error = ENXIO;
482281Stoy 		return;
492281Stoy 	}
502281Stoy 	tp = &pt_tty[minor(dev)];
514484Swnj 	if ((tp->t_state & ISOPEN) == 0) {
522427Swnj 		ttychars(tp);		/* Set up default chars */
532427Swnj 		tp->t_flags = 0;	/* No features (nor raw mode) */
544484Swnj 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
552281Stoy 		u.u_error = EBUSY;
562281Stoy 		return;
572281Stoy 	}
584484Swnj 	if (tp->t_oproc)			/* Ctrlr still around. */
592281Stoy 		tp->t_state |= CARR_ON;
604484Swnj 	while ((tp->t_state & CARR_ON) == 0) {
612281Stoy 		tp->t_state |= WOPEN;
622281Stoy 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
632281Stoy 	}
642281Stoy 	(*linesw[tp->t_line].l_open)(dev, tp);
652281Stoy }
662281Stoy 
672281Stoy ptsclose(dev)
682281Stoy dev_t dev;
692427Swnj {					/* Close slave part of PTY */
702281Stoy 	register struct tty *tp;
712281Stoy 
722281Stoy 	tp = &pt_tty[minor(dev)];
732281Stoy 	(*linesw[tp->t_line].l_close)(tp);
742281Stoy }
752281Stoy 
762281Stoy ptsread(dev)
772281Stoy dev_t dev;
784484Swnj {
794484Swnj 	register struct tty *tp;
802281Stoy 
812281Stoy 	tp = &pt_tty[minor(dev)];
824484Swnj 	if (tp->t_oproc) {
832281Stoy 		(*linesw[tp->t_line].l_read)(tp);
842281Stoy 		wakeup((caddr_t)&tp->t_rawq.c_cf);
852281Stoy 	}
862281Stoy }
872281Stoy 
882281Stoy ptswrite(dev)
892281Stoy dev_t dev;
904484Swnj {
912281Stoy 	register struct tty *tp;
922281Stoy 
932281Stoy 	tp = &pt_tty[minor(dev)];
944484Swnj 	if (tp->t_oproc)
952281Stoy 		(*linesw[tp->t_line].l_write)(tp);
962281Stoy }
972281Stoy 
982281Stoy ptsstart(tp)
994484Swnj 	struct tty *tp;
1004484Swnj {
1014484Swnj 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
1024484Swnj 
1034484Swnj 	if (tp->t_state & TTSTOP)
1042281Stoy 		return;
1054484Swnj 	if (pti->pti_selr) {
1064484Swnj 		selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL);
1074484Swnj 		pti->pti_selr = 0;
1084484Swnj 		pti->pti_flags &= ~PTCRCOLL;
1094484Swnj 	}
1102281Stoy 	wakeup((caddr_t)&tp->t_outq.c_cf);
1112281Stoy }
1122281Stoy 
1132281Stoy /*ARGSUSED*/
1142281Stoy ptcopen(dev, flag)
1154484Swnj 	dev_t dev;
1164484Swnj 	int flag;
1174484Swnj {
1182281Stoy 	register struct tty *tp;
1192281Stoy 
1204484Swnj 	if (minor(dev) >= NPTY) {
1212281Stoy 		u.u_error = ENXIO;
1222281Stoy 		return;
1232281Stoy 	}
1242281Stoy 	tp = &pt_tty[minor(dev)];
1254484Swnj 	if (tp->t_oproc) {
1262281Stoy 		u.u_error = EIO;
1272281Stoy 		return;
1282281Stoy 	}
1294484Swnj 	tp->t_oproc = ptsstart;
1304484Swnj 	if (tp->t_state & WOPEN)
1312281Stoy 		wakeup((caddr_t)&tp->t_rawq);
1322281Stoy 	tp->t_state |= CARR_ON;
1332281Stoy }
1342281Stoy 
1352281Stoy ptcclose(dev)
1364484Swnj 	dev_t dev;
1374484Swnj {
1382281Stoy 	register struct tty *tp;
1392281Stoy 
1402281Stoy 	tp = &pt_tty[minor(dev)];
1414484Swnj 	if (tp->t_state & ISOPEN)
1422281Stoy 		gsignal(tp->t_pgrp, SIGHUP);
1434484Swnj 	tp->t_state &= ~CARR_ON;	/* virtual carrier gone */
1444484Swnj 	flushtty(tp, FREAD|FWRITE);
1454484Swnj 	tp->t_oproc = 0;		/* mark closed */
1462281Stoy }
1472281Stoy 
1482281Stoy ptcread(dev)
1492281Stoy dev_t dev;
1504484Swnj {
1512281Stoy 	register struct tty *tp;
1522281Stoy 
1532281Stoy 	tp = &pt_tty[minor(dev)];
1544484Swnj 	if ((tp->t_state&(CARR_ON|ISOPEN)) == 0)
1552281Stoy 		return;
1564484Swnj 	while (tp->t_outq.c_cc == 0 || (tp->t_state&TTSTOP))
1572281Stoy 		sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI);
1584484Swnj 	while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0);
1594484Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)  && (tp->t_state&ASLEEP)) {
1602281Stoy 		tp->t_state &= ~ASLEEP;
1614484Swnj 		wakeup((caddr_t)&tp->t_outq);
1622281Stoy 	}
1632281Stoy }
1642281Stoy 
1654484Swnj ptcselect(dev)
1664484Swnj 	dev_t dev;
1674484Swnj {
1684484Swnj 	register struct tty *tp = &pt_tty[minor(dev)];
1694484Swnj 	struct pt_ioctl *pti;
1704484Swnj 	struct proc *p;
1714484Swnj 
1724484Swnj 	if ((tp->t_state&(CARR_ON|ISOPEN)) == 0)
1734484Swnj 		return (1);
1744484Swnj 	if (tp->t_outq.c_cc)
1754484Swnj 		return (1);
1764484Swnj 	pti = &pt_ioctl[minor(dev)];
177*4935Swnj 	if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait)
1784484Swnj 		pti->pti_flags |= PTCRCOLL;
1794484Swnj 	else
1804484Swnj 		pti->pti_selr = u.u_procp;
1814484Swnj 	return (0);
1824484Swnj }
1834484Swnj 
1842281Stoy ptcwrite(dev)
1852281Stoy dev_t dev;
1864484Swnj {
1872281Stoy 	register struct tty *tp;
1882281Stoy 	register char *cp, *ce;
1892281Stoy 	register int cc;
1902281Stoy 	char locbuf[BUFSIZ];
1912281Stoy 
1922281Stoy 	tp = &pt_tty[minor(dev)];
1934484Swnj 	if ((tp->t_state&(CARR_ON|ISOPEN)) == 0)
1942281Stoy 		return;
1954484Swnj 	while (u.u_count) {
1962281Stoy 		cc = MIN(u.u_count, BUFSIZ);
1972281Stoy 		cp = locbuf;
1982281Stoy 		iomove(cp, (unsigned)cc, B_WRITE);
1994484Swnj 		if (u.u_error)
2002281Stoy 			break;
2012281Stoy 		ce = cp + cc;
2024484Swnj 		while (cp < ce) {
2034484Swnj 			while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) {
2042281Stoy 				wakeup((caddr_t)&tp->t_rawq);
2052281Stoy 				/* Better than just flushing it! */
2062281Stoy 				/* Wait for something to be read */
2072281Stoy 				sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI);
2082281Stoy 			}
2094141Secc 			(*linesw[tp->t_line].l_rint)(*cp++, tp);
2102281Stoy 		}
2112281Stoy 	}
2122281Stoy }
2132281Stoy 
2142281Stoy /*ARGSUSED*/
2152281Stoy ptyioctl(dev, cmd, addr, flag)
2164484Swnj 	caddr_t addr;
2174484Swnj 	dev_t dev;
2184484Swnj {
2192281Stoy 	register struct tty *tp;
2202281Stoy 
2212281Stoy 	tp = &pt_tty[minor(dev)];
2224484Swnj 	/* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */
2234484Swnj 	if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP)
2244484Swnj 		while (getc(&tp->t_outq) >= 0);
2254484Swnj 	if (ttioctl(tp, cmd, addr, dev) == 0)
2262281Stoy 		u.u_error = ENOTTY;
2272281Stoy }
2282313Stoy #endif
229