xref: /csrg-svn/sys/vax/uba/dz.c (revision 23326)
1*23326Smckusick /*
2*23326Smckusick  * Copyright (c) 1982 Regents of the University of California.
3*23326Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23326Smckusick  * specifies the terms and conditions for redistribution.
5*23326Smckusick  *
6*23326Smckusick  *	@(#)dz.c	6.7 (Berkeley) 06/08/85
7*23326Smckusick  */
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 
886616Ssam #ifndef PORTSELECTOR
896616Ssam #define	ISPEED	B300
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? */
2415731Sroot 			if ((tp->t_state&TS_CARR_ON) == 0) {
2425731Sroot 				wakeup((caddr_t)&tp->t_rawq);
2435731Sroot 				tp->t_state |= TS_CARR_ON;
2445731Sroot 			}
2455731Sroot 		} else {	/* no carrier */
2465731Sroot 			if (tp->t_state&TS_CARR_ON) {
2475731Sroot 				gsignal(tp->t_pgrp, SIGHUP);
2485731Sroot 				gsignal(tp->t_pgrp, SIGCONT);
2495731Sroot 				dzaddr->dzlcs = DZ_ACK|(c&7);
25012777Ssam 				ttyflush(tp, FREAD|FWRITE);
2515731Sroot 			}
2525731Sroot 			tp->t_state &= ~TS_CARR_ON;
2535731Sroot 		}
2545731Sroot 	}
2552457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
25616191Skarels 		dzchars[dz]++;
2572457Swnj 		tp = tp0 + ((c>>8)&07);
2582457Swnj 		if (tp >= &dz_tty[dz_cnt])
25917Sbill 			continue;
2605407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2612457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2626616Ssam #ifdef PORTSELECTOR
2636616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2646616Ssam #endif
2652457Swnj 			continue;
2662457Swnj 		}
2672469Swnj 		if (c&DZ_FE)
2682457Swnj 			if (tp->t_flags & RAW)
2692469Swnj 				c = 0;
2702457Swnj 			else
2719551Ssam 				c = tp->t_intrc;
2722923Swnj 		if (c&DZ_DO && overrun == 0) {
27318313Sralph 			log(KERN_RECOV, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2742923Swnj 			overrun = 1;
2752923Swnj 		}
2762469Swnj 		if (c&DZ_PE)
2772457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2782457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
27917Sbill 				continue;
2802731Swnj #if NBK > 0
2812457Swnj 		if (tp->t_line == NETLDISC) {
2822457Swnj 			c &= 0177;
2832457Swnj 			BKINPUT(c, tp);
2842457Swnj 		} else
2852731Swnj #endif
2862457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
28717Sbill 	}
28817Sbill }
28917Sbill 
29017Sbill /*ARGSUSED*/
2917631Ssam dzioctl(dev, cmd, data, flag)
2922395Swnj 	dev_t dev;
2937631Ssam 	caddr_t data;
29417Sbill {
29517Sbill 	register struct tty *tp;
2962395Swnj 	register int unit = minor(dev);
2972395Swnj 	register int dz = unit >> 3;
29810019Ssam 	register struct dzdevice *dzaddr;
2998568Sroot 	int error;
30017Sbill 
3012395Swnj 	tp = &dz_tty[unit];
3028568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3038568Sroot 	if (error >= 0)
3048568Sroot 		return (error);
3058568Sroot 	error = ttioctl(tp, cmd, data, flag);
3068568Sroot 	if (error >= 0) {
30717563Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
30817563Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
3092395Swnj 			dzparam(unit);
3108568Sroot 		return (error);
3118568Sroot 	}
3128568Sroot 	switch (cmd) {
3132395Swnj 
314170Sbill 	case TIOCSBRK:
3155731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3165731Sroot 		if (dzaddr->dzcsr&DZ_32)
3176157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3185731Sroot 		else
3195731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
320170Sbill 		break;
3217631Ssam 
322170Sbill 	case TIOCCBRK:
3235731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3245731Sroot 		if (dzaddr->dzcsr&DZ_32)
3256157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3265731Sroot 		else
3275731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
328170Sbill 		break;
3297631Ssam 
330170Sbill 	case TIOCSDTR:
3316157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
332170Sbill 		break;
3337631Ssam 
334170Sbill 	case TIOCCDTR:
3356157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
336170Sbill 		break;
3377631Ssam 
3385731Sroot 	case TIOCMSET:
3397631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3405731Sroot 		break;
3417631Ssam 
3425731Sroot 	case TIOCMBIS:
3437631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3445731Sroot 		break;
3457631Ssam 
3465731Sroot 	case TIOCMBIC:
3477631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3485731Sroot 		break;
3497631Ssam 
3505731Sroot 	case TIOCMGET:
3517631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3525731Sroot 		break;
3537631Ssam 
354170Sbill 	default:
3558568Sroot 		return (ENOTTY);
356170Sbill 	}
3578568Sroot 	return (0);
35817Sbill }
3595731Sroot 
3605731Sroot dmtodz(bits)
3615731Sroot 	register int bits;
3625731Sroot {
3635731Sroot 	register int b;
3645731Sroot 
3655731Sroot 	b = (bits >>1) & 0370;
3665731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3675731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3685731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3695731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3705731Sroot 	return(b);
3715731Sroot }
3725731Sroot 
3735731Sroot dztodm(bits)
3745731Sroot 	register int bits;
3755731Sroot {
3765731Sroot 	register int b;
3775731Sroot 
3785731Sroot 	b = (bits << 1) & 0360;
3795731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3805731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3815731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3825731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3835731Sroot 	return(b);
3845731Sroot }
38517Sbill 
3862395Swnj dzparam(unit)
3872395Swnj 	register int unit;
38817Sbill {
38917Sbill 	register struct tty *tp;
39010019Ssam 	register struct dzdevice *dzaddr;
3912395Swnj 	register int lpr;
39217Sbill 
3932395Swnj 	tp = &dz_tty[unit];
3942395Swnj 	dzaddr = dzpdma[unit].p_addr;
39516191Skarels 	if (dzsilos & (1 << (unit >> 3)))
39616191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
39716191Skarels 	else
39816191Skarels 		dzaddr->dzcsr = DZ_IEN;
3992395Swnj 	dzact |= (1<<(unit>>3));
40017Sbill 	if (tp->t_ispeed == 0) {
4016157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
40217Sbill 		return;
40317Sbill 	}
4042395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
4059551Ssam 	if (tp->t_flags & (RAW|LITOUT))
40617Sbill 		lpr |= BITS8;
40717Sbill 	else
40817Sbill 		lpr |= (BITS7|PENABLE);
40917Sbill 	if ((tp->t_flags & EVENP) == 0)
41017Sbill 		lpr |= OPAR;
4112469Swnj 	if (tp->t_ispeed == B110)
4122469Swnj 		lpr |= TWOSB;
41317Sbill 	dzaddr->dzlpr = lpr;
41417Sbill }
41517Sbill 
41617Sbill dzxint(tp)
4172395Swnj 	register struct tty *tp;
41817Sbill {
41917Sbill 	register struct pdma *dp;
42016191Skarels 	register dz, unit;
42117Sbill 
4222395Swnj 	dp = (struct pdma *)tp->t_addr;
4235407Swnj 	tp->t_state &= ~TS_BUSY;
4245407Swnj 	if (tp->t_state & TS_FLUSH)
4255407Swnj 		tp->t_state &= ~TS_FLUSH;
4265731Sroot 	else {
427281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4285731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4295731Sroot 	}
43017Sbill 	if (tp->t_line)
43117Sbill 		(*linesw[tp->t_line].l_start)(tp);
43217Sbill 	else
43317Sbill 		dzstart(tp);
4345731Sroot 	dz = minor(tp->t_dev) >> 3;
4355731Sroot 	unit = minor(tp->t_dev) & 7;
4365407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4375731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4385731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4395731Sroot 		else
4405731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
44117Sbill }
44217Sbill 
44317Sbill dzstart(tp)
4442395Swnj 	register struct tty *tp;
44517Sbill {
44617Sbill 	register struct pdma *dp;
44710019Ssam 	register struct dzdevice *dzaddr;
4482395Swnj 	register int cc;
4495731Sroot 	int s, dz, unit;
45017Sbill 
4512395Swnj 	dp = (struct pdma *)tp->t_addr;
45217Sbill 	dzaddr = dp->p_addr;
4532395Swnj 	s = spl5();
4545407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
45517Sbill 		goto out;
4565407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
4575407Swnj 		if (tp->t_state&TS_ASLEEP) {
4585407Swnj 			tp->t_state &= ~TS_ASLEEP;
4595407Swnj 			wakeup((caddr_t)&tp->t_outq);
4605407Swnj 		}
4615407Swnj 		if (tp->t_wsel) {
4625407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4635407Swnj 			tp->t_wsel = 0;
4645407Swnj 			tp->t_state &= ~TS_WCOLL;
4655407Swnj 		}
46617Sbill 	}
46717Sbill 	if (tp->t_outq.c_cc == 0)
46817Sbill 		goto out;
4699551Ssam 	if (tp->t_flags & (RAW|LITOUT))
47017Sbill 		cc = ndqb(&tp->t_outq, 0);
47117Sbill 	else {
47217Sbill 		cc = ndqb(&tp->t_outq, 0200);
47317Sbill 		if (cc == 0) {
47417Sbill 			cc = getc(&tp->t_outq);
4752469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
4765407Swnj 			tp->t_state |= TS_TIMEOUT;
47717Sbill 			goto out;
47817Sbill 		}
47917Sbill 	}
4805407Swnj 	tp->t_state |= TS_BUSY;
48117Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
48217Sbill 	dp->p_end += cc;
4835731Sroot 	dz = minor(tp->t_dev) >> 3;
4845731Sroot 	unit = minor(tp->t_dev) & 7;
4855731Sroot 	if (dzaddr->dzcsr & DZ_32)
4865731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
4875731Sroot 	else
4885731Sroot 		dzaddr->dztcr |= (1<<unit);
4892395Swnj out:
4902395Swnj 	splx(s);
49117Sbill }
49217Sbill 
49317Sbill /*
49417Sbill  * Stop output on a line.
49517Sbill  */
49617Sbill /*ARGSUSED*/
49717Sbill dzstop(tp, flag)
4982395Swnj 	register struct tty *tp;
49917Sbill {
50017Sbill 	register struct pdma *dp;
50117Sbill 	register int s;
50217Sbill 
5032395Swnj 	dp = (struct pdma *)tp->t_addr;
5042457Swnj 	s = spl5();
5055407Swnj 	if (tp->t_state & TS_BUSY) {
50617Sbill 		dp->p_end = dp->p_mem;
5075407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5085407Swnj 			tp->t_state |= TS_FLUSH;
50917Sbill 	}
51017Sbill 	splx(s);
51117Sbill }
51217Sbill 
5135731Sroot dzmctl(dev, bits, how)
5145731Sroot 	dev_t dev;
5155731Sroot 	int bits, how;
51617Sbill {
51710019Ssam 	register struct dzdevice *dzaddr;
5185731Sroot 	register int unit, mbits;
5195731Sroot 	int b, s;
5205731Sroot 
5215731Sroot 	unit = minor(dev);
5225731Sroot 	b = 1<<(unit&7);
5232395Swnj 	dzaddr = dzpdma[unit].p_addr;
5245731Sroot 	s = spl5();
5255731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5265731Sroot 		dzwait(dzaddr)
5275731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5285731Sroot 		dzaddr->dzlcs = unit&7;
5295731Sroot 		DELAY(100);
5305731Sroot 		dzwait(dzaddr)
5315731Sroot 		DELAY(100);
5325731Sroot 		mbits = dzaddr->dzlcs;
5335731Sroot 		mbits &= 0177770;
5345731Sroot 	} else {
5355731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5365731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5375731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5385731Sroot 	}
5395731Sroot 	switch (how) {
5405731Sroot 	case DMSET:
5415731Sroot 		mbits = bits;
5425731Sroot 		break;
5435731Sroot 
5445731Sroot 	case DMBIS:
5455731Sroot 		mbits |= bits;
5465731Sroot 		break;
5475731Sroot 
5485731Sroot 	case DMBIC:
5495731Sroot 		mbits &= ~bits;
5505731Sroot 		break;
5515731Sroot 
5525731Sroot 	case DMGET:
5535731Sroot 		(void) splx(s);
5545731Sroot 		return(mbits);
5555731Sroot 	}
5565731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5575731Sroot 		mbits |= DZ_ACK|(unit&7);
5585731Sroot 		dzaddr->dzlcs = mbits;
5595731Sroot 	} else {
5605731Sroot 		if (mbits & DZ_DTR)
5615731Sroot 			dzaddr->dzdtr |= b;
5625731Sroot 		else
5635731Sroot 			dzaddr->dzdtr &= ~b;
5645731Sroot 	}
5655731Sroot 	(void) splx(s);
5665731Sroot 	return(mbits);
56717Sbill }
56817Sbill 
56916191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
57017Sbill dzscan()
57117Sbill {
57217Sbill 	register i;
57310019Ssam 	register struct dzdevice *dzaddr;
57417Sbill 	register bit;
57517Sbill 	register struct tty *tp;
5765731Sroot 	register car;
57716191Skarels 	int olddzsilos = dzsilos;
57816191Skarels 	int dztimer();
57917Sbill 
58017Sbill 	for (i = 0; i < dz_cnt ; i++) {
58117Sbill 		dzaddr = dzpdma[i].p_addr;
5822627Swnj 		if (dzaddr == 0)
5832627Swnj 			continue;
58417Sbill 		tp = &dz_tty[i];
58517Sbill 		bit = 1<<(i&07);
5865731Sroot 		car = 0;
5875731Sroot 		if (dzsoftCAR[i>>3]&bit)
5885731Sroot 			car = 1;
5895731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
5905731Sroot 			dzaddr->dzlcs = i&07;
5915731Sroot 			dzwait(dzaddr);
5925731Sroot 			car = dzaddr->dzlcs & DZ_CD;
5935731Sroot 		} else
5945731Sroot 			car = dzaddr->dzmsr&bit;
5955731Sroot 		if (car) {
59617Sbill 			/* carrier present */
5975407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
59817Sbill 				wakeup((caddr_t)&tp->t_rawq);
5995407Swnj 				tp->t_state |= TS_CARR_ON;
60017Sbill 			}
60117Sbill 		} else {
6025407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
6039551Ssam 			    (tp->t_flags&NOHANG) == 0) {
60417Sbill 				/* carrier lost */
6055407Swnj 				if (tp->t_state&TS_ISOPEN) {
606170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
607205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
608170Sbill 					dzaddr->dzdtr &= ~bit;
60912777Ssam 					ttyflush(tp, FREAD|FWRITE);
610170Sbill 				}
6115407Swnj 				tp->t_state &= ~TS_CARR_ON;
61217Sbill 			}
61317Sbill 		}
61417Sbill 	}
61516191Skarels 	for (i = 0; i < NDZ; i++) {
61616191Skarels 		ave(dzrate[i], dzchars[i], 8);
61716191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
61816397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
61916191Skarels 			dzsilos |= (1 << i);
62016191Skarels 			dztransitions++;		/*DEBUG*/
62116191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
62216397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
62316191Skarels 			dzsilos &= ~(1 << i);
62416191Skarels 		}
62516191Skarels 		dzchars[i] = 0;
62616191Skarels 	}
62716191Skarels 	if (dzsilos && !olddzsilos)
62816191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
62916191Skarels 	timeout(dzscan, (caddr_t)0, hz);
63017Sbill }
631119Sbill 
632119Sbill dztimer()
633119Sbill {
6348160Sroot 	register int dz;
63516191Skarels 	register int s;
636119Sbill 
63716191Skarels 	if (dzsilos == 0)
63816191Skarels 		return;
63916191Skarels 	s = spl5();
64016191Skarels 	dzfasttimers++;		/*DEBUG*/
6412645Swnj 	for (dz = 0; dz < NDZ; dz++)
64216191Skarels 		if (dzsilos & (1 << dz))
64316191Skarels 		    dzrint(dz);
6448160Sroot 	splx(s);
64516191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
646119Sbill }
647281Sbill 
648281Sbill /*
649281Sbill  * Reset state of driver if UBA reset was necessary.
650301Sbill  * Reset parameters and restart transmission on open lines.
651281Sbill  */
6522395Swnj dzreset(uban)
6532422Skre 	int uban;
654281Sbill {
6552395Swnj 	register int unit;
656281Sbill 	register struct tty *tp;
6572976Swnj 	register struct uba_device *ui;
658281Sbill 
6592645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6602422Skre 		ui = dzinfo[unit >> 3];
6612422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6622422Skre 			continue;
6632923Swnj 		if (unit%8 == 0)
6642923Swnj 			printf(" dz%d", unit>>3);
6652395Swnj 		tp = &dz_tty[unit];
6665407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6672395Swnj 			dzparam(unit);
6686157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6695407Swnj 			tp->t_state &= ~TS_BUSY;
670301Sbill 			dzstart(tp);
671281Sbill 		}
672281Sbill 	}
673281Sbill }
6741562Sbill #endif
675