xref: /csrg-svn/sys/vax/uba/dz.c (revision 25397)
123326Smckusick /*
223326Smckusick  * Copyright (c) 1982 Regents of the University of California.
323326Smckusick  * All rights reserved.  The Berkeley software License Agreement
423326Smckusick  * specifies the terms and conditions for redistribution.
523326Smckusick  *
6*25397Skarels  *	@(#)dz.c	6.10 (Berkeley) 11/04/85
723326Smckusick  */
817Sbill 
91935Swnj #include "dz.h"
102645Swnj #if NDZ > 0
1117Sbill /*
1210019Ssam  *  DZ-11/DZ-32 Driver
132469Swnj  *
142469Swnj  * This driver mimics dh.c; see it for explanation of common code.
1517Sbill  */
162731Swnj #include "bk.h"
179773Ssam 
189773Ssam #include "../machine/pte.h"
199773Ssam 
2017123Sbloom #include "param.h"
2117123Sbloom #include "systm.h"
2217123Sbloom #include "ioctl.h"
2317123Sbloom #include "tty.h"
2417123Sbloom #include "dir.h"
2517123Sbloom #include "user.h"
2617123Sbloom #include "proc.h"
2717123Sbloom #include "map.h"
2817123Sbloom #include "buf.h"
2917123Sbloom #include "vm.h"
3017123Sbloom #include "conf.h"
3117123Sbloom #include "bkmac.h"
3217123Sbloom #include "file.h"
3317123Sbloom #include "uio.h"
3417123Sbloom #include "kernel.h"
3518313Sralph #include "syslog.h"
36145Sbill 
3717123Sbloom #include "pdma.h"
3817123Sbloom #include "ubavar.h"
3917123Sbloom #include "dzreg.h"
408474Sroot 
412469Swnj /*
422469Swnj  * Driver information for auto-configuration stuff.
432469Swnj  */
442606Swnj int	dzprobe(), dzattach(), dzrint();
452976Swnj struct	uba_device *dzinfo[NDZ];
462395Swnj u_short	dzstd[] = { 0 };
472395Swnj struct	uba_driver dzdriver =
482606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
492395Swnj 
502645Swnj #define	NDZLINE 	(NDZ*8)
5116191Skarels #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
522469Swnj 
532469Swnj int	dzstart(), dzxint(), dzdma();
54114Sbill int	ttrstrt();
552645Swnj struct	tty dz_tty[NDZLINE];
562645Swnj int	dz_cnt = { NDZLINE };
57119Sbill int	dzact;
5816191Skarels int	dzsilos;			/* mask of dz's with silo in use */
5916191Skarels int	dzchars[NDZ];			/* recent input count */
6016191Skarels int	dzrate[NDZ];			/* smoothed input count */
6116191Skarels int	dztimerintvl;			/* time interval for dztimer */
6216191Skarels int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
6316191Skarels int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
6417Sbill 
655731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
665731Sroot 
672469Swnj /*
682469Swnj  * Software copy of dzbrk since it isn't readable
692469Swnj  */
702645Swnj char	dz_brk[NDZ];
712645Swnj char	dzsoftCAR[NDZ];
725731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
7317Sbill 
742469Swnj /*
755731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
762469Swnj  * we have to use a timer to watch it.
772469Swnj  */
782469Swnj char	dz_timer;		/* timer started? */
792469Swnj 
802469Swnj /*
812469Swnj  * Pdma structures for fast output code
822469Swnj  */
832645Swnj struct	pdma dzpdma[NDZLINE];
842469Swnj 
852395Swnj char	dz_speeds[] =
866814Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
8717Sbill 
88*25397Skarels #ifndef	PORTSELECTOR
89*25397Skarels #define	ISPEED	B9600
906616Ssam #define	IFLAGS	(EVENP|ODDP|ECHO)
916616Ssam #else
926616Ssam #define	ISPEED	B4800
936616Ssam #define	IFLAGS	(EVENP|ODDP)
946616Ssam #endif
956616Ssam 
962606Swnj dzprobe(reg)
972395Swnj 	caddr_t reg;
982395Swnj {
992457Swnj 	register int br, cvec;
10010019Ssam 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
1012395Swnj 
1022606Swnj #ifdef lint
1033102Swnj 	br = 0; cvec = br; br = cvec;
1044933Swnj 	dzrint(0); dzxint((struct tty *)0);
1052606Swnj #endif
1065731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1075731Sroot 	if (dzaddr->dzcsr & DZ_32)
1085731Sroot 		dzaddr->dzlnen = 1;
1095731Sroot 	else
1105731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1112457Swnj 	DELAY(100000);
1125731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1132457Swnj 	if (cvec && cvec != 0x200)
1142457Swnj 		cvec -= 4;
11510019Ssam 	return (sizeof (struct dzdevice));
1162395Swnj }
1172395Swnj 
1182606Swnj dzattach(ui)
1192976Swnj 	register struct uba_device *ui;
1202395Swnj {
1212395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1222395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1232606Swnj 	register int cntr;
1242645Swnj 	extern dzscan();
1252395Swnj 
1262606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
12710019Ssam 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
1282395Swnj 		pdp->p_arg = (int)tp;
1292395Swnj 		pdp->p_fcn = dzxint;
1302395Swnj 		pdp++, tp++;
1312395Swnj 	}
1322567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1332627Swnj 	if (dz_timer == 0) {
1342627Swnj 		dz_timer++;
1352756Swnj 		timeout(dzscan, (caddr_t)0, hz);
13616191Skarels 		dztimerintvl = FASTTIMER;
1372627Swnj 	}
1382395Swnj }
1392395Swnj 
14017Sbill /*ARGSUSED*/
1412395Swnj dzopen(dev, flag)
1422395Swnj 	dev_t dev;
14317Sbill {
14417Sbill 	register struct tty *tp;
1452395Swnj 	register int unit;
14617Sbill 
1472395Swnj 	unit = minor(dev);
1488568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
1498568Sroot 		return (ENXIO);
1502395Swnj 	tp = &dz_tty[unit];
1512395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
15217Sbill 	tp->t_oproc = dzstart;
1535407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
15417Sbill 		ttychars(tp);
1556616Ssam 		tp->t_ospeed = tp->t_ispeed = ISPEED;
1566616Ssam 		tp->t_flags = IFLAGS;
1575407Swnj 		/* tp->t_state |= TS_HUPCLS; */
1582395Swnj 		dzparam(unit);
1598568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
1608568Sroot 		return (EBUSY);
1616157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
162114Sbill 	(void) spl5();
1635407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
1645407Swnj 		tp->t_state |= TS_WOPEN;
16517Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
16617Sbill 	}
167114Sbill 	(void) spl0();
1688568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
16917Sbill }
17017Sbill 
1712395Swnj /*ARGSUSED*/
1722395Swnj dzclose(dev, flag)
1732395Swnj 	dev_t dev;
17417Sbill {
17517Sbill 	register struct tty *tp;
1762395Swnj 	register int unit;
17710019Ssam 	register struct dzdevice *dzaddr;
1786150Ssam 	int dz;
17917Sbill 
1802395Swnj 	unit = minor(dev);
1812395Swnj 	dz = unit >> 3;
1822395Swnj 	tp = &dz_tty[unit];
18317Sbill 	(*linesw[tp->t_line].l_close)(tp);
1845731Sroot 	dzaddr = dzpdma[unit].p_addr;
1855731Sroot 	if (dzaddr->dzcsr&DZ_32)
1866157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
1875731Sroot 	else
1885731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
1896842Swnj 	if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
1906157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
19117Sbill 	ttyclose(tp);
19217Sbill }
19317Sbill 
1947727Sroot dzread(dev, uio)
1952395Swnj 	dev_t dev;
1967727Sroot 	struct uio *uio;
19717Sbill {
19817Sbill 	register struct tty *tp;
19917Sbill 
2002395Swnj 	tp = &dz_tty[minor(dev)];
2017727Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
20217Sbill }
20317Sbill 
2047833Sroot dzwrite(dev, uio)
2052395Swnj 	dev_t dev;
2067833Sroot 	struct uio *uio;
20717Sbill {
20817Sbill 	register struct tty *tp;
20917Sbill 
2102395Swnj 	tp = &dz_tty[minor(dev)];
2118531Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
21217Sbill }
21317Sbill 
214119Sbill /*ARGSUSED*/
2152395Swnj dzrint(dz)
2162395Swnj 	int dz;
21717Sbill {
21817Sbill 	register struct tty *tp;
21917Sbill 	register int c;
22010019Ssam 	register struct dzdevice *dzaddr;
221119Sbill 	register struct tty *tp0;
2222395Swnj 	register int unit;
2232923Swnj 	int overrun = 0;
22417Sbill 
2252457Swnj 	if ((dzact & (1<<dz)) == 0)
2262457Swnj 		return;
2272457Swnj 	unit = dz * 8;
2282457Swnj 	dzaddr = dzpdma[unit].p_addr;
2292457Swnj 	tp0 = &dz_tty[unit];
2305731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2315731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2325731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2335731Sroot 		c = dzaddr->dzmtsr;
2345731Sroot 		tp = tp0 + (c&7);
2355731Sroot 		if (tp >= &dz_tty[dz_cnt])
2365731Sroot 			break;
2375731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2385731Sroot 		dzwait(dzaddr);		/* wait for them */
2395731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2405731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
241*25397Skarels 			/* carrier present */
242*25397Skarels 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
243*25397Skarels 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
244*25397Skarels 			dzaddr->dzlcs = DZ_ACK|(c&7);
2455731Sroot 	}
2462457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
24716191Skarels 		dzchars[dz]++;
2482457Swnj 		tp = tp0 + ((c>>8)&07);
2492457Swnj 		if (tp >= &dz_tty[dz_cnt])
25017Sbill 			continue;
2515407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2522457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2536616Ssam #ifdef PORTSELECTOR
2546616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2556616Ssam #endif
256*25397Skarels 				continue;
2572457Swnj 		}
2582469Swnj 		if (c&DZ_FE)
2592457Swnj 			if (tp->t_flags & RAW)
2602469Swnj 				c = 0;
2612457Swnj 			else
2629551Ssam 				c = tp->t_intrc;
2632923Swnj 		if (c&DZ_DO && overrun == 0) {
26424843Seric 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2652923Swnj 			overrun = 1;
2662923Swnj 		}
2672469Swnj 		if (c&DZ_PE)
2682457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2692457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
27017Sbill 				continue;
2712731Swnj #if NBK > 0
2722457Swnj 		if (tp->t_line == NETLDISC) {
2732457Swnj 			c &= 0177;
2742457Swnj 			BKINPUT(c, tp);
2752457Swnj 		} else
2762731Swnj #endif
2772457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
27817Sbill 	}
27917Sbill }
28017Sbill 
28117Sbill /*ARGSUSED*/
2827631Ssam dzioctl(dev, cmd, data, flag)
2832395Swnj 	dev_t dev;
2847631Ssam 	caddr_t data;
28517Sbill {
28617Sbill 	register struct tty *tp;
2872395Swnj 	register int unit = minor(dev);
2882395Swnj 	register int dz = unit >> 3;
28910019Ssam 	register struct dzdevice *dzaddr;
2908568Sroot 	int error;
29117Sbill 
2922395Swnj 	tp = &dz_tty[unit];
2938568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
2948568Sroot 	if (error >= 0)
2958568Sroot 		return (error);
2968568Sroot 	error = ttioctl(tp, cmd, data, flag);
2978568Sroot 	if (error >= 0) {
29817563Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
29917563Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
3002395Swnj 			dzparam(unit);
3018568Sroot 		return (error);
3028568Sroot 	}
3038568Sroot 	switch (cmd) {
3042395Swnj 
305170Sbill 	case TIOCSBRK:
3065731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3075731Sroot 		if (dzaddr->dzcsr&DZ_32)
3086157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3095731Sroot 		else
3105731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
311170Sbill 		break;
3127631Ssam 
313170Sbill 	case TIOCCBRK:
3145731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3155731Sroot 		if (dzaddr->dzcsr&DZ_32)
3166157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3175731Sroot 		else
3185731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
319170Sbill 		break;
3207631Ssam 
321170Sbill 	case TIOCSDTR:
3226157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
323170Sbill 		break;
3247631Ssam 
325170Sbill 	case TIOCCDTR:
3266157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
327170Sbill 		break;
3287631Ssam 
3295731Sroot 	case TIOCMSET:
3307631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3315731Sroot 		break;
3327631Ssam 
3335731Sroot 	case TIOCMBIS:
3347631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3355731Sroot 		break;
3367631Ssam 
3375731Sroot 	case TIOCMBIC:
3387631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3395731Sroot 		break;
3407631Ssam 
3415731Sroot 	case TIOCMGET:
3427631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3435731Sroot 		break;
3447631Ssam 
345170Sbill 	default:
3468568Sroot 		return (ENOTTY);
347170Sbill 	}
3488568Sroot 	return (0);
34917Sbill }
3505731Sroot 
3515731Sroot dmtodz(bits)
3525731Sroot 	register int bits;
3535731Sroot {
3545731Sroot 	register int b;
3555731Sroot 
3565731Sroot 	b = (bits >>1) & 0370;
3575731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3585731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3595731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3605731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3615731Sroot 	return(b);
3625731Sroot }
3635731Sroot 
3645731Sroot dztodm(bits)
3655731Sroot 	register int bits;
3665731Sroot {
3675731Sroot 	register int b;
3685731Sroot 
3695731Sroot 	b = (bits << 1) & 0360;
3705731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3715731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3725731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3735731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3745731Sroot 	return(b);
3755731Sroot }
37617Sbill 
3772395Swnj dzparam(unit)
3782395Swnj 	register int unit;
37917Sbill {
38017Sbill 	register struct tty *tp;
38110019Ssam 	register struct dzdevice *dzaddr;
3822395Swnj 	register int lpr;
38317Sbill 
3842395Swnj 	tp = &dz_tty[unit];
3852395Swnj 	dzaddr = dzpdma[unit].p_addr;
38616191Skarels 	if (dzsilos & (1 << (unit >> 3)))
38716191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
38816191Skarels 	else
38916191Skarels 		dzaddr->dzcsr = DZ_IEN;
3902395Swnj 	dzact |= (1<<(unit>>3));
39117Sbill 	if (tp->t_ispeed == 0) {
3926157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
39317Sbill 		return;
39417Sbill 	}
3952395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
39624271Slepreau 	if (tp->t_flags & (RAW|LITOUT|PASS8))
39717Sbill 		lpr |= BITS8;
39817Sbill 	else
39917Sbill 		lpr |= (BITS7|PENABLE);
40017Sbill 	if ((tp->t_flags & EVENP) == 0)
40117Sbill 		lpr |= OPAR;
4022469Swnj 	if (tp->t_ispeed == B110)
4032469Swnj 		lpr |= TWOSB;
40417Sbill 	dzaddr->dzlpr = lpr;
40517Sbill }
40617Sbill 
40717Sbill dzxint(tp)
4082395Swnj 	register struct tty *tp;
40917Sbill {
41017Sbill 	register struct pdma *dp;
41116191Skarels 	register dz, unit;
41217Sbill 
4132395Swnj 	dp = (struct pdma *)tp->t_addr;
4145407Swnj 	tp->t_state &= ~TS_BUSY;
4155407Swnj 	if (tp->t_state & TS_FLUSH)
4165407Swnj 		tp->t_state &= ~TS_FLUSH;
4175731Sroot 	else {
418281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4195731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4205731Sroot 	}
42117Sbill 	if (tp->t_line)
42217Sbill 		(*linesw[tp->t_line].l_start)(tp);
42317Sbill 	else
42417Sbill 		dzstart(tp);
4255731Sroot 	dz = minor(tp->t_dev) >> 3;
4265731Sroot 	unit = minor(tp->t_dev) & 7;
4275407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4285731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4295731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4305731Sroot 		else
4315731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
43217Sbill }
43317Sbill 
43417Sbill dzstart(tp)
4352395Swnj 	register struct tty *tp;
43617Sbill {
43717Sbill 	register struct pdma *dp;
43810019Ssam 	register struct dzdevice *dzaddr;
4392395Swnj 	register int cc;
4405731Sroot 	int s, dz, unit;
44117Sbill 
4422395Swnj 	dp = (struct pdma *)tp->t_addr;
44317Sbill 	dzaddr = dp->p_addr;
4442395Swnj 	s = spl5();
4455407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
44617Sbill 		goto out;
4475407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
4485407Swnj 		if (tp->t_state&TS_ASLEEP) {
4495407Swnj 			tp->t_state &= ~TS_ASLEEP;
4505407Swnj 			wakeup((caddr_t)&tp->t_outq);
4515407Swnj 		}
4525407Swnj 		if (tp->t_wsel) {
4535407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4545407Swnj 			tp->t_wsel = 0;
4555407Swnj 			tp->t_state &= ~TS_WCOLL;
4565407Swnj 		}
45717Sbill 	}
45817Sbill 	if (tp->t_outq.c_cc == 0)
45917Sbill 		goto out;
4609551Ssam 	if (tp->t_flags & (RAW|LITOUT))
46117Sbill 		cc = ndqb(&tp->t_outq, 0);
46217Sbill 	else {
46317Sbill 		cc = ndqb(&tp->t_outq, 0200);
46417Sbill 		if (cc == 0) {
46517Sbill 			cc = getc(&tp->t_outq);
4662469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
4675407Swnj 			tp->t_state |= TS_TIMEOUT;
46817Sbill 			goto out;
46917Sbill 		}
47017Sbill 	}
4715407Swnj 	tp->t_state |= TS_BUSY;
47217Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
47317Sbill 	dp->p_end += cc;
4745731Sroot 	dz = minor(tp->t_dev) >> 3;
4755731Sroot 	unit = minor(tp->t_dev) & 7;
4765731Sroot 	if (dzaddr->dzcsr & DZ_32)
4775731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
4785731Sroot 	else
4795731Sroot 		dzaddr->dztcr |= (1<<unit);
4802395Swnj out:
4812395Swnj 	splx(s);
48217Sbill }
48317Sbill 
48417Sbill /*
48517Sbill  * Stop output on a line.
48617Sbill  */
48717Sbill /*ARGSUSED*/
48817Sbill dzstop(tp, flag)
4892395Swnj 	register struct tty *tp;
49017Sbill {
49117Sbill 	register struct pdma *dp;
49217Sbill 	register int s;
49317Sbill 
4942395Swnj 	dp = (struct pdma *)tp->t_addr;
4952457Swnj 	s = spl5();
4965407Swnj 	if (tp->t_state & TS_BUSY) {
49717Sbill 		dp->p_end = dp->p_mem;
4985407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
4995407Swnj 			tp->t_state |= TS_FLUSH;
50017Sbill 	}
50117Sbill 	splx(s);
50217Sbill }
50317Sbill 
5045731Sroot dzmctl(dev, bits, how)
5055731Sroot 	dev_t dev;
5065731Sroot 	int bits, how;
50717Sbill {
50810019Ssam 	register struct dzdevice *dzaddr;
5095731Sroot 	register int unit, mbits;
5105731Sroot 	int b, s;
5115731Sroot 
5125731Sroot 	unit = minor(dev);
5135731Sroot 	b = 1<<(unit&7);
5142395Swnj 	dzaddr = dzpdma[unit].p_addr;
5155731Sroot 	s = spl5();
5165731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5175731Sroot 		dzwait(dzaddr)
5185731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5195731Sroot 		dzaddr->dzlcs = unit&7;
5205731Sroot 		DELAY(100);
5215731Sroot 		dzwait(dzaddr)
5225731Sroot 		DELAY(100);
5235731Sroot 		mbits = dzaddr->dzlcs;
5245731Sroot 		mbits &= 0177770;
5255731Sroot 	} else {
5265731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5275731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5285731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5295731Sroot 	}
5305731Sroot 	switch (how) {
5315731Sroot 	case DMSET:
5325731Sroot 		mbits = bits;
5335731Sroot 		break;
5345731Sroot 
5355731Sroot 	case DMBIS:
5365731Sroot 		mbits |= bits;
5375731Sroot 		break;
5385731Sroot 
5395731Sroot 	case DMBIC:
5405731Sroot 		mbits &= ~bits;
5415731Sroot 		break;
5425731Sroot 
5435731Sroot 	case DMGET:
5445731Sroot 		(void) splx(s);
5455731Sroot 		return(mbits);
5465731Sroot 	}
5475731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5485731Sroot 		mbits |= DZ_ACK|(unit&7);
5495731Sroot 		dzaddr->dzlcs = mbits;
5505731Sroot 	} else {
5515731Sroot 		if (mbits & DZ_DTR)
5525731Sroot 			dzaddr->dzdtr |= b;
5535731Sroot 		else
5545731Sroot 			dzaddr->dzdtr &= ~b;
5555731Sroot 	}
5565731Sroot 	(void) splx(s);
5575731Sroot 	return(mbits);
55817Sbill }
55917Sbill 
56016191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
56117Sbill dzscan()
56217Sbill {
56317Sbill 	register i;
56410019Ssam 	register struct dzdevice *dzaddr;
56517Sbill 	register bit;
56617Sbill 	register struct tty *tp;
5675731Sroot 	register car;
56816191Skarels 	int olddzsilos = dzsilos;
56916191Skarels 	int dztimer();
57017Sbill 
57117Sbill 	for (i = 0; i < dz_cnt ; i++) {
57217Sbill 		dzaddr = dzpdma[i].p_addr;
5732627Swnj 		if (dzaddr == 0)
5742627Swnj 			continue;
57517Sbill 		tp = &dz_tty[i];
57617Sbill 		bit = 1<<(i&07);
5775731Sroot 		car = 0;
5785731Sroot 		if (dzsoftCAR[i>>3]&bit)
5795731Sroot 			car = 1;
5805731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
5815731Sroot 			dzaddr->dzlcs = i&07;
5825731Sroot 			dzwait(dzaddr);
5835731Sroot 			car = dzaddr->dzlcs & DZ_CD;
5845731Sroot 		} else
5855731Sroot 			car = dzaddr->dzmsr&bit;
5865731Sroot 		if (car) {
58717Sbill 			/* carrier present */
588*25397Skarels 			if ((tp->t_state & TS_CARR_ON) == 0)
589*25397Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
590*25397Skarels 		} else if ((tp->t_state&TS_CARR_ON) &&
591*25397Skarels 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
592*25397Skarels 			dzaddr->dzdtr &= ~bit;
59317Sbill 	}
59416191Skarels 	for (i = 0; i < NDZ; i++) {
59516191Skarels 		ave(dzrate[i], dzchars[i], 8);
59616191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
59716397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
59816191Skarels 			dzsilos |= (1 << i);
59916191Skarels 			dztransitions++;		/*DEBUG*/
60016191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
60116397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
60216191Skarels 			dzsilos &= ~(1 << i);
60316191Skarels 		}
60416191Skarels 		dzchars[i] = 0;
60516191Skarels 	}
60616191Skarels 	if (dzsilos && !olddzsilos)
60716191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
60816191Skarels 	timeout(dzscan, (caddr_t)0, hz);
60917Sbill }
610119Sbill 
611119Sbill dztimer()
612119Sbill {
6138160Sroot 	register int dz;
61416191Skarels 	register int s;
615119Sbill 
61616191Skarels 	if (dzsilos == 0)
61716191Skarels 		return;
61816191Skarels 	s = spl5();
61916191Skarels 	dzfasttimers++;		/*DEBUG*/
6202645Swnj 	for (dz = 0; dz < NDZ; dz++)
62116191Skarels 		if (dzsilos & (1 << dz))
62216191Skarels 		    dzrint(dz);
6238160Sroot 	splx(s);
62416191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
625119Sbill }
626281Sbill 
627281Sbill /*
628281Sbill  * Reset state of driver if UBA reset was necessary.
629301Sbill  * Reset parameters and restart transmission on open lines.
630281Sbill  */
6312395Swnj dzreset(uban)
6322422Skre 	int uban;
633281Sbill {
6342395Swnj 	register int unit;
635281Sbill 	register struct tty *tp;
6362976Swnj 	register struct uba_device *ui;
637281Sbill 
6382645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6392422Skre 		ui = dzinfo[unit >> 3];
6402422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6412422Skre 			continue;
6422923Swnj 		if (unit%8 == 0)
6432923Swnj 			printf(" dz%d", unit>>3);
6442395Swnj 		tp = &dz_tty[unit];
6455407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6462395Swnj 			dzparam(unit);
6476157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6485407Swnj 			tp->t_state &= ~TS_BUSY;
649301Sbill 			dzstart(tp);
650281Sbill 		}
651281Sbill 	}
652281Sbill }
6531562Sbill #endif
654