xref: /csrg-svn/sys/vax/uba/dz.c (revision 49759)
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*49759Smarc  *	@(#)dz.c	7.14 (Berkeley) 05/16/91
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  */
1645804Sbostic #include "sys/param.h"
1745804Sbostic #include "sys/systm.h"
1845804Sbostic #include "sys/ioctl.h"
1945804Sbostic #include "sys/tty.h"
2045804Sbostic #include "sys/user.h"
2145804Sbostic #include "sys/proc.h"
2245804Sbostic #include "sys/map.h"
2345804Sbostic #include "sys/buf.h"
2445804Sbostic #include "sys/vm.h"
2545804Sbostic #include "sys/conf.h"
2645804Sbostic #include "sys/file.h"
2745804Sbostic #include "sys/uio.h"
2845804Sbostic #include "sys/kernel.h"
2945804Sbostic #include "sys/syslog.h"
30145Sbill 
3117123Sbloom #include "pdma.h"
3217123Sbloom #include "ubavar.h"
3317123Sbloom #include "dzreg.h"
3445804Sbostic #include "../include/pte.h"
358474Sroot 
362469Swnj /*
372469Swnj  * Driver information for auto-configuration stuff.
382469Swnj  */
392606Swnj int	dzprobe(), dzattach(), dzrint();
402976Swnj struct	uba_device *dzinfo[NDZ];
412395Swnj u_short	dzstd[] = { 0 };
422395Swnj struct	uba_driver dzdriver =
432606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
442395Swnj 
452645Swnj #define	NDZLINE 	(NDZ*8)
4616191Skarels #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
472469Swnj 
482469Swnj int	dzstart(), dzxint(), dzdma();
49114Sbill int	ttrstrt();
502645Swnj struct	tty dz_tty[NDZLINE];
512645Swnj int	dz_cnt = { NDZLINE };
52119Sbill int	dzact;
5316191Skarels int	dzsilos;			/* mask of dz's with silo in use */
5416191Skarels int	dzchars[NDZ];			/* recent input count */
5516191Skarels int	dzrate[NDZ];			/* smoothed input count */
5616191Skarels int	dztimerintvl;			/* time interval for dztimer */
5716191Skarels int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
5816191Skarels int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
5917Sbill 
605731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
615731Sroot 
622469Swnj /*
632469Swnj  * Software copy of dzbrk since it isn't readable
642469Swnj  */
652645Swnj char	dz_brk[NDZ];
662645Swnj char	dzsoftCAR[NDZ];
675731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
6817Sbill 
692469Swnj /*
705731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
712469Swnj  * we have to use a timer to watch it.
722469Swnj  */
732469Swnj char	dz_timer;		/* timer started? */
742469Swnj 
752469Swnj /*
762469Swnj  * Pdma structures for fast output code
772469Swnj  */
782645Swnj struct	pdma dzpdma[NDZLINE];
792469Swnj 
8039061Smarc struct speedtab dzspeedtab[] = {
8139061Smarc 	0,	0,
8239061Smarc 	50,	020,
8339061Smarc 	75,	021,
8439061Smarc 	110,	022,
8539061Smarc 	134,	023,
8639061Smarc 	150,	024,
8739061Smarc 	300,	025,
8839061Smarc 	600,	026,
8939061Smarc 	1200,	027,
9039061Smarc 	1800,	030,
9139061Smarc 	2400,	032,
9239061Smarc 	4800,	034,
9339061Smarc 	9600,	036,
9439061Smarc 	19200,	037,
9539061Smarc 	EXTA,	037,
9639061Smarc 	-1,	-1
9739061Smarc };
9817Sbill 
9925397Skarels #ifndef	PORTSELECTOR
10039061Smarc #define	ISPEED	TTYDEF_SPEED
10139061Smarc #define	LFLAG	TTYDEF_LFLAG
1026616Ssam #else
1036616Ssam #define	ISPEED	B4800
10439061Smarc #define	LFLAG	(TTYDEF_LFLAG&~ECHO)
1056616Ssam #endif
1066616Ssam 
dzprobe(reg)1072606Swnj dzprobe(reg)
1082395Swnj 	caddr_t reg;
1092395Swnj {
1102457Swnj 	register int br, cvec;
11110019Ssam 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
1122395Swnj 
1132606Swnj #ifdef lint
1143102Swnj 	br = 0; cvec = br; br = cvec;
1154933Swnj 	dzrint(0); dzxint((struct tty *)0);
1162606Swnj #endif
1175731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1185731Sroot 	if (dzaddr->dzcsr & DZ_32)
1195731Sroot 		dzaddr->dzlnen = 1;
1205731Sroot 	else
1215731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1222457Swnj 	DELAY(100000);
1235731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1242457Swnj 	if (cvec && cvec != 0x200)
1252457Swnj 		cvec -= 4;
12610019Ssam 	return (sizeof (struct dzdevice));
1272395Swnj }
1282395Swnj 
dzattach(ui)1292606Swnj dzattach(ui)
1302976Swnj 	register struct uba_device *ui;
1312395Swnj {
1322395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1332395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1342606Swnj 	register int cntr;
1352645Swnj 	extern dzscan();
1362395Swnj 
1372606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
13810019Ssam 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
1392395Swnj 		pdp->p_arg = (int)tp;
1402395Swnj 		pdp->p_fcn = dzxint;
1412395Swnj 		pdp++, tp++;
1422395Swnj 	}
1432567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1442627Swnj 	if (dz_timer == 0) {
1452627Swnj 		dz_timer++;
1462756Swnj 		timeout(dzscan, (caddr_t)0, hz);
14716191Skarels 		dztimerintvl = FASTTIMER;
1482627Swnj 	}
1492395Swnj }
1502395Swnj 
15117Sbill /*ARGSUSED*/
dzopen(dev,flag)1522395Swnj dzopen(dev, flag)
1532395Swnj 	dev_t dev;
15417Sbill {
15517Sbill 	register struct tty *tp;
1562395Swnj 	register int unit;
15747687Smckusick 	int error = 0, dzparam();
15817Sbill 
1592395Swnj 	unit = minor(dev);
1608568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
1618568Sroot 		return (ENXIO);
1622395Swnj 	tp = &dz_tty[unit];
1632395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
16417Sbill 	tp->t_oproc = dzstart;
16539061Smarc 	tp->t_param = dzparam;
16639061Smarc 	tp->t_dev = dev;
1675407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
16844393Smarc 		tp->t_state |= TS_WOPEN;
16917Sbill 		ttychars(tp);
17027050Skarels #ifndef PORTSELECTOR
17127050Skarels 		if (tp->t_ispeed == 0) {
17239061Smarc #endif
17339061Smarc 			tp->t_iflag = TTYDEF_IFLAG;
17439061Smarc 			tp->t_oflag = TTYDEF_OFLAG;
17539061Smarc 			tp->t_cflag = TTYDEF_CFLAG;
17639061Smarc 			tp->t_lflag = LFLAG;
17739061Smarc 			tp->t_ispeed = tp->t_ospeed = ISPEED;
17839061Smarc #ifdef PORTSELECTOR
17939061Smarc 			tp->t_cflag |= HUPCL;
18039061Smarc #else
18127050Skarels 		}
18239061Smarc #endif
18339061Smarc 		dzparam(tp, &tp->t_termios);
18439061Smarc 		ttsetwater(tp);
1858568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
1868568Sroot 		return (EBUSY);
1876157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
188114Sbill 	(void) spl5();
18940725Skarels 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
19039061Smarc 	       (tp->t_state & TS_CARR_ON) == 0) {
1915407Swnj 		tp->t_state |= TS_WOPEN;
19244393Smarc 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
19344393Smarc 		    ttopen, 0))
19440725Skarels 			break;
19517Sbill 	}
196114Sbill 	(void) spl0();
19740725Skarels 	if (error)
19840725Skarels 		return (error);
1998568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
20017Sbill }
20117Sbill 
2022395Swnj /*ARGSUSED*/
dzclose(dev,flag,mode,p)203*49759Smarc dzclose(dev, flag, mode, p)
2042395Swnj 	dev_t dev;
205*49759Smarc 	int flag, mode;
206*49759Smarc 	struct proc *p;
20717Sbill {
20817Sbill 	register struct tty *tp;
2092395Swnj 	register int unit;
21010019Ssam 	register struct dzdevice *dzaddr;
2116150Ssam 	int dz;
21217Sbill 
2132395Swnj 	unit = minor(dev);
2142395Swnj 	dz = unit >> 3;
2152395Swnj 	tp = &dz_tty[unit];
216*49759Smarc 	(*linesw[tp->t_line].l_close)(tp, flag);
2175731Sroot 	dzaddr = dzpdma[unit].p_addr;
2185731Sroot 	if (dzaddr->dzcsr&DZ_32)
2196157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
2205731Sroot 	else
2215731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
22239061Smarc 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
22339061Smarc 	    (tp->t_state&TS_ISOPEN) == 0)
2246157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
22540725Skarels 	return (ttyclose(tp));
22617Sbill }
22717Sbill 
dzread(dev,uio,flag)22839061Smarc dzread(dev, uio, flag)
2292395Swnj 	dev_t dev;
2307727Sroot 	struct uio *uio;
23117Sbill {
23217Sbill 	register struct tty *tp;
23317Sbill 
2342395Swnj 	tp = &dz_tty[minor(dev)];
23539061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
23617Sbill }
23717Sbill 
dzwrite(dev,uio,flag)23839061Smarc dzwrite(dev, uio, flag)
2392395Swnj 	dev_t dev;
2407833Sroot 	struct uio *uio;
24117Sbill {
24217Sbill 	register struct tty *tp;
24317Sbill 
2442395Swnj 	tp = &dz_tty[minor(dev)];
24539061Smarc 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24617Sbill }
24717Sbill 
248119Sbill /*ARGSUSED*/
dzrint(dz)2492395Swnj dzrint(dz)
2502395Swnj 	int dz;
25117Sbill {
25217Sbill 	register struct tty *tp;
25339061Smarc 	register int c, cc;
25410019Ssam 	register struct dzdevice *dzaddr;
255119Sbill 	register struct tty *tp0;
2562395Swnj 	register int unit;
2572923Swnj 	int overrun = 0;
25817Sbill 
2592457Swnj 	if ((dzact & (1<<dz)) == 0)
2602457Swnj 		return;
2612457Swnj 	unit = dz * 8;
2622457Swnj 	dzaddr = dzpdma[unit].p_addr;
2632457Swnj 	tp0 = &dz_tty[unit];
2645731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2655731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2665731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2675731Sroot 		c = dzaddr->dzmtsr;
2685731Sroot 		tp = tp0 + (c&7);
2695731Sroot 		if (tp >= &dz_tty[dz_cnt])
2705731Sroot 			break;
2715731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2725731Sroot 		dzwait(dzaddr);		/* wait for them */
2735731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2745731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
27525397Skarels 			/* carrier present */
27625397Skarels 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
27725397Skarels 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
27825397Skarels 			dzaddr->dzlcs = DZ_ACK|(c&7);
2795731Sroot 	}
2802457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
28139061Smarc 		cc = c&0xff;
28216191Skarels 		dzchars[dz]++;
2832457Swnj 		tp = tp0 + ((c>>8)&07);
2842457Swnj 		if (tp >= &dz_tty[dz_cnt])
28517Sbill 			continue;
2865407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2872457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2886616Ssam #ifdef PORTSELECTOR
2896616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
2906616Ssam #endif
29125397Skarels 				continue;
2922457Swnj 		}
2932469Swnj 		if (c&DZ_FE)
29439061Smarc 			cc |= TTY_FE;
2952923Swnj 		if (c&DZ_DO && overrun == 0) {
29624843Seric 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
2972923Swnj 			overrun = 1;
2982923Swnj 		}
2992469Swnj 		if (c&DZ_PE)
30039061Smarc 			cc |= TTY_PE;
30139061Smarc 		(*linesw[tp->t_line].l_rint)(cc, tp);
30217Sbill 	}
30317Sbill }
30417Sbill 
30517Sbill /*ARGSUSED*/
dzioctl(dev,cmd,data,flag)3067631Ssam dzioctl(dev, cmd, data, flag)
3072395Swnj 	dev_t dev;
3087631Ssam 	caddr_t data;
30917Sbill {
31017Sbill 	register struct tty *tp;
3112395Swnj 	register int unit = minor(dev);
3122395Swnj 	register int dz = unit >> 3;
31310019Ssam 	register struct dzdevice *dzaddr;
3148568Sroot 	int error;
31517Sbill 
3162395Swnj 	tp = &dz_tty[unit];
3178568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3188568Sroot 	if (error >= 0)
3198568Sroot 		return (error);
3208568Sroot 	error = ttioctl(tp, cmd, data, flag);
32139061Smarc 	if (error >= 0)
3228568Sroot 		return (error);
32339061Smarc 
3248568Sroot 	switch (cmd) {
3252395Swnj 
326170Sbill 	case TIOCSBRK:
3275731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3285731Sroot 		if (dzaddr->dzcsr&DZ_32)
3296157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3305731Sroot 		else
3315731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
332170Sbill 		break;
3337631Ssam 
334170Sbill 	case TIOCCBRK:
3355731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3365731Sroot 		if (dzaddr->dzcsr&DZ_32)
3376157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3385731Sroot 		else
3395731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
340170Sbill 		break;
3417631Ssam 
342170Sbill 	case TIOCSDTR:
3436157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
344170Sbill 		break;
3457631Ssam 
346170Sbill 	case TIOCCDTR:
3476157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
348170Sbill 		break;
3497631Ssam 
3505731Sroot 	case TIOCMSET:
3517631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
3525731Sroot 		break;
3537631Ssam 
3545731Sroot 	case TIOCMBIS:
3557631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
3565731Sroot 		break;
3577631Ssam 
3585731Sroot 	case TIOCMBIC:
3597631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
3605731Sroot 		break;
3617631Ssam 
3625731Sroot 	case TIOCMGET:
3637631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
3645731Sroot 		break;
3657631Ssam 
366170Sbill 	default:
3678568Sroot 		return (ENOTTY);
368170Sbill 	}
3698568Sroot 	return (0);
37017Sbill }
3715731Sroot 
dmtodz(bits)3725731Sroot dmtodz(bits)
3735731Sroot 	register int bits;
3745731Sroot {
3755731Sroot 	register int b;
3765731Sroot 
3775731Sroot 	b = (bits >>1) & 0370;
3785731Sroot 	if (bits & DML_ST) b |= DZ_ST;
3795731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
3805731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
3815731Sroot 	if (bits & DML_LE) b |= DZ_LE;
3825731Sroot 	return(b);
3835731Sroot }
3845731Sroot 
dztodm(bits)3855731Sroot dztodm(bits)
3865731Sroot 	register int bits;
3875731Sroot {
3885731Sroot 	register int b;
3895731Sroot 
3905731Sroot 	b = (bits << 1) & 0360;
3915731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
3925731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
3935731Sroot 	if (bits & DZ_ST) b |= DML_ST;
3945731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
3955731Sroot 	return(b);
3965731Sroot }
39717Sbill 
dzparam(tp,t)39839061Smarc dzparam(tp, t)
39939061Smarc 	register struct tty *tp;
40039061Smarc 	register struct termios *t;
40117Sbill {
40210019Ssam 	register struct dzdevice *dzaddr;
4032395Swnj 	register int lpr;
40439061Smarc 	register int cflag = t->c_cflag;
40539061Smarc 	int unit = minor(tp->t_dev);
40639061Smarc 	int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
40739061Smarc 
40839061Smarc 	/* check requested parameters */
40939061Smarc         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
41039061Smarc             (cflag&CSIZE) == CS5 || (cflag&CSIZE) == CS6)
41139061Smarc                 return(EINVAL);
41239061Smarc         /* and copy to tty */
41339061Smarc         tp->t_ispeed = t->c_ispeed;
41439061Smarc         tp->t_ospeed = t->c_ospeed;
41539061Smarc         tp->t_cflag = cflag;
41639061Smarc 
4172395Swnj 	dzaddr = dzpdma[unit].p_addr;
41816191Skarels 	if (dzsilos & (1 << (unit >> 3)))
41916191Skarels 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
42016191Skarels 	else
42116191Skarels 		dzaddr->dzcsr = DZ_IEN;
4222395Swnj 	dzact |= (1<<(unit>>3));
42347286Sbostic 	if (ospeed == 0)
4246157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
42547286Sbostic 	else {
42647286Sbostic 		lpr = (ospeed<<8) | (unit & 07);
42747286Sbostic 		if ((cflag&CSIZE) == CS7)
42847286Sbostic 			lpr |= BITS7;
42947286Sbostic 		else
43047286Sbostic 			lpr |= BITS8;
43147286Sbostic 		if (cflag&PARENB)
43247286Sbostic 			lpr |= PENABLE;
43347286Sbostic 		if (cflag&PARODD)
43447286Sbostic 			lpr |= OPAR;
43547286Sbostic 		if (cflag&CSTOPB)
43647286Sbostic 			lpr |= TWOSB;
43747286Sbostic 		dzaddr->dzlpr = lpr;
43817Sbill 	}
43947286Sbostic 	return(0);
44017Sbill }
44117Sbill 
dzxint(tp)44217Sbill dzxint(tp)
4432395Swnj 	register struct tty *tp;
44417Sbill {
44517Sbill 	register struct pdma *dp;
44616191Skarels 	register dz, unit;
44717Sbill 
4482395Swnj 	dp = (struct pdma *)tp->t_addr;
4495407Swnj 	tp->t_state &= ~TS_BUSY;
4505407Swnj 	if (tp->t_state & TS_FLUSH)
4515407Swnj 		tp->t_state &= ~TS_FLUSH;
4525731Sroot 	else {
453281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4545731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4555731Sroot 	}
45617Sbill 	if (tp->t_line)
45717Sbill 		(*linesw[tp->t_line].l_start)(tp);
45817Sbill 	else
45917Sbill 		dzstart(tp);
4605731Sroot 	dz = minor(tp->t_dev) >> 3;
4615731Sroot 	unit = minor(tp->t_dev) & 7;
4625407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4635731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4645731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4655731Sroot 		else
4665731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
46717Sbill }
46817Sbill 
dzstart(tp)46917Sbill dzstart(tp)
4702395Swnj 	register struct tty *tp;
47117Sbill {
47217Sbill 	register struct pdma *dp;
47310019Ssam 	register struct dzdevice *dzaddr;
4742395Swnj 	register int cc;
4755731Sroot 	int s, dz, unit;
47617Sbill 
4772395Swnj 	dp = (struct pdma *)tp->t_addr;
47817Sbill 	dzaddr = dp->p_addr;
4792395Swnj 	s = spl5();
4805407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
48117Sbill 		goto out;
48239061Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
4835407Swnj 		if (tp->t_state&TS_ASLEEP) {
4845407Swnj 			tp->t_state &= ~TS_ASLEEP;
4855407Swnj 			wakeup((caddr_t)&tp->t_outq);
4865407Swnj 		}
4875407Swnj 		if (tp->t_wsel) {
4885407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
4895407Swnj 			tp->t_wsel = 0;
4905407Swnj 			tp->t_state &= ~TS_WCOLL;
4915407Swnj 		}
49217Sbill 	}
49317Sbill 	if (tp->t_outq.c_cc == 0)
49417Sbill 		goto out;
4959551Ssam 	if (tp->t_flags & (RAW|LITOUT))
49617Sbill 		cc = ndqb(&tp->t_outq, 0);
49717Sbill 	else {
49817Sbill 		cc = ndqb(&tp->t_outq, 0200);
49917Sbill 		if (cc == 0) {
50017Sbill 			cc = getc(&tp->t_outq);
5012469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5025407Swnj 			tp->t_state |= TS_TIMEOUT;
50317Sbill 			goto out;
50417Sbill 		}
50517Sbill 	}
5065407Swnj 	tp->t_state |= TS_BUSY;
50717Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
50817Sbill 	dp->p_end += cc;
5095731Sroot 	dz = minor(tp->t_dev) >> 3;
5105731Sroot 	unit = minor(tp->t_dev) & 7;
5115731Sroot 	if (dzaddr->dzcsr & DZ_32)
5125731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
5135731Sroot 	else
5145731Sroot 		dzaddr->dztcr |= (1<<unit);
5152395Swnj out:
5162395Swnj 	splx(s);
51717Sbill }
51817Sbill 
51917Sbill /*
52017Sbill  * Stop output on a line.
52117Sbill  */
52217Sbill /*ARGSUSED*/
dzstop(tp,flag)52317Sbill dzstop(tp, flag)
5242395Swnj 	register struct tty *tp;
52517Sbill {
52617Sbill 	register struct pdma *dp;
52717Sbill 	register int s;
52817Sbill 
5292395Swnj 	dp = (struct pdma *)tp->t_addr;
5302457Swnj 	s = spl5();
5315407Swnj 	if (tp->t_state & TS_BUSY) {
53217Sbill 		dp->p_end = dp->p_mem;
5335407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5345407Swnj 			tp->t_state |= TS_FLUSH;
53517Sbill 	}
53617Sbill 	splx(s);
53717Sbill }
53817Sbill 
dzmctl(dev,bits,how)5395731Sroot dzmctl(dev, bits, how)
5405731Sroot 	dev_t dev;
5415731Sroot 	int bits, how;
54217Sbill {
54310019Ssam 	register struct dzdevice *dzaddr;
5445731Sroot 	register int unit, mbits;
5455731Sroot 	int b, s;
5465731Sroot 
5475731Sroot 	unit = minor(dev);
5485731Sroot 	b = 1<<(unit&7);
5492395Swnj 	dzaddr = dzpdma[unit].p_addr;
5505731Sroot 	s = spl5();
5515731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5525731Sroot 		dzwait(dzaddr)
5535731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5545731Sroot 		dzaddr->dzlcs = unit&7;
5555731Sroot 		DELAY(100);
5565731Sroot 		dzwait(dzaddr)
5575731Sroot 		DELAY(100);
5585731Sroot 		mbits = dzaddr->dzlcs;
5595731Sroot 		mbits &= 0177770;
5605731Sroot 	} else {
5615731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5625731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5635731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5645731Sroot 	}
5655731Sroot 	switch (how) {
5665731Sroot 	case DMSET:
5675731Sroot 		mbits = bits;
5685731Sroot 		break;
5695731Sroot 
5705731Sroot 	case DMBIS:
5715731Sroot 		mbits |= bits;
5725731Sroot 		break;
5735731Sroot 
5745731Sroot 	case DMBIC:
5755731Sroot 		mbits &= ~bits;
5765731Sroot 		break;
5775731Sroot 
5785731Sroot 	case DMGET:
5795731Sroot 		(void) splx(s);
5805731Sroot 		return(mbits);
5815731Sroot 	}
5825731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5835731Sroot 		mbits |= DZ_ACK|(unit&7);
5845731Sroot 		dzaddr->dzlcs = mbits;
5855731Sroot 	} else {
5865731Sroot 		if (mbits & DZ_DTR)
5875731Sroot 			dzaddr->dzdtr |= b;
5885731Sroot 		else
5895731Sroot 			dzaddr->dzdtr &= ~b;
5905731Sroot 	}
59130387Skarels 	if (mbits & DZ_DTR && dzsoftCAR[unit >> 3] & b)
59230387Skarels 		dz_tty[unit].t_state |= TS_CARR_ON;
5935731Sroot 	(void) splx(s);
5945731Sroot 	return(mbits);
59517Sbill }
59617Sbill 
59716191Skarels int dztransitions, dzfasttimers;		/*DEBUG*/
dzscan()59817Sbill dzscan()
59917Sbill {
60017Sbill 	register i;
60110019Ssam 	register struct dzdevice *dzaddr;
60217Sbill 	register bit;
60317Sbill 	register struct tty *tp;
6045731Sroot 	register car;
60516191Skarels 	int olddzsilos = dzsilos;
60616191Skarels 	int dztimer();
60717Sbill 
60817Sbill 	for (i = 0; i < dz_cnt ; i++) {
60917Sbill 		dzaddr = dzpdma[i].p_addr;
6102627Swnj 		if (dzaddr == 0)
6112627Swnj 			continue;
61217Sbill 		tp = &dz_tty[i];
61317Sbill 		bit = 1<<(i&07);
6145731Sroot 		car = 0;
6155731Sroot 		if (dzsoftCAR[i>>3]&bit)
6165731Sroot 			car = 1;
6175731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
6185731Sroot 			dzaddr->dzlcs = i&07;
6195731Sroot 			dzwait(dzaddr);
6205731Sroot 			car = dzaddr->dzlcs & DZ_CD;
6215731Sroot 		} else
6225731Sroot 			car = dzaddr->dzmsr&bit;
6235731Sroot 		if (car) {
62417Sbill 			/* carrier present */
62525397Skarels 			if ((tp->t_state & TS_CARR_ON) == 0)
62625397Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
62725397Skarels 		} else if ((tp->t_state&TS_CARR_ON) &&
62825397Skarels 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
62925397Skarels 			dzaddr->dzdtr &= ~bit;
63017Sbill 	}
63116191Skarels 	for (i = 0; i < NDZ; i++) {
63216191Skarels 		ave(dzrate[i], dzchars[i], 8);
63316191Skarels 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
63416397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
63516191Skarels 			dzsilos |= (1 << i);
63616191Skarels 			dztransitions++;		/*DEBUG*/
63716191Skarels 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
63816397Ssam 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
63916191Skarels 			dzsilos &= ~(1 << i);
64016191Skarels 		}
64116191Skarels 		dzchars[i] = 0;
64216191Skarels 	}
64316191Skarels 	if (dzsilos && !olddzsilos)
64416191Skarels 		timeout(dztimer, (caddr_t)0, dztimerintvl);
64516191Skarels 	timeout(dzscan, (caddr_t)0, hz);
64617Sbill }
647119Sbill 
dztimer()648119Sbill dztimer()
649119Sbill {
6508160Sroot 	register int dz;
65116191Skarels 	register int s;
652119Sbill 
65316191Skarels 	if (dzsilos == 0)
65416191Skarels 		return;
65516191Skarels 	s = spl5();
65616191Skarels 	dzfasttimers++;		/*DEBUG*/
6572645Swnj 	for (dz = 0; dz < NDZ; dz++)
65816191Skarels 		if (dzsilos & (1 << dz))
65916191Skarels 		    dzrint(dz);
6608160Sroot 	splx(s);
66116191Skarels 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
662119Sbill }
663281Sbill 
664281Sbill /*
665281Sbill  * Reset state of driver if UBA reset was necessary.
666301Sbill  * Reset parameters and restart transmission on open lines.
667281Sbill  */
dzreset(uban)6682395Swnj dzreset(uban)
6692422Skre 	int uban;
670281Sbill {
6712395Swnj 	register int unit;
672281Sbill 	register struct tty *tp;
6732976Swnj 	register struct uba_device *ui;
674281Sbill 
6752645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6762422Skre 		ui = dzinfo[unit >> 3];
6772422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6782422Skre 			continue;
6792923Swnj 		if (unit%8 == 0)
6802923Swnj 			printf(" dz%d", unit>>3);
6812395Swnj 		tp = &dz_tty[unit];
6825407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6832395Swnj 			dzparam(unit);
6846157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6855407Swnj 			tp->t_state &= ~TS_BUSY;
686301Sbill 			dzstart(tp);
687281Sbill 		}
688281Sbill 	}
689281Sbill }
6901562Sbill #endif
691