xref: /csrg-svn/sys/vax/uba/dz.c (revision 45804)
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*45804Sbostic  *	@(#)dz.c	7.10 (Berkeley) 12/16/90
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  */
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/systm.h"
18*45804Sbostic #include "sys/ioctl.h"
19*45804Sbostic #include "sys/tty.h"
20*45804Sbostic #include "sys/user.h"
21*45804Sbostic #include "sys/proc.h"
22*45804Sbostic #include "sys/map.h"
23*45804Sbostic #include "sys/buf.h"
24*45804Sbostic #include "sys/vm.h"
25*45804Sbostic #include "sys/conf.h"
26*45804Sbostic #include "sys/bkmac.h"
27*45804Sbostic #include "sys/file.h"
28*45804Sbostic #include "sys/uio.h"
29*45804Sbostic #include "sys/kernel.h"
30*45804Sbostic #include "sys/syslog.h"
31145Sbill 
3217123Sbloom #include "pdma.h"
3317123Sbloom #include "ubavar.h"
3417123Sbloom #include "dzreg.h"
35*45804Sbostic #include "../include/pte.h"
368474Sroot 
372469Swnj /*
382469Swnj  * Driver information for auto-configuration stuff.
392469Swnj  */
402606Swnj int	dzprobe(), dzattach(), dzrint();
412976Swnj struct	uba_device *dzinfo[NDZ];
422395Swnj u_short	dzstd[] = { 0 };
432395Swnj struct	uba_driver dzdriver =
442606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
452395Swnj 
462645Swnj #define	NDZLINE 	(NDZ*8)
4716191Skarels #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
482469Swnj 
492469Swnj int	dzstart(), dzxint(), dzdma();
50114Sbill int	ttrstrt();
512645Swnj struct	tty dz_tty[NDZLINE];
522645Swnj int	dz_cnt = { NDZLINE };
53119Sbill int	dzact;
5416191Skarels int	dzsilos;			/* mask of dz's with silo in use */
5516191Skarels int	dzchars[NDZ];			/* recent input count */
5616191Skarels int	dzrate[NDZ];			/* smoothed input count */
5716191Skarels int	dztimerintvl;			/* time interval for dztimer */
5816191Skarels int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
5916191Skarels int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
6017Sbill 
615731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
625731Sroot 
632469Swnj /*
642469Swnj  * Software copy of dzbrk since it isn't readable
652469Swnj  */
662645Swnj char	dz_brk[NDZ];
672645Swnj char	dzsoftCAR[NDZ];
685731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
6917Sbill 
702469Swnj /*
715731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
722469Swnj  * we have to use a timer to watch it.
732469Swnj  */
742469Swnj char	dz_timer;		/* timer started? */
752469Swnj 
762469Swnj /*
772469Swnj  * Pdma structures for fast output code
782469Swnj  */
792645Swnj struct	pdma dzpdma[NDZLINE];
802469Swnj 
8139061Smarc struct speedtab dzspeedtab[] = {
8239061Smarc 	0,	0,
8339061Smarc 	50,	020,
8439061Smarc 	75,	021,
8539061Smarc 	110,	022,
8639061Smarc 	134,	023,
8739061Smarc 	150,	024,
8839061Smarc 	300,	025,
8939061Smarc 	600,	026,
9039061Smarc 	1200,	027,
9139061Smarc 	1800,	030,
9239061Smarc 	2400,	032,
9339061Smarc 	4800,	034,
9439061Smarc 	9600,	036,
9539061Smarc 	19200,	037,
9639061Smarc 	EXTA,	037,
9739061Smarc 	-1,	-1
9839061Smarc };
9917Sbill 
10025397Skarels #ifndef	PORTSELECTOR
10139061Smarc #define	ISPEED	TTYDEF_SPEED
10239061Smarc #define	LFLAG	TTYDEF_LFLAG
1036616Ssam #else
1046616Ssam #define	ISPEED	B4800
10539061Smarc #define	LFLAG	(TTYDEF_LFLAG&~ECHO)
1066616Ssam #endif
1076616Ssam 
1082606Swnj dzprobe(reg)
1092395Swnj 	caddr_t reg;
1102395Swnj {
1112457Swnj 	register int br, cvec;
11210019Ssam 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
1132395Swnj 
1142606Swnj #ifdef lint
1153102Swnj 	br = 0; cvec = br; br = cvec;
1164933Swnj 	dzrint(0); dzxint((struct tty *)0);
1172606Swnj #endif
1185731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1195731Sroot 	if (dzaddr->dzcsr & DZ_32)
1205731Sroot 		dzaddr->dzlnen = 1;
1215731Sroot 	else
1225731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1232457Swnj 	DELAY(100000);
1245731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1252457Swnj 	if (cvec && cvec != 0x200)
1262457Swnj 		cvec -= 4;
12710019Ssam 	return (sizeof (struct dzdevice));
1282395Swnj }
1292395Swnj 
1302606Swnj dzattach(ui)
1312976Swnj 	register struct uba_device *ui;
1322395Swnj {
1332395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1342395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1352606Swnj 	register int cntr;
1362645Swnj 	extern dzscan();
1372395Swnj 
1382606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
13910019Ssam 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
1402395Swnj 		pdp->p_arg = (int)tp;
1412395Swnj 		pdp->p_fcn = dzxint;
1422395Swnj 		pdp++, tp++;
1432395Swnj 	}
1442567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1452627Swnj 	if (dz_timer == 0) {
1462627Swnj 		dz_timer++;
1472756Swnj 		timeout(dzscan, (caddr_t)0, hz);
14816191Skarels 		dztimerintvl = FASTTIMER;
1492627Swnj 	}
1502395Swnj }
1512395Swnj 
15217Sbill /*ARGSUSED*/
1532395Swnj dzopen(dev, flag)
1542395Swnj 	dev_t dev;
15517Sbill {
15617Sbill 	register struct tty *tp;
1572395Swnj 	register int unit;
15840725Skarels 	int error, dzparam();
15917Sbill 
1602395Swnj 	unit = minor(dev);
1618568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
1628568Sroot 		return (ENXIO);
1632395Swnj 	tp = &dz_tty[unit];
1642395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
16517Sbill 	tp->t_oproc = dzstart;
16639061Smarc 	tp->t_param = dzparam;
16739061Smarc 	tp->t_dev = dev;
1685407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
16944393Smarc 		tp->t_state |= TS_WOPEN;
17017Sbill 		ttychars(tp);
17127050Skarels #ifndef PORTSELECTOR
17227050Skarels 		if (tp->t_ispeed == 0) {
17339061Smarc #endif
17439061Smarc 			tp->t_iflag = TTYDEF_IFLAG;
17539061Smarc 			tp->t_oflag = TTYDEF_OFLAG;
17639061Smarc 			tp->t_cflag = TTYDEF_CFLAG;
17739061Smarc 			tp->t_lflag = LFLAG;
17839061Smarc 			tp->t_ispeed = tp->t_ospeed = ISPEED;
17939061Smarc #ifdef PORTSELECTOR
18039061Smarc 			tp->t_cflag |= HUPCL;
18139061Smarc #else
18227050Skarels 		}
18339061Smarc #endif
18439061Smarc 		dzparam(tp, &tp->t_termios);
18539061Smarc 		ttsetwater(tp);
1868568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
1878568Sroot 		return (EBUSY);
1886157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
189114Sbill 	(void) spl5();
19040725Skarels 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
19139061Smarc 	       (tp->t_state & TS_CARR_ON) == 0) {
1925407Swnj 		tp->t_state |= TS_WOPEN;
19344393Smarc 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
19444393Smarc 		    ttopen, 0))
19540725Skarels 			break;
19617Sbill 	}
197114Sbill 	(void) spl0();
19840725Skarels 	if (error)
19940725Skarels 		return (error);
2008568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
20117Sbill }
20217Sbill 
2032395Swnj /*ARGSUSED*/
2042395Swnj dzclose(dev, flag)
2052395Swnj 	dev_t dev;
20617Sbill {
20717Sbill 	register struct tty *tp;
2082395Swnj 	register int unit;
20910019Ssam 	register struct dzdevice *dzaddr;
2106150Ssam 	int dz;
21117Sbill 
2122395Swnj 	unit = minor(dev);
2132395Swnj 	dz = unit >> 3;
2142395Swnj 	tp = &dz_tty[unit];
21517Sbill 	(*linesw[tp->t_line].l_close)(tp);
2165731Sroot 	dzaddr = dzpdma[unit].p_addr;
2175731Sroot 	if (dzaddr->dzcsr&DZ_32)
2186157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
2195731Sroot 	else
2205731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
22139061Smarc 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
22239061Smarc 	    (tp->t_state&TS_ISOPEN) == 0)
2236157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
22440725Skarels 	return (ttyclose(tp));
22517Sbill }
22617Sbill 
22739061Smarc dzread(dev, uio, flag)
2282395Swnj 	dev_t dev;
2297727Sroot 	struct uio *uio;
23017Sbill {
23117Sbill 	register struct tty *tp;
23217Sbill 
2332395Swnj 	tp = &dz_tty[minor(dev)];
23439061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
23517Sbill }
23617Sbill 
23739061Smarc dzwrite(dev, uio, flag)
2382395Swnj 	dev_t dev;
2397833Sroot 	struct uio *uio;
24017Sbill {
24117Sbill 	register struct tty *tp;
24217Sbill 
2432395Swnj 	tp = &dz_tty[minor(dev)];
24439061Smarc 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24517Sbill }
24617Sbill 
247119Sbill /*ARGSUSED*/
2482395Swnj dzrint(dz)
2492395Swnj 	int dz;
25017Sbill {
25117Sbill 	register struct tty *tp;
25239061Smarc 	register int c, cc;
25310019Ssam 	register struct dzdevice *dzaddr;
254119Sbill 	register struct tty *tp0;
2552395Swnj 	register int unit;
2562923Swnj 	int overrun = 0;
25717Sbill 
2582457Swnj 	if ((dzact & (1<<dz)) == 0)
2592457Swnj 		return;
2602457Swnj 	unit = dz * 8;
2612457Swnj 	dzaddr = dzpdma[unit].p_addr;
2622457Swnj 	tp0 = &dz_tty[unit];
2635731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2645731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2655731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2665731Sroot 		c = dzaddr->dzmtsr;
2675731Sroot 		tp = tp0 + (c&7);
2685731Sroot 		if (tp >= &dz_tty[dz_cnt])
2695731Sroot 			break;
2705731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2715731Sroot 		dzwait(dzaddr);		/* wait for them */
2725731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2735731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
27425397Skarels 			/* carrier present */
27525397Skarels 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
27625397Skarels 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
27725397Skarels 			dzaddr->dzlcs = DZ_ACK|(c&7);
2785731Sroot 	}
2792457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
28039061Smarc 		cc = c&0xff;
28116191Skarels 		dzchars[dz]++;
2822457Swnj 		tp = tp0 + ((c>>8)&07);
2832457Swnj 		if (tp >= &dz_tty[dz_cnt])
28417Sbill 			continue;
2855407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2862457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2876616Ssam #ifdef PORTSELECTOR
2886616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2896616Ssam #endif
29025397Skarels 				continue;
2912457Swnj 		}
2922469Swnj 		if (c&DZ_FE)
29339061Smarc 			cc |= TTY_FE;
2942923Swnj 		if (c&DZ_DO && overrun == 0) {
29524843Seric 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2962923Swnj 			overrun = 1;
2972923Swnj 		}
2982469Swnj 		if (c&DZ_PE)
29939061Smarc 			cc |= TTY_PE;
30039061Smarc 		(*linesw[tp->t_line].l_rint)(cc, tp);
30117Sbill 	}
30217Sbill }
30317Sbill 
30417Sbill /*ARGSUSED*/
3057631Ssam dzioctl(dev, cmd, data, flag)
3062395Swnj 	dev_t dev;
3077631Ssam 	caddr_t data;
30817Sbill {
30917Sbill 	register struct tty *tp;
3102395Swnj 	register int unit = minor(dev);
3112395Swnj 	register int dz = unit >> 3;
31210019Ssam 	register struct dzdevice *dzaddr;
3138568Sroot 	int error;
31417Sbill 
3152395Swnj 	tp = &dz_tty[unit];
3168568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3178568Sroot 	if (error >= 0)
3188568Sroot 		return (error);
3198568Sroot 	error = ttioctl(tp, cmd, data, flag);
32039061Smarc 	if (error >= 0)
3218568Sroot 		return (error);
32239061Smarc 
3238568Sroot 	switch (cmd) {
3242395Swnj 
325170Sbill 	case TIOCSBRK:
3265731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3275731Sroot 		if (dzaddr->dzcsr&DZ_32)
3286157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3295731Sroot 		else
3305731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
331170Sbill 		break;
3327631Ssam 
333170Sbill 	case TIOCCBRK:
3345731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3355731Sroot 		if (dzaddr->dzcsr&DZ_32)
3366157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3375731Sroot 		else
3385731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
339170Sbill 		break;
3407631Ssam 
341170Sbill 	case TIOCSDTR:
3426157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
343170Sbill 		break;
3447631Ssam 
345170Sbill 	case TIOCCDTR:
3466157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
347170Sbill 		break;
3487631Ssam 
3495731Sroot 	case TIOCMSET:
3507631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3515731Sroot 		break;
3527631Ssam 
3535731Sroot 	case TIOCMBIS:
3547631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3555731Sroot 		break;
3567631Ssam 
3575731Sroot 	case TIOCMBIC:
3587631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3595731Sroot 		break;
3607631Ssam 
3615731Sroot 	case TIOCMGET:
3627631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3635731Sroot 		break;
3647631Ssam 
365170Sbill 	default:
3668568Sroot 		return (ENOTTY);
367170Sbill 	}
3688568Sroot 	return (0);
36917Sbill }
3705731Sroot 
3715731Sroot dmtodz(bits)
3725731Sroot 	register int bits;
3735731Sroot {
3745731Sroot 	register int b;
3755731Sroot 
3765731Sroot 	b = (bits >>1) & 0370;
3775731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3785731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3795731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3805731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3815731Sroot 	return(b);
3825731Sroot }
3835731Sroot 
3845731Sroot dztodm(bits)
3855731Sroot 	register int bits;
3865731Sroot {
3875731Sroot 	register int b;
3885731Sroot 
3895731Sroot 	b = (bits << 1) & 0360;
3905731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3915731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3925731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3935731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3945731Sroot 	return(b);
3955731Sroot }
39617Sbill 
39739061Smarc dzparam(tp, t)
39839061Smarc 	register struct tty *tp;
39939061Smarc 	register struct termios *t;
40017Sbill {
40110019Ssam 	register struct dzdevice *dzaddr;
4022395Swnj 	register int lpr;
40339061Smarc 	register int cflag = t->c_cflag;
40439061Smarc 	int unit = minor(tp->t_dev);
40539061Smarc 	int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
40639061Smarc 
40739061Smarc 	/* check requested parameters */
40839061Smarc         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
40939061Smarc             (cflag&CSIZE) == CS5 || (cflag&CSIZE) == CS6)
41039061Smarc                 return(EINVAL);
41139061Smarc         /* and copy to tty */
41239061Smarc         tp->t_ispeed = t->c_ispeed;
41339061Smarc         tp->t_ospeed = t->c_ospeed;
41439061Smarc         tp->t_cflag = cflag;
41539061Smarc 
4162395Swnj 	dzaddr = dzpdma[unit].p_addr;
41716191Skarels 	if (dzsilos & (1 << (unit >> 3)))
41816191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
41916191Skarels 	else
42016191Skarels 		dzaddr->dzcsr = DZ_IEN;
4212395Swnj 	dzact |= (1<<(unit>>3));
42239061Smarc 	if (ospeed == 0) {
4236157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
42417Sbill 		return;
42517Sbill 	}
42639061Smarc 	lpr = (ospeed<<8) | (unit & 07);
42739061Smarc 	if ((cflag&CSIZE) == CS7)
42839061Smarc 		lpr |= BITS7;
42939061Smarc 	else
43017Sbill 		lpr |= BITS8;
43139061Smarc 	if (cflag&PARENB)
43239061Smarc 		lpr |= PENABLE;
43339061Smarc 	if (cflag&PARODD)
43417Sbill 		lpr |= OPAR;
43539061Smarc 	if (cflag&CSTOPB)
4362469Swnj 		lpr |= TWOSB;
43717Sbill 	dzaddr->dzlpr = lpr;
43839061Smarc 	return 0;
43917Sbill }
44017Sbill 
44117Sbill dzxint(tp)
4422395Swnj 	register struct tty *tp;
44317Sbill {
44417Sbill 	register struct pdma *dp;
44516191Skarels 	register dz, unit;
44617Sbill 
4472395Swnj 	dp = (struct pdma *)tp->t_addr;
4485407Swnj 	tp->t_state &= ~TS_BUSY;
4495407Swnj 	if (tp->t_state & TS_FLUSH)
4505407Swnj 		tp->t_state &= ~TS_FLUSH;
4515731Sroot 	else {
452281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4535731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4545731Sroot 	}
45517Sbill 	if (tp->t_line)
45617Sbill 		(*linesw[tp->t_line].l_start)(tp);
45717Sbill 	else
45817Sbill 		dzstart(tp);
4595731Sroot 	dz = minor(tp->t_dev) >> 3;
4605731Sroot 	unit = minor(tp->t_dev) & 7;
4615407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4625731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4635731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4645731Sroot 		else
4655731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
46617Sbill }
46717Sbill 
46817Sbill dzstart(tp)
4692395Swnj 	register struct tty *tp;
47017Sbill {
47117Sbill 	register struct pdma *dp;
47210019Ssam 	register struct dzdevice *dzaddr;
4732395Swnj 	register int cc;
4745731Sroot 	int s, dz, unit;
47517Sbill 
4762395Swnj 	dp = (struct pdma *)tp->t_addr;
47717Sbill 	dzaddr = dp->p_addr;
4782395Swnj 	s = spl5();
4795407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
48017Sbill 		goto out;
48139061Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
4825407Swnj 		if (tp->t_state&TS_ASLEEP) {
4835407Swnj 			tp->t_state &= ~TS_ASLEEP;
4845407Swnj 			wakeup((caddr_t)&tp->t_outq);
4855407Swnj 		}
4865407Swnj 		if (tp->t_wsel) {
4875407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4885407Swnj 			tp->t_wsel = 0;
4895407Swnj 			tp->t_state &= ~TS_WCOLL;
4905407Swnj 		}
49117Sbill 	}
49217Sbill 	if (tp->t_outq.c_cc == 0)
49317Sbill 		goto out;
4949551Ssam 	if (tp->t_flags & (RAW|LITOUT))
49517Sbill 		cc = ndqb(&tp->t_outq, 0);
49617Sbill 	else {
49717Sbill 		cc = ndqb(&tp->t_outq, 0200);
49817Sbill 		if (cc == 0) {
49917Sbill 			cc = getc(&tp->t_outq);
5002469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5015407Swnj 			tp->t_state |= TS_TIMEOUT;
50217Sbill 			goto out;
50317Sbill 		}
50417Sbill 	}
5055407Swnj 	tp->t_state |= TS_BUSY;
50617Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
50717Sbill 	dp->p_end += cc;
5085731Sroot 	dz = minor(tp->t_dev) >> 3;
5095731Sroot 	unit = minor(tp->t_dev) & 7;
5105731Sroot 	if (dzaddr->dzcsr & DZ_32)
5115731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
5125731Sroot 	else
5135731Sroot 		dzaddr->dztcr |= (1<<unit);
5142395Swnj out:
5152395Swnj 	splx(s);
51617Sbill }
51717Sbill 
51817Sbill /*
51917Sbill  * Stop output on a line.
52017Sbill  */
52117Sbill /*ARGSUSED*/
52217Sbill dzstop(tp, flag)
5232395Swnj 	register struct tty *tp;
52417Sbill {
52517Sbill 	register struct pdma *dp;
52617Sbill 	register int s;
52717Sbill 
5282395Swnj 	dp = (struct pdma *)tp->t_addr;
5292457Swnj 	s = spl5();
5305407Swnj 	if (tp->t_state & TS_BUSY) {
53117Sbill 		dp->p_end = dp->p_mem;
5325407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5335407Swnj 			tp->t_state |= TS_FLUSH;
53417Sbill 	}
53517Sbill 	splx(s);
53617Sbill }
53717Sbill 
5385731Sroot dzmctl(dev, bits, how)
5395731Sroot 	dev_t dev;
5405731Sroot 	int bits, how;
54117Sbill {
54210019Ssam 	register struct dzdevice *dzaddr;
5435731Sroot 	register int unit, mbits;
5445731Sroot 	int b, s;
5455731Sroot 
5465731Sroot 	unit = minor(dev);
5475731Sroot 	b = 1<<(unit&7);
5482395Swnj 	dzaddr = dzpdma[unit].p_addr;
5495731Sroot 	s = spl5();
5505731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5515731Sroot 		dzwait(dzaddr)
5525731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5535731Sroot 		dzaddr->dzlcs = unit&7;
5545731Sroot 		DELAY(100);
5555731Sroot 		dzwait(dzaddr)
5565731Sroot 		DELAY(100);
5575731Sroot 		mbits = dzaddr->dzlcs;
5585731Sroot 		mbits &= 0177770;
5595731Sroot 	} else {
5605731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5615731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5625731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5635731Sroot 	}
5645731Sroot 	switch (how) {
5655731Sroot 	case DMSET:
5665731Sroot 		mbits = bits;
5675731Sroot 		break;
5685731Sroot 
5695731Sroot 	case DMBIS:
5705731Sroot 		mbits |= bits;
5715731Sroot 		break;
5725731Sroot 
5735731Sroot 	case DMBIC:
5745731Sroot 		mbits &= ~bits;
5755731Sroot 		break;
5765731Sroot 
5775731Sroot 	case DMGET:
5785731Sroot 		(void) splx(s);
5795731Sroot 		return(mbits);
5805731Sroot 	}
5815731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5825731Sroot 		mbits |= DZ_ACK|(unit&7);
5835731Sroot 		dzaddr->dzlcs = mbits;
5845731Sroot 	} else {
5855731Sroot 		if (mbits & DZ_DTR)
5865731Sroot 			dzaddr->dzdtr |= b;
5875731Sroot 		else
5885731Sroot 			dzaddr->dzdtr &= ~b;
5895731Sroot 	}
59030387Skarels 	if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b)
59130387Skarels 		dz_tty[unit].t_state |= TS_CARR_ON;
5925731Sroot 	(void) splx(s);
5935731Sroot 	return(mbits);
59417Sbill }
59517Sbill 
59616191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
59717Sbill dzscan()
59817Sbill {
59917Sbill 	register i;
60010019Ssam 	register struct dzdevice *dzaddr;
60117Sbill 	register bit;
60217Sbill 	register struct tty *tp;
6035731Sroot 	register car;
60416191Skarels 	int olddzsilos = dzsilos;
60516191Skarels 	int dztimer();
60617Sbill 
60717Sbill 	for (i = 0; i < dz_cnt ; i++) {
60817Sbill 		dzaddr = dzpdma[i].p_addr;
6092627Swnj 		if (dzaddr == 0)
6102627Swnj 			continue;
61117Sbill 		tp = &dz_tty[i];
61217Sbill 		bit = 1<<(i&07);
6135731Sroot 		car = 0;
6145731Sroot 		if (dzsoftCAR[i>>3]&bit)
6155731Sroot 			car = 1;
6165731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
6175731Sroot 			dzaddr->dzlcs = i&07;
6185731Sroot 			dzwait(dzaddr);
6195731Sroot 			car = dzaddr->dzlcs & DZ_CD;
6205731Sroot 		} else
6215731Sroot 			car = dzaddr->dzmsr&bit;
6225731Sroot 		if (car) {
62317Sbill 			/* carrier present */
62425397Skarels 			if ((tp->t_state & TS_CARR_ON) == 0)
62525397Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
62625397Skarels 		} else if ((tp->t_state&TS_CARR_ON) &&
62725397Skarels 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
62825397Skarels 			dzaddr->dzdtr &= ~bit;
62917Sbill 	}
63016191Skarels 	for (i = 0; i < NDZ; i++) {
63116191Skarels 		ave(dzrate[i], dzchars[i], 8);
63216191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
63316397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
63416191Skarels 			dzsilos |= (1 << i);
63516191Skarels 			dztransitions++;		/*DEBUG*/
63616191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
63716397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
63816191Skarels 			dzsilos &= ~(1 << i);
63916191Skarels 		}
64016191Skarels 		dzchars[i] = 0;
64116191Skarels 	}
64216191Skarels 	if (dzsilos && !olddzsilos)
64316191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
64416191Skarels 	timeout(dzscan, (caddr_t)0, hz);
64517Sbill }
646119Sbill 
647119Sbill dztimer()
648119Sbill {
6498160Sroot 	register int dz;
65016191Skarels 	register int s;
651119Sbill 
65216191Skarels 	if (dzsilos == 0)
65316191Skarels 		return;
65416191Skarels 	s = spl5();
65516191Skarels 	dzfasttimers++;		/*DEBUG*/
6562645Swnj 	for (dz = 0; dz < NDZ; dz++)
65716191Skarels 		if (dzsilos & (1 << dz))
65816191Skarels 		    dzrint(dz);
6598160Sroot 	splx(s);
66016191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
661119Sbill }
662281Sbill 
663281Sbill /*
664281Sbill  * Reset state of driver if UBA reset was necessary.
665301Sbill  * Reset parameters and restart transmission on open lines.
666281Sbill  */
6672395Swnj dzreset(uban)
6682422Skre 	int uban;
669281Sbill {
6702395Swnj 	register int unit;
671281Sbill 	register struct tty *tp;
6722976Swnj 	register struct uba_device *ui;
673281Sbill 
6742645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6752422Skre 		ui = dzinfo[unit >> 3];
6762422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6772422Skre 			continue;
6782923Swnj 		if (unit%8 == 0)
6792923Swnj 			printf(" dz%d", unit>>3);
6802395Swnj 		tp = &dz_tty[unit];
6815407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6822395Swnj 			dzparam(unit);
6836157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6845407Swnj 			tp->t_state &= ~TS_BUSY;
685301Sbill 			dzstart(tp);
686281Sbill 		}
687281Sbill 	}
688281Sbill }
6891562Sbill #endif
690