xref: /csrg-svn/sys/vax/uba/dz.c (revision 39061)
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*39061Smarc  *	@(#)dz.c	7.4 (Berkeley) 09/06/89
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  */
1617123Sbloom #include "param.h"
1717123Sbloom #include "systm.h"
1817123Sbloom #include "ioctl.h"
1917123Sbloom #include "tty.h"
2017123Sbloom #include "dir.h"
2117123Sbloom #include "user.h"
2217123Sbloom #include "proc.h"
2317123Sbloom #include "map.h"
2417123Sbloom #include "buf.h"
2517123Sbloom #include "vm.h"
2617123Sbloom #include "conf.h"
2717123Sbloom #include "bkmac.h"
2817123Sbloom #include "file.h"
2917123Sbloom #include "uio.h"
3017123Sbloom #include "kernel.h"
3118313Sralph #include "syslog.h"
32145Sbill 
3317123Sbloom #include "pdma.h"
3417123Sbloom #include "ubavar.h"
3517123Sbloom #include "dzreg.h"
36*39061Smarc #include "machine/pte.h"
378474Sroot 
382469Swnj /*
392469Swnj  * Driver information for auto-configuration stuff.
402469Swnj  */
412606Swnj int	dzprobe(), dzattach(), dzrint();
422976Swnj struct	uba_device *dzinfo[NDZ];
432395Swnj u_short	dzstd[] = { 0 };
442395Swnj struct	uba_driver dzdriver =
452606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
462395Swnj 
472645Swnj #define	NDZLINE 	(NDZ*8)
4816191Skarels #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
492469Swnj 
502469Swnj int	dzstart(), dzxint(), dzdma();
51114Sbill int	ttrstrt();
522645Swnj struct	tty dz_tty[NDZLINE];
532645Swnj int	dz_cnt = { NDZLINE };
54119Sbill int	dzact;
5516191Skarels int	dzsilos;			/* mask of dz's with silo in use */
5616191Skarels int	dzchars[NDZ];			/* recent input count */
5716191Skarels int	dzrate[NDZ];			/* smoothed input count */
5816191Skarels int	dztimerintvl;			/* time interval for dztimer */
5916191Skarels int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
6016191Skarels int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
6117Sbill 
625731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
635731Sroot 
642469Swnj /*
652469Swnj  * Software copy of dzbrk since it isn't readable
662469Swnj  */
672645Swnj char	dz_brk[NDZ];
682645Swnj char	dzsoftCAR[NDZ];
695731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
7017Sbill 
712469Swnj /*
725731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
732469Swnj  * we have to use a timer to watch it.
742469Swnj  */
752469Swnj char	dz_timer;		/* timer started? */
762469Swnj 
772469Swnj /*
782469Swnj  * Pdma structures for fast output code
792469Swnj  */
802645Swnj struct	pdma dzpdma[NDZLINE];
812469Swnj 
82*39061Smarc struct speedtab dzspeedtab[] = {
83*39061Smarc 	0,	0,
84*39061Smarc 	50,	020,
85*39061Smarc 	75,	021,
86*39061Smarc 	110,	022,
87*39061Smarc 	134,	023,
88*39061Smarc 	150,	024,
89*39061Smarc 	300,	025,
90*39061Smarc 	600,	026,
91*39061Smarc 	1200,	027,
92*39061Smarc 	1800,	030,
93*39061Smarc 	2400,	032,
94*39061Smarc 	4800,	034,
95*39061Smarc 	9600,	036,
96*39061Smarc 	19200,	037,
97*39061Smarc 	EXTA,	037,
98*39061Smarc 	-1,	-1
99*39061Smarc };
10017Sbill 
10125397Skarels #ifndef	PORTSELECTOR
102*39061Smarc #define	ISPEED	TTYDEF_SPEED
103*39061Smarc #define	LFLAG	TTYDEF_LFLAG
1046616Ssam #else
1056616Ssam #define	ISPEED	B4800
106*39061Smarc #define	LFLAG	(TTYDEF_LFLAG&~ECHO)
1076616Ssam #endif
1086616Ssam 
1092606Swnj dzprobe(reg)
1102395Swnj 	caddr_t reg;
1112395Swnj {
1122457Swnj 	register int br, cvec;
11310019Ssam 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
1142395Swnj 
1152606Swnj #ifdef lint
1163102Swnj 	br = 0; cvec = br; br = cvec;
1174933Swnj 	dzrint(0); dzxint((struct tty *)0);
1182606Swnj #endif
1195731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1205731Sroot 	if (dzaddr->dzcsr & DZ_32)
1215731Sroot 		dzaddr->dzlnen = 1;
1225731Sroot 	else
1235731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1242457Swnj 	DELAY(100000);
1255731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1262457Swnj 	if (cvec && cvec != 0x200)
1272457Swnj 		cvec -= 4;
12810019Ssam 	return (sizeof (struct dzdevice));
1292395Swnj }
1302395Swnj 
1312606Swnj dzattach(ui)
1322976Swnj 	register struct uba_device *ui;
1332395Swnj {
1342395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1352395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1362606Swnj 	register int cntr;
1372645Swnj 	extern dzscan();
1382395Swnj 
1392606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
14010019Ssam 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
1412395Swnj 		pdp->p_arg = (int)tp;
1422395Swnj 		pdp->p_fcn = dzxint;
1432395Swnj 		pdp++, tp++;
1442395Swnj 	}
1452567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1462627Swnj 	if (dz_timer == 0) {
1472627Swnj 		dz_timer++;
1482756Swnj 		timeout(dzscan, (caddr_t)0, hz);
14916191Skarels 		dztimerintvl = FASTTIMER;
1502627Swnj 	}
1512395Swnj }
1522395Swnj 
15317Sbill /*ARGSUSED*/
1542395Swnj dzopen(dev, flag)
1552395Swnj 	dev_t dev;
15617Sbill {
15717Sbill 	register struct tty *tp;
1582395Swnj 	register int unit;
159*39061Smarc 	int dzparam();
16017Sbill 
1612395Swnj 	unit = minor(dev);
1628568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
1638568Sroot 		return (ENXIO);
1642395Swnj 	tp = &dz_tty[unit];
1652395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
16617Sbill 	tp->t_oproc = dzstart;
167*39061Smarc 	tp->t_param = dzparam;
168*39061Smarc 	tp->t_dev = dev;
1695407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
17017Sbill 		ttychars(tp);
17127050Skarels #ifndef PORTSELECTOR
17227050Skarels 		if (tp->t_ispeed == 0) {
173*39061Smarc #endif
174*39061Smarc 			tp->t_iflag = TTYDEF_IFLAG;
175*39061Smarc 			tp->t_oflag = TTYDEF_OFLAG;
176*39061Smarc 			tp->t_cflag = TTYDEF_CFLAG;
177*39061Smarc 			tp->t_lflag = LFLAG;
178*39061Smarc 			tp->t_ispeed = tp->t_ospeed = ISPEED;
179*39061Smarc #ifdef PORTSELECTOR
180*39061Smarc 			tp->t_cflag |= HUPCL;
181*39061Smarc #else
18227050Skarels 		}
183*39061Smarc #endif
184*39061Smarc 		dzparam(tp, &tp->t_termios);
185*39061Smarc 		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();
190*39061Smarc 	while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
191*39061Smarc 	       (tp->t_state & TS_CARR_ON) == 0) {
1925407Swnj 		tp->t_state |= TS_WOPEN;
19317Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
19417Sbill 	}
195114Sbill 	(void) spl0();
1968568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
19717Sbill }
19817Sbill 
1992395Swnj /*ARGSUSED*/
2002395Swnj dzclose(dev, flag)
2012395Swnj 	dev_t dev;
20217Sbill {
20317Sbill 	register struct tty *tp;
2042395Swnj 	register int unit;
20510019Ssam 	register struct dzdevice *dzaddr;
2066150Ssam 	int dz;
20717Sbill 
2082395Swnj 	unit = minor(dev);
2092395Swnj 	dz = unit >> 3;
2102395Swnj 	tp = &dz_tty[unit];
21117Sbill 	(*linesw[tp->t_line].l_close)(tp);
2125731Sroot 	dzaddr = dzpdma[unit].p_addr;
2135731Sroot 	if (dzaddr->dzcsr&DZ_32)
2146157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
2155731Sroot 	else
2165731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
217*39061Smarc 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
218*39061Smarc 	    (tp->t_state&TS_ISOPEN) == 0)
2196157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
22017Sbill 	ttyclose(tp);
22117Sbill }
22217Sbill 
223*39061Smarc dzread(dev, uio, flag)
2242395Swnj 	dev_t dev;
2257727Sroot 	struct uio *uio;
22617Sbill {
22717Sbill 	register struct tty *tp;
22817Sbill 
2292395Swnj 	tp = &dz_tty[minor(dev)];
230*39061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
23117Sbill }
23217Sbill 
233*39061Smarc dzwrite(dev, uio, flag)
2342395Swnj 	dev_t dev;
2357833Sroot 	struct uio *uio;
23617Sbill {
23717Sbill 	register struct tty *tp;
23817Sbill 
2392395Swnj 	tp = &dz_tty[minor(dev)];
240*39061Smarc 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24117Sbill }
24217Sbill 
243119Sbill /*ARGSUSED*/
2442395Swnj dzrint(dz)
2452395Swnj 	int dz;
24617Sbill {
24717Sbill 	register struct tty *tp;
248*39061Smarc 	register int c, cc;
24910019Ssam 	register struct dzdevice *dzaddr;
250119Sbill 	register struct tty *tp0;
2512395Swnj 	register int unit;
2522923Swnj 	int overrun = 0;
25317Sbill 
2542457Swnj 	if ((dzact & (1<<dz)) == 0)
2552457Swnj 		return;
2562457Swnj 	unit = dz * 8;
2572457Swnj 	dzaddr = dzpdma[unit].p_addr;
2582457Swnj 	tp0 = &dz_tty[unit];
2595731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2605731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2615731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2625731Sroot 		c = dzaddr->dzmtsr;
2635731Sroot 		tp = tp0 + (c&7);
2645731Sroot 		if (tp >= &dz_tty[dz_cnt])
2655731Sroot 			break;
2665731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2675731Sroot 		dzwait(dzaddr);		/* wait for them */
2685731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2695731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
27025397Skarels 			/* carrier present */
27125397Skarels 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
27225397Skarels 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
27325397Skarels 			dzaddr->dzlcs = DZ_ACK|(c&7);
2745731Sroot 	}
2752457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
276*39061Smarc 		cc = c&0xff;
27716191Skarels 		dzchars[dz]++;
2782457Swnj 		tp = tp0 + ((c>>8)&07);
2792457Swnj 		if (tp >= &dz_tty[dz_cnt])
28017Sbill 			continue;
2815407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2822457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2836616Ssam #ifdef PORTSELECTOR
2846616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2856616Ssam #endif
28625397Skarels 				continue;
2872457Swnj 		}
2882469Swnj 		if (c&DZ_FE)
289*39061Smarc 			cc |= TTY_FE;
2902923Swnj 		if (c&DZ_DO && overrun == 0) {
29124843Seric 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2922923Swnj 			overrun = 1;
2932923Swnj 		}
2942469Swnj 		if (c&DZ_PE)
295*39061Smarc 			cc |= TTY_PE;
296*39061Smarc 		(*linesw[tp->t_line].l_rint)(cc, tp);
29717Sbill 	}
29817Sbill }
29917Sbill 
30017Sbill /*ARGSUSED*/
3017631Ssam dzioctl(dev, cmd, data, flag)
3022395Swnj 	dev_t dev;
3037631Ssam 	caddr_t data;
30417Sbill {
30517Sbill 	register struct tty *tp;
3062395Swnj 	register int unit = minor(dev);
3072395Swnj 	register int dz = unit >> 3;
30810019Ssam 	register struct dzdevice *dzaddr;
3098568Sroot 	int error;
31017Sbill 
3112395Swnj 	tp = &dz_tty[unit];
3128568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3138568Sroot 	if (error >= 0)
3148568Sroot 		return (error);
3158568Sroot 	error = ttioctl(tp, cmd, data, flag);
316*39061Smarc 	if (error >= 0)
3178568Sroot 		return (error);
318*39061Smarc 
3198568Sroot 	switch (cmd) {
3202395Swnj 
321170Sbill 	case TIOCSBRK:
3225731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3235731Sroot 		if (dzaddr->dzcsr&DZ_32)
3246157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3255731Sroot 		else
3265731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
327170Sbill 		break;
3287631Ssam 
329170Sbill 	case TIOCCBRK:
3305731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3315731Sroot 		if (dzaddr->dzcsr&DZ_32)
3326157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3335731Sroot 		else
3345731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
335170Sbill 		break;
3367631Ssam 
337170Sbill 	case TIOCSDTR:
3386157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
339170Sbill 		break;
3407631Ssam 
341170Sbill 	case TIOCCDTR:
3426157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
343170Sbill 		break;
3447631Ssam 
3455731Sroot 	case TIOCMSET:
3467631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3475731Sroot 		break;
3487631Ssam 
3495731Sroot 	case TIOCMBIS:
3507631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3515731Sroot 		break;
3527631Ssam 
3535731Sroot 	case TIOCMBIC:
3547631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3555731Sroot 		break;
3567631Ssam 
3575731Sroot 	case TIOCMGET:
3587631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3595731Sroot 		break;
3607631Ssam 
361170Sbill 	default:
3628568Sroot 		return (ENOTTY);
363170Sbill 	}
3648568Sroot 	return (0);
36517Sbill }
3665731Sroot 
3675731Sroot dmtodz(bits)
3685731Sroot 	register int bits;
3695731Sroot {
3705731Sroot 	register int b;
3715731Sroot 
3725731Sroot 	b = (bits >>1) & 0370;
3735731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3745731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3755731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3765731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3775731Sroot 	return(b);
3785731Sroot }
3795731Sroot 
3805731Sroot dztodm(bits)
3815731Sroot 	register int bits;
3825731Sroot {
3835731Sroot 	register int b;
3845731Sroot 
3855731Sroot 	b = (bits << 1) & 0360;
3865731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3875731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3885731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3895731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3905731Sroot 	return(b);
3915731Sroot }
39217Sbill 
393*39061Smarc dzparam(tp, t)
394*39061Smarc 	register struct tty *tp;
395*39061Smarc 	register struct termios *t;
39617Sbill {
39710019Ssam 	register struct dzdevice *dzaddr;
3982395Swnj 	register int lpr;
399*39061Smarc 	register int cflag = t->c_cflag;
400*39061Smarc 	int unit = minor(tp->t_dev);
401*39061Smarc 	int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
402*39061Smarc 
403*39061Smarc 	/* check requested parameters */
404*39061Smarc         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
405*39061Smarc             (cflag&CSIZE) == CS5 || (cflag&CSIZE) == CS6)
406*39061Smarc                 return(EINVAL);
407*39061Smarc         /* and copy to tty */
408*39061Smarc         tp->t_ispeed = t->c_ispeed;
409*39061Smarc         tp->t_ospeed = t->c_ospeed;
410*39061Smarc         tp->t_cflag = cflag;
411*39061Smarc 
4122395Swnj 	dzaddr = dzpdma[unit].p_addr;
41316191Skarels 	if (dzsilos & (1 << (unit >> 3)))
41416191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
41516191Skarels 	else
41616191Skarels 		dzaddr->dzcsr = DZ_IEN;
4172395Swnj 	dzact |= (1<<(unit>>3));
418*39061Smarc 	if (ospeed == 0) {
4196157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
42017Sbill 		return;
42117Sbill 	}
422*39061Smarc 	lpr = (ospeed<<8) | (unit & 07);
423*39061Smarc 	if ((cflag&CSIZE) == CS7)
424*39061Smarc 		lpr |= BITS7;
425*39061Smarc 	else
42617Sbill 		lpr |= BITS8;
427*39061Smarc 	if (cflag&PARENB)
428*39061Smarc 		lpr |= PENABLE;
429*39061Smarc 	if (cflag&PARODD)
43017Sbill 		lpr |= OPAR;
431*39061Smarc 	if (cflag&CSTOPB)
4322469Swnj 		lpr |= TWOSB;
43317Sbill 	dzaddr->dzlpr = lpr;
434*39061Smarc 	return 0;
43517Sbill }
43617Sbill 
43717Sbill dzxint(tp)
4382395Swnj 	register struct tty *tp;
43917Sbill {
44017Sbill 	register struct pdma *dp;
44116191Skarels 	register dz, unit;
44217Sbill 
4432395Swnj 	dp = (struct pdma *)tp->t_addr;
4445407Swnj 	tp->t_state &= ~TS_BUSY;
4455407Swnj 	if (tp->t_state & TS_FLUSH)
4465407Swnj 		tp->t_state &= ~TS_FLUSH;
4475731Sroot 	else {
448281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4495731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4505731Sroot 	}
45117Sbill 	if (tp->t_line)
45217Sbill 		(*linesw[tp->t_line].l_start)(tp);
45317Sbill 	else
45417Sbill 		dzstart(tp);
4555731Sroot 	dz = minor(tp->t_dev) >> 3;
4565731Sroot 	unit = minor(tp->t_dev) & 7;
4575407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4585731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4595731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4605731Sroot 		else
4615731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
46217Sbill }
46317Sbill 
46417Sbill dzstart(tp)
4652395Swnj 	register struct tty *tp;
46617Sbill {
46717Sbill 	register struct pdma *dp;
46810019Ssam 	register struct dzdevice *dzaddr;
4692395Swnj 	register int cc;
4705731Sroot 	int s, dz, unit;
47117Sbill 
4722395Swnj 	dp = (struct pdma *)tp->t_addr;
47317Sbill 	dzaddr = dp->p_addr;
4742395Swnj 	s = spl5();
4755407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
47617Sbill 		goto out;
477*39061Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
4785407Swnj 		if (tp->t_state&TS_ASLEEP) {
4795407Swnj 			tp->t_state &= ~TS_ASLEEP;
4805407Swnj 			wakeup((caddr_t)&tp->t_outq);
4815407Swnj 		}
4825407Swnj 		if (tp->t_wsel) {
4835407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4845407Swnj 			tp->t_wsel = 0;
4855407Swnj 			tp->t_state &= ~TS_WCOLL;
4865407Swnj 		}
48717Sbill 	}
48817Sbill 	if (tp->t_outq.c_cc == 0)
48917Sbill 		goto out;
4909551Ssam 	if (tp->t_flags & (RAW|LITOUT))
49117Sbill 		cc = ndqb(&tp->t_outq, 0);
49217Sbill 	else {
49317Sbill 		cc = ndqb(&tp->t_outq, 0200);
49417Sbill 		if (cc == 0) {
49517Sbill 			cc = getc(&tp->t_outq);
4962469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
4975407Swnj 			tp->t_state |= TS_TIMEOUT;
49817Sbill 			goto out;
49917Sbill 		}
50017Sbill 	}
5015407Swnj 	tp->t_state |= TS_BUSY;
50217Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
50317Sbill 	dp->p_end += cc;
5045731Sroot 	dz = minor(tp->t_dev) >> 3;
5055731Sroot 	unit = minor(tp->t_dev) & 7;
5065731Sroot 	if (dzaddr->dzcsr & DZ_32)
5075731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
5085731Sroot 	else
5095731Sroot 		dzaddr->dztcr |= (1<<unit);
5102395Swnj out:
5112395Swnj 	splx(s);
51217Sbill }
51317Sbill 
51417Sbill /*
51517Sbill  * Stop output on a line.
51617Sbill  */
51717Sbill /*ARGSUSED*/
51817Sbill dzstop(tp, flag)
5192395Swnj 	register struct tty *tp;
52017Sbill {
52117Sbill 	register struct pdma *dp;
52217Sbill 	register int s;
52317Sbill 
5242395Swnj 	dp = (struct pdma *)tp->t_addr;
5252457Swnj 	s = spl5();
5265407Swnj 	if (tp->t_state & TS_BUSY) {
52717Sbill 		dp->p_end = dp->p_mem;
5285407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5295407Swnj 			tp->t_state |= TS_FLUSH;
53017Sbill 	}
53117Sbill 	splx(s);
53217Sbill }
53317Sbill 
5345731Sroot dzmctl(dev, bits, how)
5355731Sroot 	dev_t dev;
5365731Sroot 	int bits, how;
53717Sbill {
53810019Ssam 	register struct dzdevice *dzaddr;
5395731Sroot 	register int unit, mbits;
5405731Sroot 	int b, s;
5415731Sroot 
5425731Sroot 	unit = minor(dev);
5435731Sroot 	b = 1<<(unit&7);
5442395Swnj 	dzaddr = dzpdma[unit].p_addr;
5455731Sroot 	s = spl5();
5465731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5475731Sroot 		dzwait(dzaddr)
5485731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5495731Sroot 		dzaddr->dzlcs = unit&7;
5505731Sroot 		DELAY(100);
5515731Sroot 		dzwait(dzaddr)
5525731Sroot 		DELAY(100);
5535731Sroot 		mbits = dzaddr->dzlcs;
5545731Sroot 		mbits &= 0177770;
5555731Sroot 	} else {
5565731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5575731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5585731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5595731Sroot 	}
5605731Sroot 	switch (how) {
5615731Sroot 	case DMSET:
5625731Sroot 		mbits = bits;
5635731Sroot 		break;
5645731Sroot 
5655731Sroot 	case DMBIS:
5665731Sroot 		mbits |= bits;
5675731Sroot 		break;
5685731Sroot 
5695731Sroot 	case DMBIC:
5705731Sroot 		mbits &= ~bits;
5715731Sroot 		break;
5725731Sroot 
5735731Sroot 	case DMGET:
5745731Sroot 		(void) splx(s);
5755731Sroot 		return(mbits);
5765731Sroot 	}
5775731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5785731Sroot 		mbits |= DZ_ACK|(unit&7);
5795731Sroot 		dzaddr->dzlcs = mbits;
5805731Sroot 	} else {
5815731Sroot 		if (mbits & DZ_DTR)
5825731Sroot 			dzaddr->dzdtr |= b;
5835731Sroot 		else
5845731Sroot 			dzaddr->dzdtr &= ~b;
5855731Sroot 	}
58630387Skarels 	if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b)
58730387Skarels 		dz_tty[unit].t_state |= TS_CARR_ON;
5885731Sroot 	(void) splx(s);
5895731Sroot 	return(mbits);
59017Sbill }
59117Sbill 
59216191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
59317Sbill dzscan()
59417Sbill {
59517Sbill 	register i;
59610019Ssam 	register struct dzdevice *dzaddr;
59717Sbill 	register bit;
59817Sbill 	register struct tty *tp;
5995731Sroot 	register car;
60016191Skarels 	int olddzsilos = dzsilos;
60116191Skarels 	int dztimer();
60217Sbill 
60317Sbill 	for (i = 0; i < dz_cnt ; i++) {
60417Sbill 		dzaddr = dzpdma[i].p_addr;
6052627Swnj 		if (dzaddr == 0)
6062627Swnj 			continue;
60717Sbill 		tp = &dz_tty[i];
60817Sbill 		bit = 1<<(i&07);
6095731Sroot 		car = 0;
6105731Sroot 		if (dzsoftCAR[i>>3]&bit)
6115731Sroot 			car = 1;
6125731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
6135731Sroot 			dzaddr->dzlcs = i&07;
6145731Sroot 			dzwait(dzaddr);
6155731Sroot 			car = dzaddr->dzlcs & DZ_CD;
6165731Sroot 		} else
6175731Sroot 			car = dzaddr->dzmsr&bit;
6185731Sroot 		if (car) {
61917Sbill 			/* carrier present */
62025397Skarels 			if ((tp->t_state & TS_CARR_ON) == 0)
62125397Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
62225397Skarels 		} else if ((tp->t_state&TS_CARR_ON) &&
62325397Skarels 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
62425397Skarels 			dzaddr->dzdtr &= ~bit;
62517Sbill 	}
62616191Skarels 	for (i = 0; i < NDZ; i++) {
62716191Skarels 		ave(dzrate[i], dzchars[i], 8);
62816191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
62916397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
63016191Skarels 			dzsilos |= (1 << i);
63116191Skarels 			dztransitions++;		/*DEBUG*/
63216191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
63316397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
63416191Skarels 			dzsilos &= ~(1 << i);
63516191Skarels 		}
63616191Skarels 		dzchars[i] = 0;
63716191Skarels 	}
63816191Skarels 	if (dzsilos && !olddzsilos)
63916191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
64016191Skarels 	timeout(dzscan, (caddr_t)0, hz);
64117Sbill }
642119Sbill 
643119Sbill dztimer()
644119Sbill {
6458160Sroot 	register int dz;
64616191Skarels 	register int s;
647119Sbill 
64816191Skarels 	if (dzsilos == 0)
64916191Skarels 		return;
65016191Skarels 	s = spl5();
65116191Skarels 	dzfasttimers++;		/*DEBUG*/
6522645Swnj 	for (dz = 0; dz < NDZ; dz++)
65316191Skarels 		if (dzsilos & (1 << dz))
65416191Skarels 		    dzrint(dz);
6558160Sroot 	splx(s);
65616191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
657119Sbill }
658281Sbill 
659281Sbill /*
660281Sbill  * Reset state of driver if UBA reset was necessary.
661301Sbill  * Reset parameters and restart transmission on open lines.
662281Sbill  */
6632395Swnj dzreset(uban)
6642422Skre 	int uban;
665281Sbill {
6662395Swnj 	register int unit;
667281Sbill 	register struct tty *tp;
6682976Swnj 	register struct uba_device *ui;
669281Sbill 
6702645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6712422Skre 		ui = dzinfo[unit >> 3];
6722422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6732422Skre 			continue;
6742923Swnj 		if (unit%8 == 0)
6752923Swnj 			printf(" dz%d", unit>>3);
6762395Swnj 		tp = &dz_tty[unit];
6775407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6782395Swnj 			dzparam(unit);
6796157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6805407Swnj 			tp->t_state &= ~TS_BUSY;
681301Sbill 			dzstart(tp);
682281Sbill 		}
683281Sbill 	}
684281Sbill }
6851562Sbill #endif
686