xref: /csrg-svn/sys/vax/uba/dz.c (revision 5731)
1*5731Sroot /*	dz.c	4.33	82/02/08	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 0
517Sbill /*
6*5731Sroot  *  DZ-11 and DZ32 Driver
72469Swnj  *
82469Swnj  * This driver mimics dh.c; see it for explanation of common code.
917Sbill  */
102731Swnj #include "bk.h"
1117Sbill #include "../h/param.h"
1217Sbill #include "../h/systm.h"
1317Sbill #include "../h/tty.h"
1417Sbill #include "../h/dir.h"
1517Sbill #include "../h/user.h"
1617Sbill #include "../h/map.h"
1717Sbill #include "../h/pte.h"
182395Swnj #include "../h/buf.h"
192567Swnj #include "../h/vm.h"
202976Swnj #include "../h/ubavar.h"
2117Sbill #include "../h/conf.h"
2217Sbill #include "../h/pdma.h"
23114Sbill #include "../h/bk.h"
24871Sbill #include "../h/file.h"
25145Sbill 
262469Swnj /*
272469Swnj  * Driver information for auto-configuration stuff.
282469Swnj  */
292606Swnj int	dzprobe(), dzattach(), dzrint();
302976Swnj struct	uba_device *dzinfo[NDZ];
312395Swnj u_short	dzstd[] = { 0 };
322395Swnj struct	uba_driver dzdriver =
332606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
342395Swnj 
352645Swnj #define	NDZLINE 	(NDZ*8)
3617Sbill 
372469Swnj /*
382469Swnj  * Registers and bits
392469Swnj  */
402469Swnj 
41*5731Sroot /* bits in dzlpr */
42*5731Sroot #define	BITS7	0020
43*5731Sroot #define	BITS8	0030
44*5731Sroot #define	TWOSB	0040
452457Swnj #define	PENABLE	0100
462457Swnj #define	OPAR	0200
4717Sbill 
48*5731Sroot /* bits in dzrbuf */
492469Swnj #define	DZ_PE	010000
502469Swnj #define	DZ_FE	020000
512469Swnj #define	DZ_DO	040000
522469Swnj 
53*5731Sroot /* bits in dzcsr */
54*5731Sroot #define	DZ_32	000001		/* DZ32 mode */
55*5731Sroot #define	DZ_MIE	000002		/* Modem Interrupt Enable */
56*5731Sroot #define	DZ_CLR	000020		/* Reset dz */
57*5731Sroot #define	DZ_MSE	000040		/* Master Scan Enable */
58*5731Sroot #define	DZ_RIE	000100		/* Receiver Interrupt Enable */
59*5731Sroot #define DZ_MSC	004000		/* Modem Status Change */
602469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
612469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
62*5731Sroot #define	DZ_IEN	(DZ_32|DZ_MIE|DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
632469Swnj 
64*5731Sroot /* flags for modem-control */
65*5731Sroot #define	DZ_ON	DZ_DTR
662469Swnj #define	DZ_OFF	0
67*5731Sroot 
68*5731Sroot /* bits in dzlcs */
69*5731Sroot #define DZ_ACK	0100000		/* ACK bit in dzlcs */
70*5731Sroot #define DZ_RTS	0010000		/* Request To Send */
71*5731Sroot #define	DZ_ST	0004000		/* Secondary Transmit */
72*5731Sroot #define	DZ_BRK	0002000		/* Break */
73*5731Sroot #define DZ_DTR	0001000		/* Data Terminal Ready */
74*5731Sroot #define	DZ_LE	0000400		/* Line Enable */
75*5731Sroot #define	DZ_DSR	0000200		/* Data Set Ready */
76*5731Sroot #define	DZ_RI	0000100		/* Ring Indicate */
77*5731Sroot #define DZ_CD	0000040		/* Carrier Detect */
78*5731Sroot #define	DZ_CTS	0000020		/* Clear To Send */
79*5731Sroot #define	DZ_SR	0000010		/* Secondary Receive */
8017Sbill 
81*5731Sroot /* bits in dm lsr, copied from dh.c */
82*5731Sroot #define	DML_DSR		0000400		/* data set ready, not a real DM bit */
83*5731Sroot #define	DML_RNG		0000200		/* ring */
84*5731Sroot #define	DML_CAR		0000100		/* carrier detect */
85*5731Sroot #define	DML_CTS		0000040		/* clear to send */
86*5731Sroot #define	DML_SR		0000020		/* secondary receive */
87*5731Sroot #define	DML_ST		0000010		/* secondary transmit */
88*5731Sroot #define	DML_RTS		0000004		/* request to send */
89*5731Sroot #define	DML_DTR		0000002		/* data terminal ready */
90*5731Sroot #define	DML_LE		0000001		/* line enable */
91*5731Sroot 
922469Swnj int	dzstart(), dzxint(), dzdma();
93114Sbill int	ttrstrt();
942645Swnj struct	tty dz_tty[NDZLINE];
952645Swnj int	dz_cnt = { NDZLINE };
96119Sbill int	dzact;
9717Sbill 
9817Sbill struct device {
99*5731Sroot 	short dzcsr;
100*5731Sroot 	short dzrbuf;
101*5731Sroot 	union {
102*5731Sroot 		struct {
103*5731Sroot 			char	dztcr0;
104*5731Sroot 			char	dzdtr0;
105*5731Sroot 			char	dztbuf0;
106*5731Sroot 			char	dzbrk0;
107*5731Sroot 		} dz11;
108*5731Sroot 		struct {
109*5731Sroot 			short	dzlcs0;
110*5731Sroot 			char	dztbuf0;
111*5731Sroot 			char	dzlnen0;
112*5731Sroot 		} dz32;
113*5731Sroot 	} dzun;
11417Sbill };
115*5731Sroot 
116*5731Sroot #define dzlpr	dzrbuf
117*5731Sroot #define dzmsr	dzun.dz11.dzbrk0
118*5731Sroot #define dztcr	dzun.dz11.dztcr0
119*5731Sroot #define dzdtr	dzun.dz11.dzdtr0
120*5731Sroot #define dztbuf	dzun.dz11.dztbuf0
121*5731Sroot #define dzlcs	dzun.dz32.dzlcs0
122*5731Sroot #define	dzbrk	dzmsr
123*5731Sroot #define dzlnen	dzun.dz32.dzlnen0
124*5731Sroot #define dzmtsr	dzun.dz32.dztbuf0;
125*5731Sroot 
126*5731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
127*5731Sroot 
1282469Swnj /*
1292469Swnj  * Software copy of dzbrk since it isn't readable
1302469Swnj  */
1312645Swnj char	dz_brk[NDZ];
1322645Swnj char	dzsoftCAR[NDZ];
133*5731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
13417Sbill 
1352469Swnj /*
136*5731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
1372469Swnj  * we have to use a timer to watch it.
1382469Swnj  */
1392469Swnj char	dz_timer;		/* timer started? */
1402469Swnj 
1412469Swnj /*
1422469Swnj  * Pdma structures for fast output code
1432469Swnj  */
1442645Swnj struct	pdma dzpdma[NDZLINE];
1452469Swnj 
1462395Swnj char	dz_speeds[] =
1472395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
14817Sbill 
1492606Swnj dzprobe(reg)
1502395Swnj 	caddr_t reg;
1512395Swnj {
1522457Swnj 	register int br, cvec;
1532457Swnj 	register struct device *dzaddr = (struct device *)reg;
1542395Swnj 
1552606Swnj #ifdef lint
1563102Swnj 	br = 0; cvec = br; br = cvec;
1574933Swnj 	dzrint(0); dzxint((struct tty *)0);
1582606Swnj #endif
159*5731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
160*5731Sroot 	if (dzaddr->dzcsr & DZ_32)
161*5731Sroot 		dzaddr->dzlnen = 1;
162*5731Sroot 	else
163*5731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1642457Swnj 	DELAY(100000);
165*5731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1662457Swnj 	if (cvec && cvec != 0x200)
1672457Swnj 		cvec -= 4;
1682457Swnj 	return (1);
1692395Swnj }
1702395Swnj 
1712606Swnj dzattach(ui)
1722976Swnj 	register struct uba_device *ui;
1732395Swnj {
1742395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1752395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1762606Swnj 	register int cntr;
1772645Swnj 	extern dzscan();
1782395Swnj 
1792606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1802606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1812395Swnj 		pdp->p_arg = (int)tp;
1822395Swnj 		pdp->p_fcn = dzxint;
1832395Swnj 		pdp++, tp++;
1842395Swnj 	}
1852567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1862627Swnj 	if (dz_timer == 0) {
1872627Swnj 		dz_timer++;
1882756Swnj 		timeout(dzscan, (caddr_t)0, hz);
1892627Swnj 	}
1902395Swnj }
1912395Swnj 
19217Sbill /*ARGSUSED*/
1932395Swnj dzopen(dev, flag)
1942395Swnj 	dev_t dev;
19517Sbill {
19617Sbill 	register struct tty *tp;
1972395Swnj 	register int unit;
19817Sbill 
1992395Swnj 	unit = minor(dev);
2002395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
20117Sbill 		u.u_error = ENXIO;
20217Sbill 		return;
20317Sbill 	}
2042395Swnj 	tp = &dz_tty[unit];
2052395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
20617Sbill 	tp->t_oproc = dzstart;
2075407Swnj 	tp->t_state |= TS_WOPEN;
2085407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
20917Sbill 		ttychars(tp);
2102469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
21117Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
2125407Swnj 		/* tp->t_state |= TS_HUPCLS; */
2132395Swnj 		dzparam(unit);
2145407Swnj 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {
21517Sbill 		u.u_error = EBUSY;
21617Sbill 		return;
21717Sbill 	}
218*5731Sroot 	dzmctl(dev, DZ_ON, DMSET);
219114Sbill 	(void) spl5();
2205407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
2215407Swnj 		tp->t_state |= TS_WOPEN;
22217Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
22317Sbill 	}
224114Sbill 	(void) spl0();
2252395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
22617Sbill }
22717Sbill 
2282395Swnj /*ARGSUSED*/
2292395Swnj dzclose(dev, flag)
2302395Swnj 	dev_t dev;
23117Sbill {
23217Sbill 	register struct tty *tp;
2332395Swnj 	register int unit;
234*5731Sroot 	register struct device *dzaddr;
235*5731Sroot 	int dz, s;
23617Sbill 
2372395Swnj 	unit = minor(dev);
2382395Swnj 	dz = unit >> 3;
2392395Swnj 	tp = &dz_tty[unit];
24017Sbill 	(*linesw[tp->t_line].l_close)(tp);
241*5731Sroot 	dzaddr = dzpdma[unit].p_addr;
242*5731Sroot 	if (dzaddr->dzcsr&DZ_32)
243*5731Sroot 		dzmctl(dev, DZ_BRK, DMBIC);
244*5731Sroot 	else
245*5731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
246*5731Sroot 	if ((tp->t_state&TS_HUPCLS) || (tp->t_state&TS_ISOPEN) == 0)
247*5731Sroot 		dzmctl(dev, DZ_OFF, DMSET);
24817Sbill 	ttyclose(tp);
24917Sbill }
25017Sbill 
2512395Swnj dzread(dev)
2522395Swnj 	dev_t dev;
25317Sbill {
25417Sbill 	register struct tty *tp;
25517Sbill 
2562395Swnj 	tp = &dz_tty[minor(dev)];
25717Sbill 	(*linesw[tp->t_line].l_read)(tp);
25817Sbill }
25917Sbill 
2602395Swnj dzwrite(dev)
2612395Swnj 	dev_t dev;
26217Sbill {
26317Sbill 	register struct tty *tp;
26417Sbill 
2652395Swnj 	tp = &dz_tty[minor(dev)];
26617Sbill 	(*linesw[tp->t_line].l_write)(tp);
26717Sbill }
26817Sbill 
269119Sbill /*ARGSUSED*/
2702395Swnj dzrint(dz)
2712395Swnj 	int dz;
27217Sbill {
27317Sbill 	register struct tty *tp;
27417Sbill 	register int c;
27517Sbill 	register struct device *dzaddr;
276119Sbill 	register struct tty *tp0;
2772395Swnj 	register int unit;
2782923Swnj 	int overrun = 0;
27917Sbill 
2802457Swnj 	if ((dzact & (1<<dz)) == 0)
2812457Swnj 		return;
2822457Swnj 	unit = dz * 8;
2832457Swnj 	dzaddr = dzpdma[unit].p_addr;
2842457Swnj 	tp0 = &dz_tty[unit];
285*5731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
286*5731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
287*5731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
288*5731Sroot 		c = dzaddr->dzmtsr;
289*5731Sroot 		tp = tp0 + (c&7);
290*5731Sroot 		if (tp >= &dz_tty[dz_cnt])
291*5731Sroot 			break;
292*5731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
293*5731Sroot 		dzwait(dzaddr);		/* wait for them */
294*5731Sroot 		if (c & DZ_CD)		/* carrier status change? */
295*5731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
296*5731Sroot 			if ((tp->t_state&TS_CARR_ON) == 0) {
297*5731Sroot 				wakeup((caddr_t)&tp->t_rawq);
298*5731Sroot 				tp->t_state |= TS_CARR_ON;
299*5731Sroot 			}
300*5731Sroot 		} else {	/* no carrier */
301*5731Sroot 			if (tp->t_state&TS_CARR_ON) {
302*5731Sroot 				gsignal(tp->t_pgrp, SIGHUP);
303*5731Sroot 				gsignal(tp->t_pgrp, SIGCONT);
304*5731Sroot 				dzaddr->dzlcs = DZ_ACK|(c&7);
305*5731Sroot 				flushtty(tp, FREAD|FWRITE);
306*5731Sroot 			}
307*5731Sroot 			tp->t_state &= ~TS_CARR_ON;
308*5731Sroot 		}
309*5731Sroot 	}
3102457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
3112457Swnj 		tp = tp0 + ((c>>8)&07);
3122457Swnj 		if (tp >= &dz_tty[dz_cnt])
31317Sbill 			continue;
3145407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
3152457Swnj 			wakeup((caddr_t)&tp->t_rawq);
3162457Swnj 			continue;
3172457Swnj 		}
3182469Swnj 		if (c&DZ_FE)
3192457Swnj 			if (tp->t_flags & RAW)
3202469Swnj 				c = 0;
3212457Swnj 			else
3222457Swnj 				c = tun.t_intrc;
3232923Swnj 		if (c&DZ_DO && overrun == 0) {
324*5731Sroot 			/* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
3252923Swnj 			overrun = 1;
3262923Swnj 		}
3272469Swnj 		if (c&DZ_PE)
3282457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
3292457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
33017Sbill 				continue;
3312731Swnj #if NBK > 0
3322457Swnj 		if (tp->t_line == NETLDISC) {
3332457Swnj 			c &= 0177;
3342457Swnj 			BKINPUT(c, tp);
3352457Swnj 		} else
3362731Swnj #endif
3372457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
33817Sbill 	}
33917Sbill }
34017Sbill 
34117Sbill /*ARGSUSED*/
34217Sbill dzioctl(dev, cmd, addr, flag)
3432395Swnj 	dev_t dev;
3442395Swnj 	caddr_t addr;
34517Sbill {
34617Sbill 	register struct tty *tp;
3472395Swnj 	register int unit = minor(dev);
3482395Swnj 	register int dz = unit >> 3;
349*5731Sroot 	register struct device *dzaddr;
350*5731Sroot 	int temp;
35117Sbill 
3522395Swnj 	tp = &dz_tty[unit];
353114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
354114Sbill 	if (cmd == 0)
355114Sbill 		return;
3561896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
35717Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
3582395Swnj 			dzparam(unit);
359170Sbill 	} else switch(cmd) {
3602395Swnj 
361170Sbill 	case TIOCSBRK:
362*5731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
363*5731Sroot 		if (dzaddr->dzcsr&DZ_32)
364*5731Sroot 			dzmctl(dev, DZ_BRK, DMBIS);
365*5731Sroot 		else
366*5731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
367170Sbill 		break;
368170Sbill 	case TIOCCBRK:
369*5731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
370*5731Sroot 		if (dzaddr->dzcsr&DZ_32)
371*5731Sroot 			dzmctl(dev, DZ_BRK, DMBIC);
372*5731Sroot 		else
373*5731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
374170Sbill 		break;
375170Sbill 	case TIOCSDTR:
376*5731Sroot 		dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
377170Sbill 		break;
378170Sbill 	case TIOCCDTR:
379*5731Sroot 		dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
380170Sbill 		break;
381*5731Sroot 	case TIOCMSET:
382*5731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
383*5731Sroot 			u.u_error = EFAULT;
384*5731Sroot 		else
385*5731Sroot 			dzmctl(dev, dmtodz(temp), DMSET);
386*5731Sroot 		break;
387*5731Sroot 	case TIOCMBIS:
388*5731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
389*5731Sroot 			u.u_error = EFAULT;
390*5731Sroot 		else
391*5731Sroot 			dzmctl(dev, dmtodz(temp), DMBIS);
392*5731Sroot 		break;
393*5731Sroot 	case TIOCMBIC:
394*5731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
395*5731Sroot 			u.u_error = EFAULT;
396*5731Sroot 		else
397*5731Sroot 			dzmctl(dev, dmtodz(temp), DMBIC);
398*5731Sroot 		break;
399*5731Sroot 	case TIOCMGET:
400*5731Sroot 		temp = dztodm(dzmctl(dev, 0, DMGET));
401*5731Sroot 		if (copyout((caddr_t) &temp, addr, sizeof(temp)))
402*5731Sroot 			u.u_error = EFAULT;
403*5731Sroot 		break;
404170Sbill 	default:
40517Sbill 		u.u_error = ENOTTY;
406170Sbill 	}
40717Sbill }
408*5731Sroot 
409*5731Sroot dmtodz(bits)
410*5731Sroot 	register int bits;
411*5731Sroot {
412*5731Sroot 	register int b;
413*5731Sroot 
414*5731Sroot 	b = (bits >>1) & 0370;
415*5731Sroot 	if (bits & DML_ST) b |= DZ_ST;
416*5731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
417*5731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
418*5731Sroot 	if (bits & DML_LE) b |= DZ_LE;
419*5731Sroot 	return(b);
420*5731Sroot }
421*5731Sroot 
422*5731Sroot dztodm(bits)
423*5731Sroot 	register int bits;
424*5731Sroot {
425*5731Sroot 	register int b;
426*5731Sroot 
427*5731Sroot 	b = (bits << 1) & 0360;
428*5731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
429*5731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
430*5731Sroot 	if (bits & DZ_ST) b |= DML_ST;
431*5731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
432*5731Sroot 	return(b);
433*5731Sroot }
43417Sbill 
4352395Swnj dzparam(unit)
4362395Swnj 	register int unit;
43717Sbill {
43817Sbill 	register struct tty *tp;
43917Sbill 	register struct device *dzaddr;
4402395Swnj 	register int lpr;
44117Sbill 
4422395Swnj 	tp = &dz_tty[unit];
4432395Swnj 	dzaddr = dzpdma[unit].p_addr;
44417Sbill 	dzaddr->dzcsr = DZ_IEN;
4452395Swnj 	dzact |= (1<<(unit>>3));
44617Sbill 	if (tp->t_ispeed == 0) {
447*5731Sroot 		dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
44817Sbill 		return;
44917Sbill 	}
4502395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
4512296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
45217Sbill 		lpr |= BITS8;
45317Sbill 	else
45417Sbill 		lpr |= (BITS7|PENABLE);
45517Sbill 	if ((tp->t_flags & EVENP) == 0)
45617Sbill 		lpr |= OPAR;
4572469Swnj 	if (tp->t_ispeed == B110)
4582469Swnj 		lpr |= TWOSB;
45917Sbill 	dzaddr->dzlpr = lpr;
46017Sbill }
46117Sbill 
46217Sbill dzxint(tp)
4632395Swnj 	register struct tty *tp;
46417Sbill {
46517Sbill 	register struct pdma *dp;
466*5731Sroot 	register s, dz, unit;
46717Sbill 
4682469Swnj 	s = spl5();		/* block pdma interrupts */
4692395Swnj 	dp = (struct pdma *)tp->t_addr;
4705407Swnj 	tp->t_state &= ~TS_BUSY;
4715407Swnj 	if (tp->t_state & TS_FLUSH)
4725407Swnj 		tp->t_state &= ~TS_FLUSH;
473*5731Sroot 	else {
474281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
475*5731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
476*5731Sroot 	}
47717Sbill 	if (tp->t_line)
47817Sbill 		(*linesw[tp->t_line].l_start)(tp);
47917Sbill 	else
48017Sbill 		dzstart(tp);
481*5731Sroot 	dz = minor(tp->t_dev) >> 3;
482*5731Sroot 	unit = minor(tp->t_dev) & 7;
4835407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
484*5731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
485*5731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
486*5731Sroot 		else
487*5731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
488145Sbill 	splx(s);
48917Sbill }
49017Sbill 
49117Sbill dzstart(tp)
4922395Swnj 	register struct tty *tp;
49317Sbill {
49417Sbill 	register struct pdma *dp;
49517Sbill 	register struct device *dzaddr;
4962395Swnj 	register int cc;
497*5731Sroot 	int s, dz, unit;
49817Sbill 
4992395Swnj 	dp = (struct pdma *)tp->t_addr;
50017Sbill 	dzaddr = dp->p_addr;
5012395Swnj 	s = spl5();
5025407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
50317Sbill 		goto out;
5045407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
5055407Swnj 		if (tp->t_state&TS_ASLEEP) {
5065407Swnj 			tp->t_state &= ~TS_ASLEEP;
5075407Swnj 			wakeup((caddr_t)&tp->t_outq);
5085407Swnj 		}
5095407Swnj 		if (tp->t_wsel) {
5105407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
5115407Swnj 			tp->t_wsel = 0;
5125407Swnj 			tp->t_state &= ~TS_WCOLL;
5135407Swnj 		}
51417Sbill 	}
51517Sbill 	if (tp->t_outq.c_cc == 0)
51617Sbill 		goto out;
517*5731Sroot 	if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
51817Sbill 		cc = ndqb(&tp->t_outq, 0);
51917Sbill 	else {
52017Sbill 		cc = ndqb(&tp->t_outq, 0200);
52117Sbill 		if (cc == 0) {
52217Sbill 			cc = getc(&tp->t_outq);
5232469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5245407Swnj 			tp->t_state |= TS_TIMEOUT;
52517Sbill 			goto out;
52617Sbill 		}
52717Sbill 	}
5285407Swnj 	tp->t_state |= TS_BUSY;
52917Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
53017Sbill 	dp->p_end += cc;
531*5731Sroot 	dz = minor(tp->t_dev) >> 3;
532*5731Sroot 	unit = minor(tp->t_dev) & 7;
533*5731Sroot 	if (dzaddr->dzcsr & DZ_32)
534*5731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
535*5731Sroot 	else
536*5731Sroot 		dzaddr->dztcr |= (1<<unit);
5372395Swnj out:
5382395Swnj 	splx(s);
53917Sbill }
54017Sbill 
54117Sbill /*
54217Sbill  * Stop output on a line.
54317Sbill  */
54417Sbill /*ARGSUSED*/
54517Sbill dzstop(tp, flag)
5462395Swnj 	register struct tty *tp;
54717Sbill {
54817Sbill 	register struct pdma *dp;
54917Sbill 	register int s;
55017Sbill 
5512395Swnj 	dp = (struct pdma *)tp->t_addr;
5522457Swnj 	s = spl5();
5535407Swnj 	if (tp->t_state & TS_BUSY) {
55417Sbill 		dp->p_end = dp->p_mem;
5555407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5565407Swnj 			tp->t_state |= TS_FLUSH;
55717Sbill 	}
55817Sbill 	splx(s);
55917Sbill }
56017Sbill 
561*5731Sroot dzmctl(dev, bits, how)
562*5731Sroot 	dev_t dev;
563*5731Sroot 	int bits, how;
56417Sbill {
56517Sbill 	register struct device *dzaddr;
566*5731Sroot 	register int unit, mbits;
567*5731Sroot 	int b, s;
568*5731Sroot 
569*5731Sroot 	unit = minor(dev);
570*5731Sroot 	b = 1<<(unit&7);
5712395Swnj 	dzaddr = dzpdma[unit].p_addr;
572*5731Sroot 	s = spl5();
573*5731Sroot 	if (dzaddr->dzcsr & DZ_32) {
574*5731Sroot 		dzwait(dzaddr)
575*5731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
576*5731Sroot 		dzaddr->dzlcs = unit&7;
577*5731Sroot 		DELAY(100);
578*5731Sroot 		dzwait(dzaddr)
579*5731Sroot 		DELAY(100);
580*5731Sroot 		mbits = dzaddr->dzlcs;
581*5731Sroot 		mbits &= 0177770;
582*5731Sroot 	} else {
583*5731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
584*5731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
585*5731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
586*5731Sroot 	}
587*5731Sroot 	switch (how) {
588*5731Sroot 	case DMSET:
589*5731Sroot 		mbits = bits;
590*5731Sroot 		break;
591*5731Sroot 
592*5731Sroot 	case DMBIS:
593*5731Sroot 		mbits |= bits;
594*5731Sroot 		break;
595*5731Sroot 
596*5731Sroot 	case DMBIC:
597*5731Sroot 		mbits &= ~bits;
598*5731Sroot 		break;
599*5731Sroot 
600*5731Sroot 	case DMGET:
601*5731Sroot 		(void) splx(s);
602*5731Sroot 		return(mbits);
603*5731Sroot 	}
604*5731Sroot 	if (dzaddr->dzcsr & DZ_32) {
605*5731Sroot 		mbits |= DZ_ACK|(unit&7);
606*5731Sroot 		dzaddr->dzlcs = mbits;
607*5731Sroot 	} else {
608*5731Sroot 		if (mbits & DZ_DTR)
609*5731Sroot 			dzaddr->dzdtr |= b;
610*5731Sroot 		else
611*5731Sroot 			dzaddr->dzdtr &= ~b;
612*5731Sroot 	}
613*5731Sroot 	(void) splx(s);
614*5731Sroot 	return(mbits);
61517Sbill }
61617Sbill 
61717Sbill dzscan()
61817Sbill {
61917Sbill 	register i;
62017Sbill 	register struct device *dzaddr;
62117Sbill 	register bit;
62217Sbill 	register struct tty *tp;
623*5731Sroot 	register car;
62417Sbill 
62517Sbill 	for (i = 0; i < dz_cnt ; i++) {
62617Sbill 		dzaddr = dzpdma[i].p_addr;
6272627Swnj 		if (dzaddr == 0)
6282627Swnj 			continue;
62917Sbill 		tp = &dz_tty[i];
63017Sbill 		bit = 1<<(i&07);
631*5731Sroot 		car = 0;
632*5731Sroot 		if (dzsoftCAR[i>>3]&bit)
633*5731Sroot 			car = 1;
634*5731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
635*5731Sroot 			dzaddr->dzlcs = i&07;
636*5731Sroot 			dzwait(dzaddr);
637*5731Sroot 			car = dzaddr->dzlcs & DZ_CD;
638*5731Sroot 		} else
639*5731Sroot 			car = dzaddr->dzmsr&bit;
640*5731Sroot 		if (car) {
64117Sbill 			/* carrier present */
6425407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
64317Sbill 				wakeup((caddr_t)&tp->t_rawq);
6445407Swnj 				tp->t_state |= TS_CARR_ON;
64517Sbill 			}
64617Sbill 		} else {
6475407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
6482469Swnj 			    (tp->t_local&LNOHANG)==0) {
64917Sbill 				/* carrier lost */
6505407Swnj 				if (tp->t_state&TS_ISOPEN) {
651170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
652205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
653170Sbill 					dzaddr->dzdtr &= ~bit;
654871Sbill 					flushtty(tp, FREAD|FWRITE);
655170Sbill 				}
6565407Swnj 				tp->t_state &= ~TS_CARR_ON;
65717Sbill 			}
65817Sbill 		}
65917Sbill 	}
6602756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
66117Sbill }
662119Sbill 
663119Sbill dztimer()
664119Sbill {
6652457Swnj 	int dz;
666119Sbill 
6672645Swnj 	for (dz = 0; dz < NDZ; dz++)
6682457Swnj 		dzrint(dz);
669119Sbill }
670281Sbill 
671281Sbill /*
672281Sbill  * Reset state of driver if UBA reset was necessary.
673301Sbill  * Reset parameters and restart transmission on open lines.
674281Sbill  */
6752395Swnj dzreset(uban)
6762422Skre 	int uban;
677281Sbill {
6782395Swnj 	register int unit;
679281Sbill 	register struct tty *tp;
6802976Swnj 	register struct uba_device *ui;
681281Sbill 
6822645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6832422Skre 		ui = dzinfo[unit >> 3];
6842422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6852422Skre 			continue;
6862923Swnj 		if (unit%8 == 0)
6872923Swnj 			printf(" dz%d", unit>>3);
6882395Swnj 		tp = &dz_tty[unit];
6895407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6902395Swnj 			dzparam(unit);
691*5731Sroot 			dzmctl(unit, DZ_ON, DMSET);
6925407Swnj 			tp->t_state &= ~TS_BUSY;
693301Sbill 			dzstart(tp);
694281Sbill 		}
695281Sbill 	}
696281Sbill 	dztimer();
697281Sbill }
6981562Sbill #endif
699