xref: /csrg-svn/sys/vax/uba/dz.c (revision 6157)
1*6157Ssam /*	dz.c	4.35	82/03/13	*/
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"
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"
16*6157Ssam #include "../h/proc.h"
1717Sbill #include "../h/map.h"
1817Sbill #include "../h/pte.h"
192395Swnj #include "../h/buf.h"
202567Swnj #include "../h/vm.h"
212976Swnj #include "../h/ubavar.h"
2217Sbill #include "../h/conf.h"
2317Sbill #include "../h/pdma.h"
24114Sbill #include "../h/bk.h"
25871Sbill #include "../h/file.h"
26145Sbill 
272469Swnj /*
282469Swnj  * Driver information for auto-configuration stuff.
292469Swnj  */
302606Swnj int	dzprobe(), dzattach(), dzrint();
312976Swnj struct	uba_device *dzinfo[NDZ];
322395Swnj u_short	dzstd[] = { 0 };
332395Swnj struct	uba_driver dzdriver =
342606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
352395Swnj 
362645Swnj #define	NDZLINE 	(NDZ*8)
3717Sbill 
382469Swnj /*
392469Swnj  * Registers and bits
402469Swnj  */
412469Swnj 
425731Sroot /* bits in dzlpr */
435731Sroot #define	BITS7	0020
445731Sroot #define	BITS8	0030
455731Sroot #define	TWOSB	0040
462457Swnj #define	PENABLE	0100
472457Swnj #define	OPAR	0200
4817Sbill 
495731Sroot /* bits in dzrbuf */
502469Swnj #define	DZ_PE	010000
512469Swnj #define	DZ_FE	020000
522469Swnj #define	DZ_DO	040000
532469Swnj 
545731Sroot /* bits in dzcsr */
555731Sroot #define	DZ_32	000001		/* DZ32 mode */
565731Sroot #define	DZ_MIE	000002		/* Modem Interrupt Enable */
575731Sroot #define	DZ_CLR	000020		/* Reset dz */
585731Sroot #define	DZ_MSE	000040		/* Master Scan Enable */
595731Sroot #define	DZ_RIE	000100		/* Receiver Interrupt Enable */
605731Sroot #define DZ_MSC	004000		/* Modem Status Change */
612469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
622469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
635731Sroot #define	DZ_IEN	(DZ_32|DZ_MIE|DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
642469Swnj 
655731Sroot /* flags for modem-control */
665731Sroot #define	DZ_ON	DZ_DTR
672469Swnj #define	DZ_OFF	0
685731Sroot 
695731Sroot /* bits in dzlcs */
705731Sroot #define DZ_ACK	0100000		/* ACK bit in dzlcs */
715731Sroot #define DZ_RTS	0010000		/* Request To Send */
725731Sroot #define	DZ_ST	0004000		/* Secondary Transmit */
735731Sroot #define	DZ_BRK	0002000		/* Break */
745731Sroot #define DZ_DTR	0001000		/* Data Terminal Ready */
755731Sroot #define	DZ_LE	0000400		/* Line Enable */
765731Sroot #define	DZ_DSR	0000200		/* Data Set Ready */
775731Sroot #define	DZ_RI	0000100		/* Ring Indicate */
785731Sroot #define DZ_CD	0000040		/* Carrier Detect */
795731Sroot #define	DZ_CTS	0000020		/* Clear To Send */
805731Sroot #define	DZ_SR	0000010		/* Secondary Receive */
8117Sbill 
825731Sroot /* bits in dm lsr, copied from dh.c */
835731Sroot #define	DML_DSR		0000400		/* data set ready, not a real DM bit */
845731Sroot #define	DML_RNG		0000200		/* ring */
855731Sroot #define	DML_CAR		0000100		/* carrier detect */
865731Sroot #define	DML_CTS		0000040		/* clear to send */
875731Sroot #define	DML_SR		0000020		/* secondary receive */
885731Sroot #define	DML_ST		0000010		/* secondary transmit */
895731Sroot #define	DML_RTS		0000004		/* request to send */
905731Sroot #define	DML_DTR		0000002		/* data terminal ready */
915731Sroot #define	DML_LE		0000001		/* line enable */
925731Sroot 
932469Swnj int	dzstart(), dzxint(), dzdma();
94114Sbill int	ttrstrt();
952645Swnj struct	tty dz_tty[NDZLINE];
962645Swnj int	dz_cnt = { NDZLINE };
97119Sbill int	dzact;
9817Sbill 
9917Sbill struct device {
1005731Sroot 	short dzcsr;
1015731Sroot 	short dzrbuf;
1025731Sroot 	union {
1035731Sroot 		struct {
1045731Sroot 			char	dztcr0;
1055731Sroot 			char	dzdtr0;
1065731Sroot 			char	dztbuf0;
1075731Sroot 			char	dzbrk0;
1085731Sroot 		} dz11;
1095731Sroot 		struct {
1105731Sroot 			short	dzlcs0;
1115731Sroot 			char	dztbuf0;
1125731Sroot 			char	dzlnen0;
1135731Sroot 		} dz32;
1145731Sroot 	} dzun;
11517Sbill };
1165731Sroot 
1175731Sroot #define dzlpr	dzrbuf
1185731Sroot #define dzmsr	dzun.dz11.dzbrk0
1195731Sroot #define dztcr	dzun.dz11.dztcr0
1205731Sroot #define dzdtr	dzun.dz11.dzdtr0
1215731Sroot #define dztbuf	dzun.dz11.dztbuf0
1225731Sroot #define dzlcs	dzun.dz32.dzlcs0
1235731Sroot #define	dzbrk	dzmsr
1245731Sroot #define dzlnen	dzun.dz32.dzlnen0
1255731Sroot #define dzmtsr	dzun.dz32.dztbuf0;
1265731Sroot 
1275731Sroot #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
1285731Sroot 
1292469Swnj /*
1302469Swnj  * Software copy of dzbrk since it isn't readable
1312469Swnj  */
1322645Swnj char	dz_brk[NDZ];
1332645Swnj char	dzsoftCAR[NDZ];
1345731Sroot char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
13517Sbill 
1362469Swnj /*
1375731Sroot  * The dz11 doesn't interrupt on carrier transitions, so
1382469Swnj  * we have to use a timer to watch it.
1392469Swnj  */
1402469Swnj char	dz_timer;		/* timer started? */
1412469Swnj 
1422469Swnj /*
1432469Swnj  * Pdma structures for fast output code
1442469Swnj  */
1452645Swnj struct	pdma dzpdma[NDZLINE];
1462469Swnj 
1472395Swnj char	dz_speeds[] =
1482395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
14917Sbill 
1502606Swnj dzprobe(reg)
1512395Swnj 	caddr_t reg;
1522395Swnj {
1532457Swnj 	register int br, cvec;
1542457Swnj 	register struct device *dzaddr = (struct device *)reg;
1552395Swnj 
1562606Swnj #ifdef lint
1573102Swnj 	br = 0; cvec = br; br = cvec;
1584933Swnj 	dzrint(0); dzxint((struct tty *)0);
1592606Swnj #endif
1605731Sroot 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
1615731Sroot 	if (dzaddr->dzcsr & DZ_32)
1625731Sroot 		dzaddr->dzlnen = 1;
1635731Sroot 	else
1645731Sroot 		dzaddr->dztcr = 1;		/* enable any line */
1652457Swnj 	DELAY(100000);
1665731Sroot 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
1672457Swnj 	if (cvec && cvec != 0x200)
1682457Swnj 		cvec -= 4;
1692457Swnj 	return (1);
1702395Swnj }
1712395Swnj 
1722606Swnj dzattach(ui)
1732976Swnj 	register struct uba_device *ui;
1742395Swnj {
1752395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1762395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1772606Swnj 	register int cntr;
1782645Swnj 	extern dzscan();
1792395Swnj 
1802606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1812606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1822395Swnj 		pdp->p_arg = (int)tp;
1832395Swnj 		pdp->p_fcn = dzxint;
1842395Swnj 		pdp++, tp++;
1852395Swnj 	}
1862567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1872627Swnj 	if (dz_timer == 0) {
1882627Swnj 		dz_timer++;
1892756Swnj 		timeout(dzscan, (caddr_t)0, hz);
1902627Swnj 	}
1912395Swnj }
1922395Swnj 
19317Sbill /*ARGSUSED*/
1942395Swnj dzopen(dev, flag)
1952395Swnj 	dev_t dev;
19617Sbill {
19717Sbill 	register struct tty *tp;
1982395Swnj 	register int unit;
19917Sbill 
2002395Swnj 	unit = minor(dev);
2012395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
20217Sbill 		u.u_error = ENXIO;
20317Sbill 		return;
20417Sbill 	}
2052395Swnj 	tp = &dz_tty[unit];
2062395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
20717Sbill 	tp->t_oproc = dzstart;
2085407Swnj 	tp->t_state |= TS_WOPEN;
2095407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
21017Sbill 		ttychars(tp);
2112469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
21217Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
2135407Swnj 		/* tp->t_state |= TS_HUPCLS; */
2142395Swnj 		dzparam(unit);
2155407Swnj 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {
21617Sbill 		u.u_error = EBUSY;
21717Sbill 		return;
21817Sbill 	}
219*6157Ssam 	(void) dzmctl(dev, DZ_ON, DMSET);
220114Sbill 	(void) spl5();
2215407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
2225407Swnj 		tp->t_state |= TS_WOPEN;
22317Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
22417Sbill 	}
225114Sbill 	(void) spl0();
2262395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
22717Sbill }
22817Sbill 
2292395Swnj /*ARGSUSED*/
2302395Swnj dzclose(dev, flag)
2312395Swnj 	dev_t dev;
23217Sbill {
23317Sbill 	register struct tty *tp;
2342395Swnj 	register int unit;
2355731Sroot 	register struct device *dzaddr;
2366150Ssam 	int dz;
23717Sbill 
2382395Swnj 	unit = minor(dev);
2392395Swnj 	dz = unit >> 3;
2402395Swnj 	tp = &dz_tty[unit];
24117Sbill 	(*linesw[tp->t_line].l_close)(tp);
2425731Sroot 	dzaddr = dzpdma[unit].p_addr;
2435731Sroot 	if (dzaddr->dzcsr&DZ_32)
244*6157Ssam 		(void) dzmctl(dev, DZ_BRK, DMBIC);
2455731Sroot 	else
2465731Sroot 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
2475731Sroot 	if ((tp->t_state&TS_HUPCLS) || (tp->t_state&TS_ISOPEN) == 0)
248*6157Ssam 		(void) dzmctl(dev, DZ_OFF, DMSET);
24917Sbill 	ttyclose(tp);
25017Sbill }
25117Sbill 
2522395Swnj dzread(dev)
2532395Swnj 	dev_t dev;
25417Sbill {
25517Sbill 	register struct tty *tp;
25617Sbill 
2572395Swnj 	tp = &dz_tty[minor(dev)];
25817Sbill 	(*linesw[tp->t_line].l_read)(tp);
25917Sbill }
26017Sbill 
2612395Swnj dzwrite(dev)
2622395Swnj 	dev_t dev;
26317Sbill {
26417Sbill 	register struct tty *tp;
26517Sbill 
2662395Swnj 	tp = &dz_tty[minor(dev)];
26717Sbill 	(*linesw[tp->t_line].l_write)(tp);
26817Sbill }
26917Sbill 
270119Sbill /*ARGSUSED*/
2712395Swnj dzrint(dz)
2722395Swnj 	int dz;
27317Sbill {
27417Sbill 	register struct tty *tp;
27517Sbill 	register int c;
27617Sbill 	register struct device *dzaddr;
277119Sbill 	register struct tty *tp0;
2782395Swnj 	register int unit;
2792923Swnj 	int overrun = 0;
28017Sbill 
2812457Swnj 	if ((dzact & (1<<dz)) == 0)
2822457Swnj 		return;
2832457Swnj 	unit = dz * 8;
2842457Swnj 	dzaddr = dzpdma[unit].p_addr;
2852457Swnj 	tp0 = &dz_tty[unit];
2865731Sroot 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
2875731Sroot 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
2885731Sroot 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
2895731Sroot 		c = dzaddr->dzmtsr;
2905731Sroot 		tp = tp0 + (c&7);
2915731Sroot 		if (tp >= &dz_tty[dz_cnt])
2925731Sroot 			break;
2935731Sroot 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
2945731Sroot 		dzwait(dzaddr);		/* wait for them */
2955731Sroot 		if (c & DZ_CD)		/* carrier status change? */
2965731Sroot 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
2975731Sroot 			if ((tp->t_state&TS_CARR_ON) == 0) {
2985731Sroot 				wakeup((caddr_t)&tp->t_rawq);
2995731Sroot 				tp->t_state |= TS_CARR_ON;
3005731Sroot 			}
3015731Sroot 		} else {	/* no carrier */
3025731Sroot 			if (tp->t_state&TS_CARR_ON) {
3035731Sroot 				gsignal(tp->t_pgrp, SIGHUP);
3045731Sroot 				gsignal(tp->t_pgrp, SIGCONT);
3055731Sroot 				dzaddr->dzlcs = DZ_ACK|(c&7);
3065731Sroot 				flushtty(tp, FREAD|FWRITE);
3075731Sroot 			}
3085731Sroot 			tp->t_state &= ~TS_CARR_ON;
3095731Sroot 		}
3105731Sroot 	}
3112457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
3122457Swnj 		tp = tp0 + ((c>>8)&07);
3132457Swnj 		if (tp >= &dz_tty[dz_cnt])
31417Sbill 			continue;
3155407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
3162457Swnj 			wakeup((caddr_t)&tp->t_rawq);
3172457Swnj 			continue;
3182457Swnj 		}
3192469Swnj 		if (c&DZ_FE)
3202457Swnj 			if (tp->t_flags & RAW)
3212469Swnj 				c = 0;
3222457Swnj 			else
3232457Swnj 				c = tun.t_intrc;
3242923Swnj 		if (c&DZ_DO && overrun == 0) {
3255731Sroot 			/* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
3262923Swnj 			overrun = 1;
3272923Swnj 		}
3282469Swnj 		if (c&DZ_PE)
3292457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
3302457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
33117Sbill 				continue;
3322731Swnj #if NBK > 0
3332457Swnj 		if (tp->t_line == NETLDISC) {
3342457Swnj 			c &= 0177;
3352457Swnj 			BKINPUT(c, tp);
3362457Swnj 		} else
3372731Swnj #endif
3382457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
33917Sbill 	}
34017Sbill }
34117Sbill 
34217Sbill /*ARGSUSED*/
34317Sbill dzioctl(dev, cmd, addr, flag)
3442395Swnj 	dev_t dev;
3452395Swnj 	caddr_t addr;
34617Sbill {
34717Sbill 	register struct tty *tp;
3482395Swnj 	register int unit = minor(dev);
3492395Swnj 	register int dz = unit >> 3;
3505731Sroot 	register struct device *dzaddr;
3515731Sroot 	int temp;
35217Sbill 
3532395Swnj 	tp = &dz_tty[unit];
354114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
355114Sbill 	if (cmd == 0)
356114Sbill 		return;
3571896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
35817Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
3592395Swnj 			dzparam(unit);
360170Sbill 	} else switch(cmd) {
3612395Swnj 
362170Sbill 	case TIOCSBRK:
3635731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3645731Sroot 		if (dzaddr->dzcsr&DZ_32)
365*6157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIS);
3665731Sroot 		else
3675731Sroot 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
368170Sbill 		break;
369170Sbill 	case TIOCCBRK:
3705731Sroot 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
3715731Sroot 		if (dzaddr->dzcsr&DZ_32)
372*6157Ssam 			(void) dzmctl(dev, DZ_BRK, DMBIC);
3735731Sroot 		else
3745731Sroot 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
375170Sbill 		break;
376170Sbill 	case TIOCSDTR:
377*6157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
378170Sbill 		break;
379170Sbill 	case TIOCCDTR:
380*6157Ssam 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
381170Sbill 		break;
3825731Sroot 	case TIOCMSET:
3835731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
3845731Sroot 			u.u_error = EFAULT;
3855731Sroot 		else
386*6157Ssam 			(void) dzmctl(dev, dmtodz(temp), DMSET);
3875731Sroot 		break;
3885731Sroot 	case TIOCMBIS:
3895731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
3905731Sroot 			u.u_error = EFAULT;
3915731Sroot 		else
392*6157Ssam 			(void) dzmctl(dev, dmtodz(temp), DMBIS);
3935731Sroot 		break;
3945731Sroot 	case TIOCMBIC:
3955731Sroot 		if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
3965731Sroot 			u.u_error = EFAULT;
3975731Sroot 		else
398*6157Ssam 			(void) dzmctl(dev, dmtodz(temp), DMBIC);
3995731Sroot 		break;
4005731Sroot 	case TIOCMGET:
4015731Sroot 		temp = dztodm(dzmctl(dev, 0, DMGET));
4025731Sroot 		if (copyout((caddr_t) &temp, addr, sizeof(temp)))
4035731Sroot 			u.u_error = EFAULT;
4045731Sroot 		break;
405170Sbill 	default:
40617Sbill 		u.u_error = ENOTTY;
407170Sbill 	}
40817Sbill }
4095731Sroot 
4105731Sroot dmtodz(bits)
4115731Sroot 	register int bits;
4125731Sroot {
4135731Sroot 	register int b;
4145731Sroot 
4155731Sroot 	b = (bits >>1) & 0370;
4165731Sroot 	if (bits & DML_ST) b |= DZ_ST;
4175731Sroot 	if (bits & DML_RTS) b |= DZ_RTS;
4185731Sroot 	if (bits & DML_DTR) b |= DZ_DTR;
4195731Sroot 	if (bits & DML_LE) b |= DZ_LE;
4205731Sroot 	return(b);
4215731Sroot }
4225731Sroot 
4235731Sroot dztodm(bits)
4245731Sroot 	register int bits;
4255731Sroot {
4265731Sroot 	register int b;
4275731Sroot 
4285731Sroot 	b = (bits << 1) & 0360;
4295731Sroot 	if (bits & DZ_DSR) b |= DML_DSR;
4305731Sroot 	if (bits & DZ_DTR) b |= DML_DTR;
4315731Sroot 	if (bits & DZ_ST) b |= DML_ST;
4325731Sroot 	if (bits & DZ_RTS) b |= DML_RTS;
4335731Sroot 	return(b);
4345731Sroot }
43517Sbill 
4362395Swnj dzparam(unit)
4372395Swnj 	register int unit;
43817Sbill {
43917Sbill 	register struct tty *tp;
44017Sbill 	register struct device *dzaddr;
4412395Swnj 	register int lpr;
44217Sbill 
4432395Swnj 	tp = &dz_tty[unit];
4442395Swnj 	dzaddr = dzpdma[unit].p_addr;
44517Sbill 	dzaddr->dzcsr = DZ_IEN;
4462395Swnj 	dzact |= (1<<(unit>>3));
44717Sbill 	if (tp->t_ispeed == 0) {
448*6157Ssam 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
44917Sbill 		return;
45017Sbill 	}
4512395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
4522296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
45317Sbill 		lpr |= BITS8;
45417Sbill 	else
45517Sbill 		lpr |= (BITS7|PENABLE);
45617Sbill 	if ((tp->t_flags & EVENP) == 0)
45717Sbill 		lpr |= OPAR;
4582469Swnj 	if (tp->t_ispeed == B110)
4592469Swnj 		lpr |= TWOSB;
46017Sbill 	dzaddr->dzlpr = lpr;
46117Sbill }
46217Sbill 
46317Sbill dzxint(tp)
4642395Swnj 	register struct tty *tp;
46517Sbill {
46617Sbill 	register struct pdma *dp;
4675731Sroot 	register s, dz, unit;
46817Sbill 
4692469Swnj 	s = spl5();		/* block pdma interrupts */
4702395Swnj 	dp = (struct pdma *)tp->t_addr;
4715407Swnj 	tp->t_state &= ~TS_BUSY;
4725407Swnj 	if (tp->t_state & TS_FLUSH)
4735407Swnj 		tp->t_state &= ~TS_FLUSH;
4745731Sroot 	else {
475281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
4765731Sroot 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
4775731Sroot 	}
47817Sbill 	if (tp->t_line)
47917Sbill 		(*linesw[tp->t_line].l_start)(tp);
48017Sbill 	else
48117Sbill 		dzstart(tp);
4825731Sroot 	dz = minor(tp->t_dev) >> 3;
4835731Sroot 	unit = minor(tp->t_dev) & 7;
4845407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
4855731Sroot 		if (dp->p_addr->dzcsr & DZ_32)
4865731Sroot 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
4875731Sroot 		else
4885731Sroot 			dp->p_addr->dztcr &= ~(1<<unit);
489145Sbill 	splx(s);
49017Sbill }
49117Sbill 
49217Sbill dzstart(tp)
4932395Swnj 	register struct tty *tp;
49417Sbill {
49517Sbill 	register struct pdma *dp;
49617Sbill 	register struct device *dzaddr;
4972395Swnj 	register int cc;
4985731Sroot 	int s, dz, unit;
49917Sbill 
5002395Swnj 	dp = (struct pdma *)tp->t_addr;
50117Sbill 	dzaddr = dp->p_addr;
5022395Swnj 	s = spl5();
5035407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
50417Sbill 		goto out;
5055407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
5065407Swnj 		if (tp->t_state&TS_ASLEEP) {
5075407Swnj 			tp->t_state &= ~TS_ASLEEP;
5085407Swnj 			wakeup((caddr_t)&tp->t_outq);
5095407Swnj 		}
5105407Swnj 		if (tp->t_wsel) {
5115407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
5125407Swnj 			tp->t_wsel = 0;
5135407Swnj 			tp->t_state &= ~TS_WCOLL;
5145407Swnj 		}
51517Sbill 	}
51617Sbill 	if (tp->t_outq.c_cc == 0)
51717Sbill 		goto out;
5185731Sroot 	if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
51917Sbill 		cc = ndqb(&tp->t_outq, 0);
52017Sbill 	else {
52117Sbill 		cc = ndqb(&tp->t_outq, 0200);
52217Sbill 		if (cc == 0) {
52317Sbill 			cc = getc(&tp->t_outq);
5242469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5255407Swnj 			tp->t_state |= TS_TIMEOUT;
52617Sbill 			goto out;
52717Sbill 		}
52817Sbill 	}
5295407Swnj 	tp->t_state |= TS_BUSY;
53017Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
53117Sbill 	dp->p_end += cc;
5325731Sroot 	dz = minor(tp->t_dev) >> 3;
5335731Sroot 	unit = minor(tp->t_dev) & 7;
5345731Sroot 	if (dzaddr->dzcsr & DZ_32)
5355731Sroot 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
5365731Sroot 	else
5375731Sroot 		dzaddr->dztcr |= (1<<unit);
5382395Swnj out:
5392395Swnj 	splx(s);
54017Sbill }
54117Sbill 
54217Sbill /*
54317Sbill  * Stop output on a line.
54417Sbill  */
54517Sbill /*ARGSUSED*/
54617Sbill dzstop(tp, flag)
5472395Swnj 	register struct tty *tp;
54817Sbill {
54917Sbill 	register struct pdma *dp;
55017Sbill 	register int s;
55117Sbill 
5522395Swnj 	dp = (struct pdma *)tp->t_addr;
5532457Swnj 	s = spl5();
5545407Swnj 	if (tp->t_state & TS_BUSY) {
55517Sbill 		dp->p_end = dp->p_mem;
5565407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
5575407Swnj 			tp->t_state |= TS_FLUSH;
55817Sbill 	}
55917Sbill 	splx(s);
56017Sbill }
56117Sbill 
5625731Sroot dzmctl(dev, bits, how)
5635731Sroot 	dev_t dev;
5645731Sroot 	int bits, how;
56517Sbill {
56617Sbill 	register struct device *dzaddr;
5675731Sroot 	register int unit, mbits;
5685731Sroot 	int b, s;
5695731Sroot 
5705731Sroot 	unit = minor(dev);
5715731Sroot 	b = 1<<(unit&7);
5722395Swnj 	dzaddr = dzpdma[unit].p_addr;
5735731Sroot 	s = spl5();
5745731Sroot 	if (dzaddr->dzcsr & DZ_32) {
5755731Sroot 		dzwait(dzaddr)
5765731Sroot 		DELAY(100);		/* IS 100 TOO MUCH? */
5775731Sroot 		dzaddr->dzlcs = unit&7;
5785731Sroot 		DELAY(100);
5795731Sroot 		dzwait(dzaddr)
5805731Sroot 		DELAY(100);
5815731Sroot 		mbits = dzaddr->dzlcs;
5825731Sroot 		mbits &= 0177770;
5835731Sroot 	} else {
5845731Sroot 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
5855731Sroot 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
5865731Sroot 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
5875731Sroot 	}
5885731Sroot 	switch (how) {
5895731Sroot 	case DMSET:
5905731Sroot 		mbits = bits;
5915731Sroot 		break;
5925731Sroot 
5935731Sroot 	case DMBIS:
5945731Sroot 		mbits |= bits;
5955731Sroot 		break;
5965731Sroot 
5975731Sroot 	case DMBIC:
5985731Sroot 		mbits &= ~bits;
5995731Sroot 		break;
6005731Sroot 
6015731Sroot 	case DMGET:
6025731Sroot 		(void) splx(s);
6035731Sroot 		return(mbits);
6045731Sroot 	}
6055731Sroot 	if (dzaddr->dzcsr & DZ_32) {
6065731Sroot 		mbits |= DZ_ACK|(unit&7);
6075731Sroot 		dzaddr->dzlcs = mbits;
6085731Sroot 	} else {
6095731Sroot 		if (mbits & DZ_DTR)
6105731Sroot 			dzaddr->dzdtr |= b;
6115731Sroot 		else
6125731Sroot 			dzaddr->dzdtr &= ~b;
6135731Sroot 	}
6145731Sroot 	(void) splx(s);
6155731Sroot 	return(mbits);
61617Sbill }
61717Sbill 
61817Sbill dzscan()
61917Sbill {
62017Sbill 	register i;
62117Sbill 	register struct device *dzaddr;
62217Sbill 	register bit;
62317Sbill 	register struct tty *tp;
6245731Sroot 	register car;
62517Sbill 
62617Sbill 	for (i = 0; i < dz_cnt ; i++) {
62717Sbill 		dzaddr = dzpdma[i].p_addr;
6282627Swnj 		if (dzaddr == 0)
6292627Swnj 			continue;
63017Sbill 		tp = &dz_tty[i];
63117Sbill 		bit = 1<<(i&07);
6325731Sroot 		car = 0;
6335731Sroot 		if (dzsoftCAR[i>>3]&bit)
6345731Sroot 			car = 1;
6355731Sroot 		else if (dzaddr->dzcsr & DZ_32) {
6365731Sroot 			dzaddr->dzlcs = i&07;
6375731Sroot 			dzwait(dzaddr);
6385731Sroot 			car = dzaddr->dzlcs & DZ_CD;
6395731Sroot 		} else
6405731Sroot 			car = dzaddr->dzmsr&bit;
6415731Sroot 		if (car) {
64217Sbill 			/* carrier present */
6435407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
64417Sbill 				wakeup((caddr_t)&tp->t_rawq);
6455407Swnj 				tp->t_state |= TS_CARR_ON;
64617Sbill 			}
64717Sbill 		} else {
6485407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
6492469Swnj 			    (tp->t_local&LNOHANG)==0) {
65017Sbill 				/* carrier lost */
6515407Swnj 				if (tp->t_state&TS_ISOPEN) {
652170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
653205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
654170Sbill 					dzaddr->dzdtr &= ~bit;
655871Sbill 					flushtty(tp, FREAD|FWRITE);
656170Sbill 				}
6575407Swnj 				tp->t_state &= ~TS_CARR_ON;
65817Sbill 			}
65917Sbill 		}
66017Sbill 	}
6612756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
66217Sbill }
663119Sbill 
664119Sbill dztimer()
665119Sbill {
6662457Swnj 	int dz;
667119Sbill 
6682645Swnj 	for (dz = 0; dz < NDZ; dz++)
6692457Swnj 		dzrint(dz);
670119Sbill }
671281Sbill 
672281Sbill /*
673281Sbill  * Reset state of driver if UBA reset was necessary.
674301Sbill  * Reset parameters and restart transmission on open lines.
675281Sbill  */
6762395Swnj dzreset(uban)
6772422Skre 	int uban;
678281Sbill {
6792395Swnj 	register int unit;
680281Sbill 	register struct tty *tp;
6812976Swnj 	register struct uba_device *ui;
682281Sbill 
6832645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
6842422Skre 		ui = dzinfo[unit >> 3];
6852422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
6862422Skre 			continue;
6872923Swnj 		if (unit%8 == 0)
6882923Swnj 			printf(" dz%d", unit>>3);
6892395Swnj 		tp = &dz_tty[unit];
6905407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
6912395Swnj 			dzparam(unit);
692*6157Ssam 			(void) dzmctl(unit, DZ_ON, DMSET);
6935407Swnj 			tp->t_state &= ~TS_BUSY;
694301Sbill 			dzstart(tp);
695281Sbill 		}
696281Sbill 	}
697281Sbill 	dztimer();
698281Sbill }
6991562Sbill #endif
700