xref: /csrg-svn/sys/vax/uba/dz.c (revision 16191)
1*16191Skarels /*	dz.c	6.2	84/03/15	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 0
517Sbill /*
610019Ssam  *  DZ-11/DZ-32 Driver
72469Swnj  *
82469Swnj  * This driver mimics dh.c; see it for explanation of common code.
917Sbill  */
102731Swnj #include "bk.h"
119773Ssam 
129773Ssam #include "../machine/pte.h"
139773Ssam 
1417Sbill #include "../h/param.h"
1517Sbill #include "../h/systm.h"
169551Ssam #include "../h/ioctl.h"
1717Sbill #include "../h/tty.h"
1817Sbill #include "../h/dir.h"
1917Sbill #include "../h/user.h"
206157Ssam #include "../h/proc.h"
2117Sbill #include "../h/map.h"
222395Swnj #include "../h/buf.h"
232567Swnj #include "../h/vm.h"
2417Sbill #include "../h/conf.h"
25114Sbill #include "../h/bk.h"
26871Sbill #include "../h/file.h"
277727Sroot #include "../h/uio.h"
2810869Ssam #include "../h/kernel.h"
29145Sbill 
308474Sroot #include "../vaxuba/pdma.h"
318474Sroot #include "../vaxuba/ubavar.h"
3210019Ssam #include "../vaxuba/dzreg.h"
338474Sroot 
342469Swnj /*
352469Swnj  * Driver information for auto-configuration stuff.
362469Swnj  */
372606Swnj int	dzprobe(), dzattach(), dzrint();
382976Swnj struct	uba_device *dzinfo[NDZ];
392395Swnj u_short	dzstd[] = { 0 };
402395Swnj struct	uba_driver dzdriver =
412606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
422395Swnj 
432645Swnj #define	NDZLINE 	(NDZ*8)
44*16191Skarels #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
452469Swnj 
462469Swnj int	dzstart(), dzxint(), dzdma();
47114Sbill int	ttrstrt();
482645Swnj struct	tty dz_tty[NDZLINE];
492645Swnj int	dz_cnt = { NDZLINE };
50119Sbill int	dzact;
51*16191Skarels int	dzsilos;			/* mask of dz's with silo in use */
52*16191Skarels int	dzchars[NDZ];			/* recent input count */
53*16191Skarels int	dzrate[NDZ];			/* smoothed input count */
54*16191Skarels int	dztimerintvl;			/* time interval for dztimer */
55*16191Skarels int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
56*16191Skarels int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
5717Sbill 
585731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
595731Sroot 
602469Swnj /*
612469Swnj  * Software copy of dzbrk since it isn't readable
622469Swnj  */
632645Swnj char	dz_brk[NDZ];
642645Swnj char	dzsoftCAR[NDZ];
655731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
6617Sbill 
672469Swnj /*
685731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
692469Swnj  * we have to use a timer to watch it.
702469Swnj  */
712469Swnj char	dz_timer;		/* timer started? */
722469Swnj 
732469Swnj /*
742469Swnj  * Pdma structures for fast output code
752469Swnj  */
762645Swnj struct	pdma dzpdma[NDZLINE];
772469Swnj 
782395Swnj char	dz_speeds[] =
796814Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
8017Sbill 
816616Ssam #ifndef PORTSELECTOR
826616Ssam #define	ISPEED	B300
836616Ssam #define	IFLAGS	(EVENP|ODDP|ECHO)
846616Ssam #else
856616Ssam #define	ISPEED	B4800
866616Ssam #define	IFLAGS	(EVENP|ODDP)
876616Ssam #endif
886616Ssam 
892606Swnj dzprobe(reg)
902395Swnj 	caddr_t reg;
912395Swnj {
922457Swnj 	register int br, cvec;
9310019Ssam 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
942395Swnj 
952606Swnj #ifdef lint
963102Swnj 	br = 0; cvec = br; br = cvec;
974933Swnj 	dzrint(0); dzxint((struct tty *)0);
982606Swnj #endif
995731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1005731Sroot 	if (dzaddr->dzcsr & DZ_32)
1015731Sroot 		dzaddr->dzlnen = 1;
1025731Sroot 	else
1035731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1042457Swnj 	DELAY(100000);
1055731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1062457Swnj 	if (cvec && cvec != 0x200)
1072457Swnj 		cvec -= 4;
10810019Ssam 	return (sizeof (struct dzdevice));
1092395Swnj }
1102395Swnj 
1112606Swnj dzattach(ui)
1122976Swnj 	register struct uba_device *ui;
1132395Swnj {
1142395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1152395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1162606Swnj 	register int cntr;
1172645Swnj 	extern dzscan();
1182395Swnj 
1192606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
12010019Ssam 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
1212395Swnj 		pdp->p_arg = (int)tp;
1222395Swnj 		pdp->p_fcn = dzxint;
1232395Swnj 		pdp++, tp++;
1242395Swnj 	}
1252567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1262627Swnj 	if (dz_timer == 0) {
1272627Swnj 		dz_timer++;
1282756Swnj 		timeout(dzscan, (caddr_t)0, hz);
129*16191Skarels 		dztimerintvl = FASTTIMER;
1302627Swnj 	}
1312395Swnj }
1322395Swnj 
13317Sbill /*ARGSUSED*/
1342395Swnj dzopen(dev, flag)
1352395Swnj 	dev_t dev;
13617Sbill {
13717Sbill 	register struct tty *tp;
1382395Swnj 	register int unit;
13917Sbill 
1402395Swnj 	unit = minor(dev);
1418568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
1428568Sroot 		return (ENXIO);
1432395Swnj 	tp = &dz_tty[unit];
1442395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
14517Sbill 	tp->t_oproc = dzstart;
1465407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
14717Sbill 		ttychars(tp);
1486616Ssam 		tp->t_ospeed = tp->t_ispeed = ISPEED;
1496616Ssam 		tp->t_flags = IFLAGS;
1505407Swnj 		/* tp->t_state |= TS_HUPCLS; */
1512395Swnj 		dzparam(unit);
1528568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
1538568Sroot 		return (EBUSY);
1546157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
155114Sbill 	(void) spl5();
1565407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
1575407Swnj 		tp->t_state |= TS_WOPEN;
15817Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
15917Sbill 	}
160114Sbill 	(void) spl0();
1618568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
16217Sbill }
16317Sbill 
1642395Swnj /*ARGSUSED*/
1652395Swnj dzclose(dev, flag)
1662395Swnj 	dev_t dev;
16717Sbill {
16817Sbill 	register struct tty *tp;
1692395Swnj 	register int unit;
17010019Ssam 	register struct dzdevice *dzaddr;
1716150Ssam 	int dz;
17217Sbill 
1732395Swnj 	unit = minor(dev);
1742395Swnj 	dz = unit >> 3;
1752395Swnj 	tp = &dz_tty[unit];
17617Sbill 	(*linesw[tp->t_line].l_close)(tp);
1775731Sroot 	dzaddr = dzpdma[unit].p_addr;
1785731Sroot 	if (dzaddr->dzcsr&DZ_32)
1796157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
1805731Sroot 	else
1815731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
1826842Swnj 	if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
1836157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
18417Sbill 	ttyclose(tp);
18517Sbill }
18617Sbill 
1877727Sroot dzread(dev, uio)
1882395Swnj 	dev_t dev;
1897727Sroot 	struct uio *uio;
19017Sbill {
19117Sbill 	register struct tty *tp;
19217Sbill 
1932395Swnj 	tp = &dz_tty[minor(dev)];
1947727Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
19517Sbill }
19617Sbill 
1977833Sroot dzwrite(dev, uio)
1982395Swnj 	dev_t dev;
1997833Sroot 	struct uio *uio;
20017Sbill {
20117Sbill 	register struct tty *tp;
20217Sbill 
2032395Swnj 	tp = &dz_tty[minor(dev)];
2048531Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
20517Sbill }
20617Sbill 
207119Sbill /*ARGSUSED*/
2082395Swnj dzrint(dz)
2092395Swnj 	int dz;
21017Sbill {
21117Sbill 	register struct tty *tp;
21217Sbill 	register int c;
21310019Ssam 	register struct dzdevice *dzaddr;
214119Sbill 	register struct tty *tp0;
2152395Swnj 	register int unit;
2162923Swnj 	int overrun = 0;
21717Sbill 
2182457Swnj 	if ((dzact & (1<<dz)) == 0)
2192457Swnj 		return;
2202457Swnj 	unit = dz * 8;
2212457Swnj 	dzaddr = dzpdma[unit].p_addr;
2222457Swnj 	tp0 = &dz_tty[unit];
2235731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2245731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2255731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2265731Sroot 		c = dzaddr->dzmtsr;
2275731Sroot 		tp = tp0 + (c&7);
2285731Sroot 		if (tp >= &dz_tty[dz_cnt])
2295731Sroot 			break;
2305731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2315731Sroot 		dzwait(dzaddr);		/* wait for them */
2325731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2335731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
2345731Sroot 			if ((tp->t_state&TS_CARR_ON) == 0) {
2355731Sroot 				wakeup((caddr_t)&tp->t_rawq);
2365731Sroot 				tp->t_state |= TS_CARR_ON;
2375731Sroot 			}
2385731Sroot 		} else {	/* no carrier */
2395731Sroot 			if (tp->t_state&TS_CARR_ON) {
2405731Sroot 				gsignal(tp->t_pgrp, SIGHUP);
2415731Sroot 				gsignal(tp->t_pgrp, SIGCONT);
2425731Sroot 				dzaddr->dzlcs = DZ_ACK|(c&7);
24312777Ssam 				ttyflush(tp, FREAD|FWRITE);
2445731Sroot 			}
2455731Sroot 			tp->t_state &= ~TS_CARR_ON;
2465731Sroot 		}
2475731Sroot 	}
2482457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
249*16191Skarels 		dzchars[dz]++;
2502457Swnj 		tp = tp0 + ((c>>8)&07);
2512457Swnj 		if (tp >= &dz_tty[dz_cnt])
25217Sbill 			continue;
2535407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2542457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2556616Ssam #ifdef PORTSELECTOR
2566616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2576616Ssam #endif
2582457Swnj 			continue;
2592457Swnj 		}
2602469Swnj 		if (c&DZ_FE)
2612457Swnj 			if (tp->t_flags & RAW)
2622469Swnj 				c = 0;
2632457Swnj 			else
2649551Ssam 				c = tp->t_intrc;
2652923Swnj 		if (c&DZ_DO && overrun == 0) {
2665731Sroot 			/* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
2672923Swnj 			overrun = 1;
2682923Swnj 		}
2692469Swnj 		if (c&DZ_PE)
2702457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2712457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
27217Sbill 				continue;
2732731Swnj #if NBK > 0
2742457Swnj 		if (tp->t_line == NETLDISC) {
2752457Swnj 			c &= 0177;
2762457Swnj 			BKINPUT(c, tp);
2772457Swnj 		} else
2782731Swnj #endif
2792457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
28017Sbill 	}
28117Sbill }
28217Sbill 
28317Sbill /*ARGSUSED*/
2847631Ssam dzioctl(dev, cmd, data, flag)
2852395Swnj 	dev_t dev;
2867631Ssam 	caddr_t data;
28717Sbill {
28817Sbill 	register struct tty *tp;
2892395Swnj 	register int unit = minor(dev);
2902395Swnj 	register int dz = unit >> 3;
29110019Ssam 	register struct dzdevice *dzaddr;
2928568Sroot 	int error;
29317Sbill 
2942395Swnj 	tp = &dz_tty[unit];
2958568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
2968568Sroot 	if (error >= 0)
2978568Sroot 		return (error);
2988568Sroot 	error = ttioctl(tp, cmd, data, flag);
2998568Sroot 	if (error >= 0) {
3007631Ssam 		if (cmd == TIOCSETP || cmd == TIOCSETN)
3012395Swnj 			dzparam(unit);
3028568Sroot 		return (error);
3038568Sroot 	}
3048568Sroot 	switch (cmd) {
3052395Swnj 
306170Sbill 	case TIOCSBRK:
3075731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3085731Sroot 		if (dzaddr->dzcsr&DZ_32)
3096157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3105731Sroot 		else
3115731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
312170Sbill 		break;
3137631Ssam 
314170Sbill 	case TIOCCBRK:
3155731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3165731Sroot 		if (dzaddr->dzcsr&DZ_32)
3176157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3185731Sroot 		else
3195731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
320170Sbill 		break;
3217631Ssam 
322170Sbill 	case TIOCSDTR:
3236157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
324170Sbill 		break;
3257631Ssam 
326170Sbill 	case TIOCCDTR:
3276157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
328170Sbill 		break;
3297631Ssam 
3305731Sroot 	case TIOCMSET:
3317631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3325731Sroot 		break;
3337631Ssam 
3345731Sroot 	case TIOCMBIS:
3357631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3365731Sroot 		break;
3377631Ssam 
3385731Sroot 	case TIOCMBIC:
3397631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3405731Sroot 		break;
3417631Ssam 
3425731Sroot 	case TIOCMGET:
3437631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3445731Sroot 		break;
3457631Ssam 
346170Sbill 	default:
3478568Sroot 		return (ENOTTY);
348170Sbill 	}
3498568Sroot 	return (0);
35017Sbill }
3515731Sroot 
3525731Sroot dmtodz(bits)
3535731Sroot 	register int bits;
3545731Sroot {
3555731Sroot 	register int b;
3565731Sroot 
3575731Sroot 	b = (bits >>1) & 0370;
3585731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3595731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3605731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3615731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3625731Sroot 	return(b);
3635731Sroot }
3645731Sroot 
3655731Sroot dztodm(bits)
3665731Sroot 	register int bits;
3675731Sroot {
3685731Sroot 	register int b;
3695731Sroot 
3705731Sroot 	b = (bits << 1) & 0360;
3715731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3725731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3735731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3745731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3755731Sroot 	return(b);
3765731Sroot }
37717Sbill 
3782395Swnj dzparam(unit)
3792395Swnj 	register int unit;
38017Sbill {
38117Sbill 	register struct tty *tp;
38210019Ssam 	register struct dzdevice *dzaddr;
3832395Swnj 	register int lpr;
38417Sbill 
3852395Swnj 	tp = &dz_tty[unit];
3862395Swnj 	dzaddr = dzpdma[unit].p_addr;
387*16191Skarels 	if (dzsilos & (1 << (unit >> 3)))
388*16191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
389*16191Skarels 	else
390*16191Skarels 		dzaddr->dzcsr = DZ_IEN;
3912395Swnj 	dzact |= (1<<(unit>>3));
39217Sbill 	if (tp->t_ispeed == 0) {
3936157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
39417Sbill 		return;
39517Sbill 	}
3962395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3979551Ssam 	if (tp->t_flags & (RAW|LITOUT))
39817Sbill 		lpr |= BITS8;
39917Sbill 	else
40017Sbill 		lpr |= (BITS7|PENABLE);
40117Sbill 	if ((tp->t_flags & EVENP) == 0)
40217Sbill 		lpr |= OPAR;
4032469Swnj 	if (tp->t_ispeed == B110)
4042469Swnj 		lpr |= TWOSB;
40517Sbill 	dzaddr->dzlpr = lpr;
40617Sbill }
40717Sbill 
40817Sbill dzxint(tp)
4092395Swnj 	register struct tty *tp;
41017Sbill {
41117Sbill 	register struct pdma *dp;
412*16191Skarels 	register dz, unit;
41317Sbill 
4142395Swnj 	dp = (struct pdma *)tp->t_addr;
4155407Swnj 	tp->t_state &= ~TS_BUSY;
4165407Swnj 	if (tp->t_state & TS_FLUSH)
4175407Swnj 		tp->t_state &= ~TS_FLUSH;
4185731Sroot 	else {
419281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4205731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4215731Sroot 	}
42217Sbill 	if (tp->t_line)
42317Sbill 		(*linesw[tp->t_line].l_start)(tp);
42417Sbill 	else
42517Sbill 		dzstart(tp);
4265731Sroot 	dz = minor(tp->t_dev) >> 3;
4275731Sroot 	unit = minor(tp->t_dev) & 7;
4285407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4295731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4305731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4315731Sroot 		else
4325731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
43317Sbill }
43417Sbill 
43517Sbill dzstart(tp)
4362395Swnj 	register struct tty *tp;
43717Sbill {
43817Sbill 	register struct pdma *dp;
43910019Ssam 	register struct dzdevice *dzaddr;
4402395Swnj 	register int cc;
4415731Sroot 	int s, dz, unit;
44217Sbill 
4432395Swnj 	dp = (struct pdma *)tp->t_addr;
44417Sbill 	dzaddr = dp->p_addr;
4452395Swnj 	s = spl5();
4465407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
44717Sbill 		goto out;
4485407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
4495407Swnj 		if (tp->t_state&TS_ASLEEP) {
4505407Swnj 			tp->t_state &= ~TS_ASLEEP;
4515407Swnj 			wakeup((caddr_t)&tp->t_outq);
4525407Swnj 		}
4535407Swnj 		if (tp->t_wsel) {
4545407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4555407Swnj 			tp->t_wsel = 0;
4565407Swnj 			tp->t_state &= ~TS_WCOLL;
4575407Swnj 		}
45817Sbill 	}
45917Sbill 	if (tp->t_outq.c_cc == 0)
46017Sbill 		goto out;
4619551Ssam 	if (tp->t_flags & (RAW|LITOUT))
46217Sbill 		cc = ndqb(&tp->t_outq, 0);
46317Sbill 	else {
46417Sbill 		cc = ndqb(&tp->t_outq, 0200);
46517Sbill 		if (cc == 0) {
46617Sbill 			cc = getc(&tp->t_outq);
4672469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
4685407Swnj 			tp->t_state |= TS_TIMEOUT;
46917Sbill 			goto out;
47017Sbill 		}
47117Sbill 	}
4725407Swnj 	tp->t_state |= TS_BUSY;
47317Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
47417Sbill 	dp->p_end += cc;
4755731Sroot 	dz = minor(tp->t_dev) >> 3;
4765731Sroot 	unit = minor(tp->t_dev) & 7;
4775731Sroot 	if (dzaddr->dzcsr & DZ_32)
4785731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
4795731Sroot 	else
4805731Sroot 		dzaddr->dztcr |= (1<<unit);
4812395Swnj out:
4822395Swnj 	splx(s);
48317Sbill }
48417Sbill 
48517Sbill /*
48617Sbill  * Stop output on a line.
48717Sbill  */
48817Sbill /*ARGSUSED*/
48917Sbill dzstop(tp, flag)
4902395Swnj 	register struct tty *tp;
49117Sbill {
49217Sbill 	register struct pdma *dp;
49317Sbill 	register int s;
49417Sbill 
4952395Swnj 	dp = (struct pdma *)tp->t_addr;
4962457Swnj 	s = spl5();
4975407Swnj 	if (tp->t_state & TS_BUSY) {
49817Sbill 		dp->p_end = dp->p_mem;
4995407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5005407Swnj 			tp->t_state |= TS_FLUSH;
50117Sbill 	}
50217Sbill 	splx(s);
50317Sbill }
50417Sbill 
5055731Sroot dzmctl(dev, bits, how)
5065731Sroot 	dev_t dev;
5075731Sroot 	int bits, how;
50817Sbill {
50910019Ssam 	register struct dzdevice *dzaddr;
5105731Sroot 	register int unit, mbits;
5115731Sroot 	int b, s;
5125731Sroot 
5135731Sroot 	unit = minor(dev);
5145731Sroot 	b = 1<<(unit&7);
5152395Swnj 	dzaddr = dzpdma[unit].p_addr;
5165731Sroot 	s = spl5();
5175731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5185731Sroot 		dzwait(dzaddr)
5195731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5205731Sroot 		dzaddr->dzlcs = unit&7;
5215731Sroot 		DELAY(100);
5225731Sroot 		dzwait(dzaddr)
5235731Sroot 		DELAY(100);
5245731Sroot 		mbits = dzaddr->dzlcs;
5255731Sroot 		mbits &= 0177770;
5265731Sroot 	} else {
5275731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5285731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5295731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5305731Sroot 	}
5315731Sroot 	switch (how) {
5325731Sroot 	case DMSET:
5335731Sroot 		mbits = bits;
5345731Sroot 		break;
5355731Sroot 
5365731Sroot 	case DMBIS:
5375731Sroot 		mbits |= bits;
5385731Sroot 		break;
5395731Sroot 
5405731Sroot 	case DMBIC:
5415731Sroot 		mbits &= ~bits;
5425731Sroot 		break;
5435731Sroot 
5445731Sroot 	case DMGET:
5455731Sroot 		(void) splx(s);
5465731Sroot 		return(mbits);
5475731Sroot 	}
5485731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5495731Sroot 		mbits |= DZ_ACK|(unit&7);
5505731Sroot 		dzaddr->dzlcs = mbits;
5515731Sroot 	} else {
5525731Sroot 		if (mbits & DZ_DTR)
5535731Sroot 			dzaddr->dzdtr |= b;
5545731Sroot 		else
5555731Sroot 			dzaddr->dzdtr &= ~b;
5565731Sroot 	}
5575731Sroot 	(void) splx(s);
5585731Sroot 	return(mbits);
55917Sbill }
56017Sbill 
561*16191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
56217Sbill dzscan()
56317Sbill {
56417Sbill 	register i;
56510019Ssam 	register struct dzdevice *dzaddr;
56617Sbill 	register bit;
56717Sbill 	register struct tty *tp;
5685731Sroot 	register car;
569*16191Skarels 	int olddzsilos = dzsilos;
570*16191Skarels 	int dztimer();
57117Sbill 
57217Sbill 	for (i = 0; i < dz_cnt ; i++) {
57317Sbill 		dzaddr = dzpdma[i].p_addr;
5742627Swnj 		if (dzaddr == 0)
5752627Swnj 			continue;
57617Sbill 		tp = &dz_tty[i];
57717Sbill 		bit = 1<<(i&07);
5785731Sroot 		car = 0;
5795731Sroot 		if (dzsoftCAR[i>>3]&bit)
5805731Sroot 			car = 1;
5815731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
5825731Sroot 			dzaddr->dzlcs = i&07;
5835731Sroot 			dzwait(dzaddr);
5845731Sroot 			car = dzaddr->dzlcs & DZ_CD;
5855731Sroot 		} else
5865731Sroot 			car = dzaddr->dzmsr&bit;
5875731Sroot 		if (car) {
58817Sbill 			/* carrier present */
5895407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
59017Sbill 				wakeup((caddr_t)&tp->t_rawq);
5915407Swnj 				tp->t_state |= TS_CARR_ON;
59217Sbill 			}
59317Sbill 		} else {
5945407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
5959551Ssam 			    (tp->t_flags&NOHANG) == 0) {
59617Sbill 				/* carrier lost */
5975407Swnj 				if (tp->t_state&TS_ISOPEN) {
598170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
599205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
600170Sbill 					dzaddr->dzdtr &= ~bit;
60112777Ssam 					ttyflush(tp, FREAD|FWRITE);
602170Sbill 				}
6035407Swnj 				tp->t_state &= ~TS_CARR_ON;
60417Sbill 			}
60517Sbill 		}
60617Sbill 	}
607*16191Skarels 	for (i = 0; i < NDZ; i++) {
608*16191Skarels 		ave(dzrate[i], dzchars[i], 8);
609*16191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
610*16191Skarels 			dzpdma[i].p_addr->dzcsr = DZ_IEN | DZ_SAE;
611*16191Skarels 			dzsilos |= (1 << i);
612*16191Skarels 			dztransitions++;		/*DEBUG*/
613*16191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
614*16191Skarels 			dzpdma[i].p_addr->dzcsr = DZ_IEN;
615*16191Skarels 			dzsilos &= ~(1 << i);
616*16191Skarels 		}
617*16191Skarels 		dzchars[i] = 0;
618*16191Skarels 	}
619*16191Skarels 	if (dzsilos && !olddzsilos)
620*16191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
621*16191Skarels 	timeout(dzscan, (caddr_t)0, hz);
62217Sbill }
623119Sbill 
624119Sbill dztimer()
625119Sbill {
6268160Sroot 	register int dz;
627*16191Skarels 	register int s;
628119Sbill 
629*16191Skarels 	if (dzsilos == 0)
630*16191Skarels 		return;
631*16191Skarels 	s = spl5();
632*16191Skarels 	dzfasttimers++;		/*DEBUG*/
6332645Swnj 	for (dz = 0; dz < NDZ; dz++)
634*16191Skarels 		if (dzsilos & (1 << dz))
635*16191Skarels 		    dzrint(dz);
6368160Sroot 	splx(s);
637*16191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
638119Sbill }
639281Sbill 
640281Sbill /*
641281Sbill  * Reset state of driver if UBA reset was necessary.
642301Sbill  * Reset parameters and restart transmission on open lines.
643281Sbill  */
6442395Swnj dzreset(uban)
6452422Skre 	int uban;
646281Sbill {
6472395Swnj 	register int unit;
648281Sbill 	register struct tty *tp;
6492976Swnj 	register struct uba_device *ui;
650281Sbill 
6512645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6522422Skre 		ui = dzinfo[unit >> 3];
6532422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6542422Skre 			continue;
6552923Swnj 		if (unit%8 == 0)
6562923Swnj 			printf(" dz%d", unit>>3);
6572395Swnj 		tp = &dz_tty[unit];
6585407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6592395Swnj 			dzparam(unit);
6606157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6615407Swnj 			tp->t_state &= ~TS_BUSY;
662301Sbill 			dzstart(tp);
663281Sbill 		}
664281Sbill 	}
665281Sbill }
6661562Sbill #endif
667