xref: /csrg-svn/sys/vax/uba/dz.c (revision 9773)
1*9773Ssam /*	dz.c	4.48	82/12/17	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 0
517Sbill /*
65731Sroot  *  DZ-11 and DZ32 Driver
72469Swnj  *
82469Swnj  * This driver mimics dh.c; see it for explanation of common code.
917Sbill  */
102731Swnj #include "bk.h"
11*9773Ssam 
12*9773Ssam #include "../machine/pte.h"
13*9773Ssam 
1417Sbill #include "../h/param.h"
1517Sbill #include "../h/systm.h"
169551Ssam #include "../h/ioctl.h"
1717Sbill #include "../h/tty.h"
1817Sbill #include "../h/dir.h"
1917Sbill #include "../h/user.h"
206157Ssam #include "../h/proc.h"
2117Sbill #include "../h/map.h"
222395Swnj #include "../h/buf.h"
232567Swnj #include "../h/vm.h"
2417Sbill #include "../h/conf.h"
25114Sbill #include "../h/bk.h"
26871Sbill #include "../h/file.h"
277727Sroot #include "../h/uio.h"
28145Sbill 
298474Sroot #include "../vaxuba/pdma.h"
308474Sroot #include "../vaxuba/ubavar.h"
318474Sroot 
322469Swnj /*
332469Swnj  * Driver information for auto-configuration stuff.
342469Swnj  */
352606Swnj int	dzprobe(), dzattach(), dzrint();
362976Swnj struct	uba_device *dzinfo[NDZ];
372395Swnj u_short	dzstd[] = { 0 };
382395Swnj struct	uba_driver dzdriver =
392606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
402395Swnj 
412645Swnj #define	NDZLINE 	(NDZ*8)
4217Sbill 
432469Swnj /*
442469Swnj  * Registers and bits
452469Swnj  */
462469Swnj 
475731Sroot /* bits in dzlpr */
485731Sroot #define	BITS7	0020
495731Sroot #define	BITS8	0030
505731Sroot #define	TWOSB	0040
512457Swnj #define	PENABLE	0100
522457Swnj #define	OPAR	0200
5317Sbill 
545731Sroot /* bits in dzrbuf */
552469Swnj #define	DZ_PE	010000
562469Swnj #define	DZ_FE	020000
572469Swnj #define	DZ_DO	040000
582469Swnj 
595731Sroot /* bits in dzcsr */
605731Sroot #define	DZ_32	000001		/* DZ32 mode */
615731Sroot #define	DZ_MIE	000002		/* Modem Interrupt Enable */
625731Sroot #define	DZ_CLR	000020		/* Reset dz */
635731Sroot #define	DZ_MSE	000040		/* Master Scan Enable */
645731Sroot #define	DZ_RIE	000100		/* Receiver Interrupt Enable */
655731Sroot #define DZ_MSC	004000		/* Modem Status Change */
662469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
672469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
685731Sroot #define	DZ_IEN	(DZ_32|DZ_MIE|DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
692469Swnj 
705731Sroot /* flags for modem-control */
715731Sroot #define	DZ_ON	DZ_DTR
722469Swnj #define	DZ_OFF	0
735731Sroot 
745731Sroot /* bits in dzlcs */
755731Sroot #define DZ_ACK	0100000		/* ACK bit in dzlcs */
765731Sroot #define DZ_RTS	0010000		/* Request To Send */
775731Sroot #define	DZ_ST	0004000		/* Secondary Transmit */
785731Sroot #define	DZ_BRK	0002000		/* Break */
795731Sroot #define DZ_DTR	0001000		/* Data Terminal Ready */
805731Sroot #define	DZ_LE	0000400		/* Line Enable */
815731Sroot #define	DZ_DSR	0000200		/* Data Set Ready */
825731Sroot #define	DZ_RI	0000100		/* Ring Indicate */
835731Sroot #define DZ_CD	0000040		/* Carrier Detect */
845731Sroot #define	DZ_CTS	0000020		/* Clear To Send */
855731Sroot #define	DZ_SR	0000010		/* Secondary Receive */
8617Sbill 
875731Sroot /* bits in dm lsr, copied from dh.c */
885731Sroot #define	DML_DSR		0000400		/* data set ready, not a real DM bit */
895731Sroot #define	DML_RNG		0000200		/* ring */
905731Sroot #define	DML_CAR		0000100		/* carrier detect */
915731Sroot #define	DML_CTS		0000040		/* clear to send */
925731Sroot #define	DML_SR		0000020		/* secondary receive */
935731Sroot #define	DML_ST		0000010		/* secondary transmit */
945731Sroot #define	DML_RTS		0000004		/* request to send */
955731Sroot #define	DML_DTR		0000002		/* data terminal ready */
965731Sroot #define	DML_LE		0000001		/* line enable */
975731Sroot 
982469Swnj int	dzstart(), dzxint(), dzdma();
99114Sbill int	ttrstrt();
1002645Swnj struct	tty dz_tty[NDZLINE];
1012645Swnj int	dz_cnt = { NDZLINE };
102119Sbill int	dzact;
10317Sbill 
10417Sbill struct device {
1055731Sroot 	short dzcsr;
1065731Sroot 	short dzrbuf;
1075731Sroot 	union {
1085731Sroot 		struct {
1095731Sroot 			char	dztcr0;
1105731Sroot 			char	dzdtr0;
1115731Sroot 			char	dztbuf0;
1125731Sroot 			char	dzbrk0;
1135731Sroot 		} dz11;
1145731Sroot 		struct {
1155731Sroot 			short	dzlcs0;
1165731Sroot 			char	dztbuf0;
1175731Sroot 			char	dzlnen0;
1185731Sroot 		} dz32;
1195731Sroot 	} dzun;
12017Sbill };
1215731Sroot 
1225731Sroot #define dzlpr	dzrbuf
1235731Sroot #define dzmsr	dzun.dz11.dzbrk0
1245731Sroot #define dztcr	dzun.dz11.dztcr0
1255731Sroot #define dzdtr	dzun.dz11.dzdtr0
1265731Sroot #define dztbuf	dzun.dz11.dztbuf0
1275731Sroot #define dzlcs	dzun.dz32.dzlcs0
1285731Sroot #define	dzbrk	dzmsr
1295731Sroot #define dzlnen	dzun.dz32.dzlnen0
1307406Skre #define dzmtsr	dzun.dz32.dztbuf0
1315731Sroot 
1325731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
1335731Sroot 
1342469Swnj /*
1352469Swnj  * Software copy of dzbrk since it isn't readable
1362469Swnj  */
1372645Swnj char	dz_brk[NDZ];
1382645Swnj char	dzsoftCAR[NDZ];
1395731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
14017Sbill 
1412469Swnj /*
1425731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
1432469Swnj  * we have to use a timer to watch it.
1442469Swnj  */
1452469Swnj char	dz_timer;		/* timer started? */
1462469Swnj 
1472469Swnj /*
1482469Swnj  * Pdma structures for fast output code
1492469Swnj  */
1502645Swnj struct	pdma dzpdma[NDZLINE];
1512469Swnj 
1522395Swnj char	dz_speeds[] =
1536814Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
15417Sbill 
1556616Ssam #ifndef PORTSELECTOR
1566616Ssam #define	ISPEED	B300
1576616Ssam #define	IFLAGS	(EVENP|ODDP|ECHO)
1586616Ssam #else
1596616Ssam #define	ISPEED	B4800
1606616Ssam #define	IFLAGS	(EVENP|ODDP)
1616616Ssam #endif
1626616Ssam 
1632606Swnj dzprobe(reg)
1642395Swnj 	caddr_t reg;
1652395Swnj {
1662457Swnj 	register int br, cvec;
1672457Swnj 	register struct device *dzaddr = (struct device *)reg;
1682395Swnj 
1692606Swnj #ifdef lint
1703102Swnj 	br = 0; cvec = br; br = cvec;
1714933Swnj 	dzrint(0); dzxint((struct tty *)0);
1722606Swnj #endif
1735731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1745731Sroot 	if (dzaddr->dzcsr & DZ_32)
1755731Sroot 		dzaddr->dzlnen = 1;
1765731Sroot 	else
1775731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1782457Swnj 	DELAY(100000);
1795731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1802457Swnj 	if (cvec && cvec != 0x200)
1812457Swnj 		cvec -= 4;
1827406Skre 	return (sizeof (struct device));
1832395Swnj }
1842395Swnj 
1852606Swnj dzattach(ui)
1862976Swnj 	register struct uba_device *ui;
1872395Swnj {
1882395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1892395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1902606Swnj 	register int cntr;
1912645Swnj 	extern dzscan();
1922395Swnj 
1932606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1942606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1952395Swnj 		pdp->p_arg = (int)tp;
1962395Swnj 		pdp->p_fcn = dzxint;
1972395Swnj 		pdp++, tp++;
1982395Swnj 	}
1992567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
2002627Swnj 	if (dz_timer == 0) {
2012627Swnj 		dz_timer++;
2022756Swnj 		timeout(dzscan, (caddr_t)0, hz);
2032627Swnj 	}
2042395Swnj }
2052395Swnj 
20617Sbill /*ARGSUSED*/
2072395Swnj dzopen(dev, flag)
2082395Swnj 	dev_t dev;
20917Sbill {
21017Sbill 	register struct tty *tp;
2112395Swnj 	register int unit;
21217Sbill 
2132395Swnj 	unit = minor(dev);
2148568Sroot 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
2158568Sroot 		return (ENXIO);
2162395Swnj 	tp = &dz_tty[unit];
2172395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
21817Sbill 	tp->t_oproc = dzstart;
2195407Swnj 	tp->t_state |= TS_WOPEN;
2205407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
22117Sbill 		ttychars(tp);
2226616Ssam 		tp->t_ospeed = tp->t_ispeed = ISPEED;
2236616Ssam 		tp->t_flags = IFLAGS;
2245407Swnj 		/* tp->t_state |= TS_HUPCLS; */
2252395Swnj 		dzparam(unit);
2268568Sroot 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
2278568Sroot 		return (EBUSY);
2286157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
229114Sbill 	(void) spl5();
2305407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
2315407Swnj 		tp->t_state |= TS_WOPEN;
23217Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
23317Sbill 	}
234114Sbill 	(void) spl0();
2358568Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
23617Sbill }
23717Sbill 
2382395Swnj /*ARGSUSED*/
2392395Swnj dzclose(dev, flag)
2402395Swnj 	dev_t dev;
24117Sbill {
24217Sbill 	register struct tty *tp;
2432395Swnj 	register int unit;
2445731Sroot 	register struct device *dzaddr;
2456150Ssam 	int dz;
24617Sbill 
2472395Swnj 	unit = minor(dev);
2482395Swnj 	dz = unit >> 3;
2492395Swnj 	tp = &dz_tty[unit];
25017Sbill 	(*linesw[tp->t_line].l_close)(tp);
2515731Sroot 	dzaddr = dzpdma[unit].p_addr;
2525731Sroot 	if (dzaddr->dzcsr&DZ_32)
2536157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
2545731Sroot 	else
2555731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
2566842Swnj 	if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
2576157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
25817Sbill 	ttyclose(tp);
25917Sbill }
26017Sbill 
2617727Sroot dzread(dev, uio)
2622395Swnj 	dev_t dev;
2637727Sroot 	struct uio *uio;
26417Sbill {
26517Sbill 	register struct tty *tp;
26617Sbill 
2672395Swnj 	tp = &dz_tty[minor(dev)];
2687727Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
26917Sbill }
27017Sbill 
2717833Sroot dzwrite(dev, uio)
2722395Swnj 	dev_t dev;
2737833Sroot 	struct uio *uio;
27417Sbill {
27517Sbill 	register struct tty *tp;
27617Sbill 
2772395Swnj 	tp = &dz_tty[minor(dev)];
2788531Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
27917Sbill }
28017Sbill 
281119Sbill /*ARGSUSED*/
2822395Swnj dzrint(dz)
2832395Swnj 	int dz;
28417Sbill {
28517Sbill 	register struct tty *tp;
28617Sbill 	register int c;
28717Sbill 	register struct device *dzaddr;
288119Sbill 	register struct tty *tp0;
2892395Swnj 	register int unit;
2902923Swnj 	int overrun = 0;
29117Sbill 
2922457Swnj 	if ((dzact & (1<<dz)) == 0)
2932457Swnj 		return;
2942457Swnj 	unit = dz * 8;
2952457Swnj 	dzaddr = dzpdma[unit].p_addr;
2962457Swnj 	tp0 = &dz_tty[unit];
2975731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2985731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2995731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
3005731Sroot 		c = dzaddr->dzmtsr;
3015731Sroot 		tp = tp0 + (c&7);
3025731Sroot 		if (tp >= &dz_tty[dz_cnt])
3035731Sroot 			break;
3045731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
3055731Sroot 		dzwait(dzaddr);		/* wait for them */
3065731Sroot 		if (c & DZ_CD)		/* carrier status change? */
3075731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
3085731Sroot 			if ((tp->t_state&TS_CARR_ON) == 0) {
3095731Sroot 				wakeup((caddr_t)&tp->t_rawq);
3105731Sroot 				tp->t_state |= TS_CARR_ON;
3115731Sroot 			}
3125731Sroot 		} else {	/* no carrier */
3135731Sroot 			if (tp->t_state&TS_CARR_ON) {
3145731Sroot 				gsignal(tp->t_pgrp, SIGHUP);
3155731Sroot 				gsignal(tp->t_pgrp, SIGCONT);
3165731Sroot 				dzaddr->dzlcs = DZ_ACK|(c&7);
3175731Sroot 				flushtty(tp, FREAD|FWRITE);
3185731Sroot 			}
3195731Sroot 			tp->t_state &= ~TS_CARR_ON;
3205731Sroot 		}
3215731Sroot 	}
3222457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
3232457Swnj 		tp = tp0 + ((c>>8)&07);
3242457Swnj 		if (tp >= &dz_tty[dz_cnt])
32517Sbill 			continue;
3265407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
3272457Swnj 			wakeup((caddr_t)&tp->t_rawq);
3286616Ssam #ifdef PORTSELECTOR
3296616Ssam 			if ((tp->t_state&TS_WOPEN) == 0)
3306616Ssam #endif
3312457Swnj 			continue;
3322457Swnj 		}
3332469Swnj 		if (c&DZ_FE)
3342457Swnj 			if (tp->t_flags & RAW)
3352469Swnj 				c = 0;
3362457Swnj 			else
3379551Ssam 				c = tp->t_intrc;
3382923Swnj 		if (c&DZ_DO && overrun == 0) {
3395731Sroot 			/* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
3402923Swnj 			overrun = 1;
3412923Swnj 		}
3422469Swnj 		if (c&DZ_PE)
3432457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
3442457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
34517Sbill 				continue;
3462731Swnj #if NBK > 0
3472457Swnj 		if (tp->t_line == NETLDISC) {
3482457Swnj 			c &= 0177;
3492457Swnj 			BKINPUT(c, tp);
3502457Swnj 		} else
3512731Swnj #endif
3522457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
35317Sbill 	}
35417Sbill }
35517Sbill 
35617Sbill /*ARGSUSED*/
3577631Ssam dzioctl(dev, cmd, data, flag)
3582395Swnj 	dev_t dev;
3597631Ssam 	caddr_t data;
36017Sbill {
36117Sbill 	register struct tty *tp;
3622395Swnj 	register int unit = minor(dev);
3632395Swnj 	register int dz = unit >> 3;
3645731Sroot 	register struct device *dzaddr;
3658568Sroot 	int error;
36617Sbill 
3672395Swnj 	tp = &dz_tty[unit];
3688568Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
3698568Sroot 	if (error >= 0)
3708568Sroot 		return (error);
3718568Sroot 	error = ttioctl(tp, cmd, data, flag);
3728568Sroot 	if (error >= 0) {
3737631Ssam 		if (cmd == TIOCSETP || cmd == TIOCSETN)
3742395Swnj 			dzparam(unit);
3758568Sroot 		return (error);
3768568Sroot 	}
3778568Sroot 	switch (cmd) {
3782395Swnj 
379170Sbill 	case TIOCSBRK:
3805731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3815731Sroot 		if (dzaddr->dzcsr&DZ_32)
3826157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3835731Sroot 		else
3845731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
385170Sbill 		break;
3867631Ssam 
387170Sbill 	case TIOCCBRK:
3885731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3895731Sroot 		if (dzaddr->dzcsr&DZ_32)
3906157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3915731Sroot 		else
3925731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
393170Sbill 		break;
3947631Ssam 
395170Sbill 	case TIOCSDTR:
3966157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
397170Sbill 		break;
3987631Ssam 
399170Sbill 	case TIOCCDTR:
4006157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
401170Sbill 		break;
4027631Ssam 
4035731Sroot 	case TIOCMSET:
4047631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
4055731Sroot 		break;
4067631Ssam 
4075731Sroot 	case TIOCMBIS:
4087631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
4095731Sroot 		break;
4107631Ssam 
4115731Sroot 	case TIOCMBIC:
4127631Ssam 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
4135731Sroot 		break;
4147631Ssam 
4155731Sroot 	case TIOCMGET:
4167631Ssam 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
4175731Sroot 		break;
4187631Ssam 
419170Sbill 	default:
4208568Sroot 		return (ENOTTY);
421170Sbill 	}
4228568Sroot 	return (0);
42317Sbill }
4245731Sroot 
4255731Sroot dmtodz(bits)
4265731Sroot 	register int bits;
4275731Sroot {
4285731Sroot 	register int b;
4295731Sroot 
4305731Sroot 	b = (bits >>1) & 0370;
4315731Sroot 	if (bits & DML_ST) b |= DZ_ST;
4325731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
4335731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
4345731Sroot 	if (bits & DML_LE) b |= DZ_LE;
4355731Sroot 	return(b);
4365731Sroot }
4375731Sroot 
4385731Sroot dztodm(bits)
4395731Sroot 	register int bits;
4405731Sroot {
4415731Sroot 	register int b;
4425731Sroot 
4435731Sroot 	b = (bits << 1) & 0360;
4445731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
4455731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
4465731Sroot 	if (bits & DZ_ST) b |= DML_ST;
4475731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
4485731Sroot 	return(b);
4495731Sroot }
45017Sbill 
4512395Swnj dzparam(unit)
4522395Swnj 	register int unit;
45317Sbill {
45417Sbill 	register struct tty *tp;
45517Sbill 	register struct device *dzaddr;
4562395Swnj 	register int lpr;
45717Sbill 
4582395Swnj 	tp = &dz_tty[unit];
4592395Swnj 	dzaddr = dzpdma[unit].p_addr;
46017Sbill 	dzaddr->dzcsr = DZ_IEN;
4612395Swnj 	dzact |= (1<<(unit>>3));
46217Sbill 	if (tp->t_ispeed == 0) {
4636157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
46417Sbill 		return;
46517Sbill 	}
4662395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
4679551Ssam 	if (tp->t_flags & (RAW|LITOUT))
46817Sbill 		lpr |= BITS8;
46917Sbill 	else
47017Sbill 		lpr |= (BITS7|PENABLE);
47117Sbill 	if ((tp->t_flags & EVENP) == 0)
47217Sbill 		lpr |= OPAR;
4732469Swnj 	if (tp->t_ispeed == B110)
4742469Swnj 		lpr |= TWOSB;
47517Sbill 	dzaddr->dzlpr = lpr;
47617Sbill }
47717Sbill 
47817Sbill dzxint(tp)
4792395Swnj 	register struct tty *tp;
48017Sbill {
48117Sbill 	register struct pdma *dp;
4825731Sroot 	register s, dz, unit;
48317Sbill 
4842469Swnj 	s = spl5();		/* block pdma interrupts */
4852395Swnj 	dp = (struct pdma *)tp->t_addr;
4865407Swnj 	tp->t_state &= ~TS_BUSY;
4875407Swnj 	if (tp->t_state & TS_FLUSH)
4885407Swnj 		tp->t_state &= ~TS_FLUSH;
4895731Sroot 	else {
490281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4915731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4925731Sroot 	}
49317Sbill 	if (tp->t_line)
49417Sbill 		(*linesw[tp->t_line].l_start)(tp);
49517Sbill 	else
49617Sbill 		dzstart(tp);
4975731Sroot 	dz = minor(tp->t_dev) >> 3;
4985731Sroot 	unit = minor(tp->t_dev) & 7;
4995407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
5005731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
5015731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
5025731Sroot 		else
5035731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
504145Sbill 	splx(s);
50517Sbill }
50617Sbill 
50717Sbill dzstart(tp)
5082395Swnj 	register struct tty *tp;
50917Sbill {
51017Sbill 	register struct pdma *dp;
51117Sbill 	register struct device *dzaddr;
5122395Swnj 	register int cc;
5135731Sroot 	int s, dz, unit;
51417Sbill 
5152395Swnj 	dp = (struct pdma *)tp->t_addr;
51617Sbill 	dzaddr = dp->p_addr;
5172395Swnj 	s = spl5();
5185407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
51917Sbill 		goto out;
5205407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
5215407Swnj 		if (tp->t_state&TS_ASLEEP) {
5225407Swnj 			tp->t_state &= ~TS_ASLEEP;
5235407Swnj 			wakeup((caddr_t)&tp->t_outq);
5245407Swnj 		}
5255407Swnj 		if (tp->t_wsel) {
5265407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
5275407Swnj 			tp->t_wsel = 0;
5285407Swnj 			tp->t_state &= ~TS_WCOLL;
5295407Swnj 		}
53017Sbill 	}
53117Sbill 	if (tp->t_outq.c_cc == 0)
53217Sbill 		goto out;
5339551Ssam 	if (tp->t_flags & (RAW|LITOUT))
53417Sbill 		cc = ndqb(&tp->t_outq, 0);
53517Sbill 	else {
53617Sbill 		cc = ndqb(&tp->t_outq, 0200);
53717Sbill 		if (cc == 0) {
53817Sbill 			cc = getc(&tp->t_outq);
5392469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5405407Swnj 			tp->t_state |= TS_TIMEOUT;
54117Sbill 			goto out;
54217Sbill 		}
54317Sbill 	}
5445407Swnj 	tp->t_state |= TS_BUSY;
54517Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
54617Sbill 	dp->p_end += cc;
5475731Sroot 	dz = minor(tp->t_dev) >> 3;
5485731Sroot 	unit = minor(tp->t_dev) & 7;
5495731Sroot 	if (dzaddr->dzcsr & DZ_32)
5505731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
5515731Sroot 	else
5525731Sroot 		dzaddr->dztcr |= (1<<unit);
5532395Swnj out:
5542395Swnj 	splx(s);
55517Sbill }
55617Sbill 
55717Sbill /*
55817Sbill  * Stop output on a line.
55917Sbill  */
56017Sbill /*ARGSUSED*/
56117Sbill dzstop(tp, flag)
5622395Swnj 	register struct tty *tp;
56317Sbill {
56417Sbill 	register struct pdma *dp;
56517Sbill 	register int s;
56617Sbill 
5672395Swnj 	dp = (struct pdma *)tp->t_addr;
5682457Swnj 	s = spl5();
5695407Swnj 	if (tp->t_state & TS_BUSY) {
57017Sbill 		dp->p_end = dp->p_mem;
5715407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5725407Swnj 			tp->t_state |= TS_FLUSH;
57317Sbill 	}
57417Sbill 	splx(s);
57517Sbill }
57617Sbill 
5775731Sroot dzmctl(dev, bits, how)
5785731Sroot 	dev_t dev;
5795731Sroot 	int bits, how;
58017Sbill {
58117Sbill 	register struct device *dzaddr;
5825731Sroot 	register int unit, mbits;
5835731Sroot 	int b, s;
5845731Sroot 
5855731Sroot 	unit = minor(dev);
5865731Sroot 	b = 1<<(unit&7);
5872395Swnj 	dzaddr = dzpdma[unit].p_addr;
5885731Sroot 	s = spl5();
5895731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5905731Sroot 		dzwait(dzaddr)
5915731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5925731Sroot 		dzaddr->dzlcs = unit&7;
5935731Sroot 		DELAY(100);
5945731Sroot 		dzwait(dzaddr)
5955731Sroot 		DELAY(100);
5965731Sroot 		mbits = dzaddr->dzlcs;
5975731Sroot 		mbits &= 0177770;
5985731Sroot 	} else {
5995731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
6005731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
6015731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
6025731Sroot 	}
6035731Sroot 	switch (how) {
6045731Sroot 	case DMSET:
6055731Sroot 		mbits = bits;
6065731Sroot 		break;
6075731Sroot 
6085731Sroot 	case DMBIS:
6095731Sroot 		mbits |= bits;
6105731Sroot 		break;
6115731Sroot 
6125731Sroot 	case DMBIC:
6135731Sroot 		mbits &= ~bits;
6145731Sroot 		break;
6155731Sroot 
6165731Sroot 	case DMGET:
6175731Sroot 		(void) splx(s);
6185731Sroot 		return(mbits);
6195731Sroot 	}
6205731Sroot 	if (dzaddr->dzcsr & DZ_32) {
6215731Sroot 		mbits |= DZ_ACK|(unit&7);
6225731Sroot 		dzaddr->dzlcs = mbits;
6235731Sroot 	} else {
6245731Sroot 		if (mbits & DZ_DTR)
6255731Sroot 			dzaddr->dzdtr |= b;
6265731Sroot 		else
6275731Sroot 			dzaddr->dzdtr &= ~b;
6285731Sroot 	}
6295731Sroot 	(void) splx(s);
6305731Sroot 	return(mbits);
63117Sbill }
63217Sbill 
63317Sbill dzscan()
63417Sbill {
63517Sbill 	register i;
63617Sbill 	register struct device *dzaddr;
63717Sbill 	register bit;
63817Sbill 	register struct tty *tp;
6395731Sroot 	register car;
64017Sbill 
64117Sbill 	for (i = 0; i < dz_cnt ; i++) {
64217Sbill 		dzaddr = dzpdma[i].p_addr;
6432627Swnj 		if (dzaddr == 0)
6442627Swnj 			continue;
64517Sbill 		tp = &dz_tty[i];
64617Sbill 		bit = 1<<(i&07);
6475731Sroot 		car = 0;
6485731Sroot 		if (dzsoftCAR[i>>3]&bit)
6495731Sroot 			car = 1;
6505731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
6515731Sroot 			dzaddr->dzlcs = i&07;
6525731Sroot 			dzwait(dzaddr);
6535731Sroot 			car = dzaddr->dzlcs & DZ_CD;
6545731Sroot 		} else
6555731Sroot 			car = dzaddr->dzmsr&bit;
6565731Sroot 		if (car) {
65717Sbill 			/* carrier present */
6585407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
65917Sbill 				wakeup((caddr_t)&tp->t_rawq);
6605407Swnj 				tp->t_state |= TS_CARR_ON;
66117Sbill 			}
66217Sbill 		} else {
6635407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
6649551Ssam 			    (tp->t_flags&NOHANG) == 0) {
66517Sbill 				/* carrier lost */
6665407Swnj 				if (tp->t_state&TS_ISOPEN) {
667170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
668205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
669170Sbill 					dzaddr->dzdtr &= ~bit;
670871Sbill 					flushtty(tp, FREAD|FWRITE);
671170Sbill 				}
6725407Swnj 				tp->t_state &= ~TS_CARR_ON;
67317Sbill 			}
67417Sbill 		}
67517Sbill 	}
6762756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
67717Sbill }
678119Sbill 
679119Sbill dztimer()
680119Sbill {
6818160Sroot 	register int dz;
6828160Sroot 	register int s = spl5();
683119Sbill 
6842645Swnj 	for (dz = 0; dz < NDZ; dz++)
6852457Swnj 		dzrint(dz);
6868160Sroot 	splx(s);
687119Sbill }
688281Sbill 
689281Sbill /*
690281Sbill  * Reset state of driver if UBA reset was necessary.
691301Sbill  * Reset parameters and restart transmission on open lines.
692281Sbill  */
6932395Swnj dzreset(uban)
6942422Skre 	int uban;
695281Sbill {
6962395Swnj 	register int unit;
697281Sbill 	register struct tty *tp;
6982976Swnj 	register struct uba_device *ui;
699281Sbill 
7002645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
7012422Skre 		ui = dzinfo[unit >> 3];
7022422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
7032422Skre 			continue;
7042923Swnj 		if (unit%8 == 0)
7052923Swnj 			printf(" dz%d", unit>>3);
7062395Swnj 		tp = &dz_tty[unit];
7075407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
7082395Swnj 			dzparam(unit);
7096157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
7105407Swnj 			tp->t_state &= ~TS_BUSY;
711301Sbill 			dzstart(tp);
712281Sbill 		}
713281Sbill 	}
714281Sbill 	dztimer();
715281Sbill }
7161562Sbill #endif
717