xref: /csrg-svn/sys/vax/uba/dz.c (revision 30387)
123326Smckusick /*
229219Smckusick  * Copyright (c) 1982, 1986 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*30387Skarels  *	@(#)dz.c	7.2 (Berkeley) 01/14/87
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 
8825397Skarels #ifndef	PORTSELECTOR
8925397Skarels #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);
15527050Skarels #ifndef PORTSELECTOR
15627050Skarels 		if (tp->t_ispeed == 0) {
15727050Skarels #else
15827050Skarels 			tp->t_state |= TS_HUPCLS;
15927050Skarels #endif PORTSELECTOR
16027050Skarels 			tp->t_ispeed = ISPEED;
16127050Skarels 			tp->t_ospeed = ISPEED;
16227050Skarels 			tp->t_flags = IFLAGS;
16327050Skarels #ifndef PORTSELECTOR
16427050Skarels 		}
16527050Skarels #endif PORTSELECTOR
1662395Swnj 		dzparam(unit);
1678568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
1688568Sroot 		return (EBUSY);
1696157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
170114Sbill 	(void) spl5();
1715407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
1725407Swnj 		tp->t_state |= TS_WOPEN;
17317Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17417Sbill 	}
175114Sbill 	(void) spl0();
1768568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
17717Sbill }
17817Sbill 
1792395Swnj /*ARGSUSED*/
1802395Swnj dzclose(dev, flag)
1812395Swnj 	dev_t dev;
18217Sbill {
18317Sbill 	register struct tty *tp;
1842395Swnj 	register int unit;
18510019Ssam 	register struct dzdevice *dzaddr;
1866150Ssam 	int dz;
18717Sbill 
1882395Swnj 	unit = minor(dev);
1892395Swnj 	dz = unit >> 3;
1902395Swnj 	tp = &dz_tty[unit];
19117Sbill 	(*linesw[tp->t_line].l_close)(tp);
1925731Sroot 	dzaddr = dzpdma[unit].p_addr;
1935731Sroot 	if (dzaddr->dzcsr&DZ_32)
1946157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
1955731Sroot 	else
1965731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
1976842Swnj 	if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
1986157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
19917Sbill 	ttyclose(tp);
20017Sbill }
20117Sbill 
2027727Sroot dzread(dev, uio)
2032395Swnj 	dev_t dev;
2047727Sroot 	struct uio *uio;
20517Sbill {
20617Sbill 	register struct tty *tp;
20717Sbill 
2082395Swnj 	tp = &dz_tty[minor(dev)];
2097727Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
21017Sbill }
21117Sbill 
2127833Sroot dzwrite(dev, uio)
2132395Swnj 	dev_t dev;
2147833Sroot 	struct uio *uio;
21517Sbill {
21617Sbill 	register struct tty *tp;
21717Sbill 
2182395Swnj 	tp = &dz_tty[minor(dev)];
2198531Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
22017Sbill }
22117Sbill 
222119Sbill /*ARGSUSED*/
2232395Swnj dzrint(dz)
2242395Swnj 	int dz;
22517Sbill {
22617Sbill 	register struct tty *tp;
22717Sbill 	register int c;
22810019Ssam 	register struct dzdevice *dzaddr;
229119Sbill 	register struct tty *tp0;
2302395Swnj 	register int unit;
2312923Swnj 	int overrun = 0;
23217Sbill 
2332457Swnj 	if ((dzact & (1<<dz)) == 0)
2342457Swnj 		return;
2352457Swnj 	unit = dz * 8;
2362457Swnj 	dzaddr = dzpdma[unit].p_addr;
2372457Swnj 	tp0 = &dz_tty[unit];
2385731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2395731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2405731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2415731Sroot 		c = dzaddr->dzmtsr;
2425731Sroot 		tp = tp0 + (c&7);
2435731Sroot 		if (tp >= &dz_tty[dz_cnt])
2445731Sroot 			break;
2455731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2465731Sroot 		dzwait(dzaddr);		/* wait for them */
2475731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2485731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
24925397Skarels 			/* carrier present */
25025397Skarels 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
25125397Skarels 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
25225397Skarels 			dzaddr->dzlcs = DZ_ACK|(c&7);
2535731Sroot 	}
2542457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
25516191Skarels 		dzchars[dz]++;
2562457Swnj 		tp = tp0 + ((c>>8)&07);
2572457Swnj 		if (tp >= &dz_tty[dz_cnt])
25817Sbill 			continue;
2595407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2602457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2616616Ssam #ifdef PORTSELECTOR
2626616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2636616Ssam #endif
26425397Skarels 				continue;
2652457Swnj 		}
2662469Swnj 		if (c&DZ_FE)
2672457Swnj 			if (tp->t_flags & RAW)
2682469Swnj 				c = 0;
2692457Swnj 			else
2709551Ssam 				c = tp->t_intrc;
2712923Swnj 		if (c&DZ_DO && overrun == 0) {
27224843Seric 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2732923Swnj 			overrun = 1;
2742923Swnj 		}
2752469Swnj 		if (c&DZ_PE)
2762457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2772457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
27817Sbill 				continue;
2792731Swnj #if NBK > 0
2802457Swnj 		if (tp->t_line == NETLDISC) {
2812457Swnj 			c &= 0177;
2822457Swnj 			BKINPUT(c, tp);
2832457Swnj 		} else
2842731Swnj #endif
2852457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
28617Sbill 	}
28717Sbill }
28817Sbill 
28917Sbill /*ARGSUSED*/
2907631Ssam dzioctl(dev, cmd, data, flag)
2912395Swnj 	dev_t dev;
2927631Ssam 	caddr_t data;
29317Sbill {
29417Sbill 	register struct tty *tp;
2952395Swnj 	register int unit = minor(dev);
2962395Swnj 	register int dz = unit >> 3;
29710019Ssam 	register struct dzdevice *dzaddr;
2988568Sroot 	int error;
29917Sbill 
3002395Swnj 	tp = &dz_tty[unit];
3018568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3028568Sroot 	if (error >= 0)
3038568Sroot 		return (error);
3048568Sroot 	error = ttioctl(tp, cmd, data, flag);
3058568Sroot 	if (error >= 0) {
30617563Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
30717563Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
3082395Swnj 			dzparam(unit);
3098568Sroot 		return (error);
3108568Sroot 	}
3118568Sroot 	switch (cmd) {
3122395Swnj 
313170Sbill 	case TIOCSBRK:
3145731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3155731Sroot 		if (dzaddr->dzcsr&DZ_32)
3166157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3175731Sroot 		else
3185731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
319170Sbill 		break;
3207631Ssam 
321170Sbill 	case TIOCCBRK:
3225731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3235731Sroot 		if (dzaddr->dzcsr&DZ_32)
3246157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3255731Sroot 		else
3265731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
327170Sbill 		break;
3287631Ssam 
329170Sbill 	case TIOCSDTR:
3306157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
331170Sbill 		break;
3327631Ssam 
333170Sbill 	case TIOCCDTR:
3346157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
335170Sbill 		break;
3367631Ssam 
3375731Sroot 	case TIOCMSET:
3387631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3395731Sroot 		break;
3407631Ssam 
3415731Sroot 	case TIOCMBIS:
3427631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3435731Sroot 		break;
3447631Ssam 
3455731Sroot 	case TIOCMBIC:
3467631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3475731Sroot 		break;
3487631Ssam 
3495731Sroot 	case TIOCMGET:
3507631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3515731Sroot 		break;
3527631Ssam 
353170Sbill 	default:
3548568Sroot 		return (ENOTTY);
355170Sbill 	}
3568568Sroot 	return (0);
35717Sbill }
3585731Sroot 
3595731Sroot dmtodz(bits)
3605731Sroot 	register int bits;
3615731Sroot {
3625731Sroot 	register int b;
3635731Sroot 
3645731Sroot 	b = (bits >>1) & 0370;
3655731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3665731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3675731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3685731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3695731Sroot 	return(b);
3705731Sroot }
3715731Sroot 
3725731Sroot dztodm(bits)
3735731Sroot 	register int bits;
3745731Sroot {
3755731Sroot 	register int b;
3765731Sroot 
3775731Sroot 	b = (bits << 1) & 0360;
3785731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3795731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3805731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3815731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3825731Sroot 	return(b);
3835731Sroot }
38417Sbill 
3852395Swnj dzparam(unit)
3862395Swnj 	register int unit;
38717Sbill {
38817Sbill 	register struct tty *tp;
38910019Ssam 	register struct dzdevice *dzaddr;
3902395Swnj 	register int lpr;
39117Sbill 
3922395Swnj 	tp = &dz_tty[unit];
3932395Swnj 	dzaddr = dzpdma[unit].p_addr;
39416191Skarels 	if (dzsilos & (1 << (unit >> 3)))
39516191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
39616191Skarels 	else
39716191Skarels 		dzaddr->dzcsr = DZ_IEN;
3982395Swnj 	dzact |= (1<<(unit>>3));
39917Sbill 	if (tp->t_ispeed == 0) {
4006157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
40117Sbill 		return;
40217Sbill 	}
4032395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
40424271Slepreau 	if (tp->t_flags & (RAW|LITOUT|PASS8))
40517Sbill 		lpr |= BITS8;
40617Sbill 	else
40717Sbill 		lpr |= (BITS7|PENABLE);
40817Sbill 	if ((tp->t_flags & EVENP) == 0)
40917Sbill 		lpr |= OPAR;
4102469Swnj 	if (tp->t_ispeed == B110)
4112469Swnj 		lpr |= TWOSB;
41217Sbill 	dzaddr->dzlpr = lpr;
41317Sbill }
41417Sbill 
41517Sbill dzxint(tp)
4162395Swnj 	register struct tty *tp;
41717Sbill {
41817Sbill 	register struct pdma *dp;
41916191Skarels 	register dz, unit;
42017Sbill 
4212395Swnj 	dp = (struct pdma *)tp->t_addr;
4225407Swnj 	tp->t_state &= ~TS_BUSY;
4235407Swnj 	if (tp->t_state & TS_FLUSH)
4245407Swnj 		tp->t_state &= ~TS_FLUSH;
4255731Sroot 	else {
426281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4275731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4285731Sroot 	}
42917Sbill 	if (tp->t_line)
43017Sbill 		(*linesw[tp->t_line].l_start)(tp);
43117Sbill 	else
43217Sbill 		dzstart(tp);
4335731Sroot 	dz = minor(tp->t_dev) >> 3;
4345731Sroot 	unit = minor(tp->t_dev) & 7;
4355407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4365731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4375731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4385731Sroot 		else
4395731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
44017Sbill }
44117Sbill 
44217Sbill dzstart(tp)
4432395Swnj 	register struct tty *tp;
44417Sbill {
44517Sbill 	register struct pdma *dp;
44610019Ssam 	register struct dzdevice *dzaddr;
4472395Swnj 	register int cc;
4485731Sroot 	int s, dz, unit;
44917Sbill 
4502395Swnj 	dp = (struct pdma *)tp->t_addr;
45117Sbill 	dzaddr = dp->p_addr;
4522395Swnj 	s = spl5();
4535407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
45417Sbill 		goto out;
4555407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
4565407Swnj 		if (tp->t_state&TS_ASLEEP) {
4575407Swnj 			tp->t_state &= ~TS_ASLEEP;
4585407Swnj 			wakeup((caddr_t)&tp->t_outq);
4595407Swnj 		}
4605407Swnj 		if (tp->t_wsel) {
4615407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4625407Swnj 			tp->t_wsel = 0;
4635407Swnj 			tp->t_state &= ~TS_WCOLL;
4645407Swnj 		}
46517Sbill 	}
46617Sbill 	if (tp->t_outq.c_cc == 0)
46717Sbill 		goto out;
4689551Ssam 	if (tp->t_flags & (RAW|LITOUT))
46917Sbill 		cc = ndqb(&tp->t_outq, 0);
47017Sbill 	else {
47117Sbill 		cc = ndqb(&tp->t_outq, 0200);
47217Sbill 		if (cc == 0) {
47317Sbill 			cc = getc(&tp->t_outq);
4742469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
4755407Swnj 			tp->t_state |= TS_TIMEOUT;
47617Sbill 			goto out;
47717Sbill 		}
47817Sbill 	}
4795407Swnj 	tp->t_state |= TS_BUSY;
48017Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
48117Sbill 	dp->p_end += cc;
4825731Sroot 	dz = minor(tp->t_dev) >> 3;
4835731Sroot 	unit = minor(tp->t_dev) & 7;
4845731Sroot 	if (dzaddr->dzcsr & DZ_32)
4855731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
4865731Sroot 	else
4875731Sroot 		dzaddr->dztcr |= (1<<unit);
4882395Swnj out:
4892395Swnj 	splx(s);
49017Sbill }
49117Sbill 
49217Sbill /*
49317Sbill  * Stop output on a line.
49417Sbill  */
49517Sbill /*ARGSUSED*/
49617Sbill dzstop(tp, flag)
4972395Swnj 	register struct tty *tp;
49817Sbill {
49917Sbill 	register struct pdma *dp;
50017Sbill 	register int s;
50117Sbill 
5022395Swnj 	dp = (struct pdma *)tp->t_addr;
5032457Swnj 	s = spl5();
5045407Swnj 	if (tp->t_state & TS_BUSY) {
50517Sbill 		dp->p_end = dp->p_mem;
5065407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5075407Swnj 			tp->t_state |= TS_FLUSH;
50817Sbill 	}
50917Sbill 	splx(s);
51017Sbill }
51117Sbill 
5125731Sroot dzmctl(dev, bits, how)
5135731Sroot 	dev_t dev;
5145731Sroot 	int bits, how;
51517Sbill {
51610019Ssam 	register struct dzdevice *dzaddr;
5175731Sroot 	register int unit, mbits;
5185731Sroot 	int b, s;
5195731Sroot 
5205731Sroot 	unit = minor(dev);
5215731Sroot 	b = 1<<(unit&7);
5222395Swnj 	dzaddr = dzpdma[unit].p_addr;
5235731Sroot 	s = spl5();
5245731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5255731Sroot 		dzwait(dzaddr)
5265731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5275731Sroot 		dzaddr->dzlcs = unit&7;
5285731Sroot 		DELAY(100);
5295731Sroot 		dzwait(dzaddr)
5305731Sroot 		DELAY(100);
5315731Sroot 		mbits = dzaddr->dzlcs;
5325731Sroot 		mbits &= 0177770;
5335731Sroot 	} else {
5345731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5355731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5365731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5375731Sroot 	}
5385731Sroot 	switch (how) {
5395731Sroot 	case DMSET:
5405731Sroot 		mbits = bits;
5415731Sroot 		break;
5425731Sroot 
5435731Sroot 	case DMBIS:
5445731Sroot 		mbits |= bits;
5455731Sroot 		break;
5465731Sroot 
5475731Sroot 	case DMBIC:
5485731Sroot 		mbits &= ~bits;
5495731Sroot 		break;
5505731Sroot 
5515731Sroot 	case DMGET:
5525731Sroot 		(void) splx(s);
5535731Sroot 		return(mbits);
5545731Sroot 	}
5555731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5565731Sroot 		mbits |= DZ_ACK|(unit&7);
5575731Sroot 		dzaddr->dzlcs = mbits;
5585731Sroot 	} else {
5595731Sroot 		if (mbits & DZ_DTR)
5605731Sroot 			dzaddr->dzdtr |= b;
5615731Sroot 		else
5625731Sroot 			dzaddr->dzdtr &= ~b;
5635731Sroot 	}
564*30387Skarels 	if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b)
565*30387Skarels 		dz_tty[unit].t_state |= TS_CARR_ON;
5665731Sroot 	(void) splx(s);
5675731Sroot 	return(mbits);
56817Sbill }
56917Sbill 
57016191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
57117Sbill dzscan()
57217Sbill {
57317Sbill 	register i;
57410019Ssam 	register struct dzdevice *dzaddr;
57517Sbill 	register bit;
57617Sbill 	register struct tty *tp;
5775731Sroot 	register car;
57816191Skarels 	int olddzsilos = dzsilos;
57916191Skarels 	int dztimer();
58017Sbill 
58117Sbill 	for (i = 0; i < dz_cnt ; i++) {
58217Sbill 		dzaddr = dzpdma[i].p_addr;
5832627Swnj 		if (dzaddr == 0)
5842627Swnj 			continue;
58517Sbill 		tp = &dz_tty[i];
58617Sbill 		bit = 1<<(i&07);
5875731Sroot 		car = 0;
5885731Sroot 		if (dzsoftCAR[i>>3]&bit)
5895731Sroot 			car = 1;
5905731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
5915731Sroot 			dzaddr->dzlcs = i&07;
5925731Sroot 			dzwait(dzaddr);
5935731Sroot 			car = dzaddr->dzlcs & DZ_CD;
5945731Sroot 		} else
5955731Sroot 			car = dzaddr->dzmsr&bit;
5965731Sroot 		if (car) {
59717Sbill 			/* carrier present */
59825397Skarels 			if ((tp->t_state & TS_CARR_ON) == 0)
59925397Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
60025397Skarels 		} else if ((tp->t_state&TS_CARR_ON) &&
60125397Skarels 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
60225397Skarels 			dzaddr->dzdtr &= ~bit;
60317Sbill 	}
60416191Skarels 	for (i = 0; i < NDZ; i++) {
60516191Skarels 		ave(dzrate[i], dzchars[i], 8);
60616191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
60716397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
60816191Skarels 			dzsilos |= (1 << i);
60916191Skarels 			dztransitions++;		/*DEBUG*/
61016191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
61116397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
61216191Skarels 			dzsilos &= ~(1 << i);
61316191Skarels 		}
61416191Skarels 		dzchars[i] = 0;
61516191Skarels 	}
61616191Skarels 	if (dzsilos && !olddzsilos)
61716191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
61816191Skarels 	timeout(dzscan, (caddr_t)0, hz);
61917Sbill }
620119Sbill 
621119Sbill dztimer()
622119Sbill {
6238160Sroot 	register int dz;
62416191Skarels 	register int s;
625119Sbill 
62616191Skarels 	if (dzsilos == 0)
62716191Skarels 		return;
62816191Skarels 	s = spl5();
62916191Skarels 	dzfasttimers++;		/*DEBUG*/
6302645Swnj 	for (dz = 0; dz < NDZ; dz++)
63116191Skarels 		if (dzsilos & (1 << dz))
63216191Skarels 		    dzrint(dz);
6338160Sroot 	splx(s);
63416191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
635119Sbill }
636281Sbill 
637281Sbill /*
638281Sbill  * Reset state of driver if UBA reset was necessary.
639301Sbill  * Reset parameters and restart transmission on open lines.
640281Sbill  */
6412395Swnj dzreset(uban)
6422422Skre 	int uban;
643281Sbill {
6442395Swnj 	register int unit;
645281Sbill 	register struct tty *tp;
6462976Swnj 	register struct uba_device *ui;
647281Sbill 
6482645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6492422Skre 		ui = dzinfo[unit >> 3];
6502422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6512422Skre 			continue;
6522923Swnj 		if (unit%8 == 0)
6532923Swnj 			printf(" dz%d", unit>>3);
6542395Swnj 		tp = &dz_tty[unit];
6555407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6562395Swnj 			dzparam(unit);
6576157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6585407Swnj 			tp->t_state &= ~TS_BUSY;
659301Sbill 			dzstart(tp);
660281Sbill 		}
661281Sbill 	}
662281Sbill }
6631562Sbill #endif
664