xref: /csrg-svn/sys/vax/uba/dz.c (revision 2469)
1*2469Swnj /*	dz.c	4.13	02/17/81	*/
217Sbill 
31935Swnj #include "dz.h"
41562Sbill #if NDZ11 > 0
52457Swnj #define	DELAY(i)	{ register int j = i; while (--j > 0); }
617Sbill /*
717Sbill  *  DZ-11 Driver
8*2469Swnj  *
9*2469Swnj  * This driver mimics dh.c; see it for explanation of common code.
1017Sbill  */
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"
1917Sbill #include "../h/uba.h"
2017Sbill #include "../h/conf.h"
2117Sbill #include "../h/pdma.h"
22114Sbill #include "../h/bk.h"
23871Sbill #include "../h/file.h"
241786Sbill #include "../h/mx.h"
25145Sbill 
26*2469Swnj /*
27*2469Swnj  * Driver information for auto-configuration stuff.
28*2469Swnj  */
292395Swnj int	dzcntrlr(), dzslave(), dzrint();
302395Swnj struct	uba_dinfo *dzinfo[NDZ11];
312395Swnj u_short	dzstd[] = { 0 };
322395Swnj struct	uba_driver dzdriver =
332457Swnj 	{ dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo };
342395Swnj 
352457Swnj #define	NDZ 	(NDZ11*8)
3617Sbill 
37*2469Swnj /*
38*2469Swnj  * Registers and bits
39*2469Swnj  */
40*2469Swnj 
41*2469Swnj /* Bits in dzlpr */
422457Swnj #define	BITS7	020
432457Swnj #define	BITS8	030
442457Swnj #define	TWOSB	040
452457Swnj #define	PENABLE	0100
462457Swnj #define	OPAR	0200
4717Sbill 
48*2469Swnj /* Bits in dzrbuf */
49*2469Swnj #define	DZ_PE	010000
50*2469Swnj #define	DZ_FE	020000
51*2469Swnj #define	DZ_DO	040000
52*2469Swnj 
53*2469Swnj /* Bits in dzcsr */
54*2469Swnj #define	DZ_CLR	020		/* Reset dz */
55*2469Swnj #define	DZ_MSE	040		/* Master Scan Enable */
56*2469Swnj #define	DZ_RIE	0100		/* Receiver Interrupt Enable */
57*2469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
58*2469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
59*2469Swnj #define	DZ_IEN	(DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE)
60*2469Swnj 
61*2469Swnj /* Flags for modem-control */
62*2469Swnj #define	DZ_ON	1
63*2469Swnj #define	DZ_OFF	0
6417Sbill 
65*2469Swnj int	dzstart(), dzxint(), dzdma();
66114Sbill int	ttrstrt();
6717Sbill struct	tty dz_tty[NDZ];
6817Sbill int	dz_cnt = { NDZ };
69119Sbill int	dzact;
7017Sbill 
7117Sbill struct device {
72*2469Swnj 	short	dzcsr;		/* control-status register */
73*2469Swnj 	short	dzrbuf;		/* receiver buffer */
74*2469Swnj #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
75*2469Swnj 	char	dztcr;		/* transmit control register */
76*2469Swnj 	char	dzdtr;		/* data terminal ready */
77*2469Swnj 	char	dztbuf;		/* transmit buffer */
78*2469Swnj 	char	dzbrk;		/* break control */
79*2469Swnj #define	dzmsr	dzbrk		/* modem status register */
8017Sbill };
81*2469Swnj /*
82*2469Swnj  * Software copy of dzbrk since it isn't readable
83*2469Swnj  */
84*2469Swnj char	dz_brk[NDZ11];
8517Sbill 
86*2469Swnj /*
87*2469Swnj  * The dz doesn't interrupt on carrier transitions, so
88*2469Swnj  * we have to use a timer to watch it.
89*2469Swnj  */
90*2469Swnj char	dz_timer;		/* timer started? */
91*2469Swnj 
92*2469Swnj /*
93*2469Swnj  * Pdma structures for fast output code
94*2469Swnj  */
952395Swnj struct	pdma dzpdma[NDZ];
96*2469Swnj 
972395Swnj char	dz_speeds[] =
982395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
9917Sbill 
1002395Swnj dzcntrlr(ui, reg)
1012395Swnj 	struct uba_dinfo *ui;
1022395Swnj 	caddr_t reg;
1032395Swnj {
1042457Swnj 	register int br, cvec;
1052457Swnj 	register struct device *dzaddr = (struct device *)reg;
1062395Swnj 
107*2469Swnj 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
1082422Skre 	dzaddr->dztcr = 1;		/* enable any line */
1092457Swnj 	DELAY(100000);
110*2469Swnj 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
1112457Swnj 	if (cvec && cvec != 0x200)
1122457Swnj 		cvec -= 4;
1132457Swnj 	return (1);
1142395Swnj }
1152395Swnj 
116*2469Swnj /*
117*2469Swnj  * Called by auto-configure to initialize good dz's;
118*2469Swnj  * set up pdma structures.
119*2469Swnj  */
1202395Swnj dzslave(ui, reg, slaveno, uban)
1212395Swnj 	register struct uba_dinfo *ui;
1222395Swnj 	caddr_t reg;
1232395Swnj {
1242395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1252395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1262395Swnj 	register int cnt;
1272395Swnj 
1282395Swnj 	for (cnt = 0; cnt < 8; cnt++) {
1292395Swnj 		pdp->p_addr = (struct device *)reg;
1302395Swnj 		pdp->p_arg = (int)tp;
1312395Swnj 		pdp->p_fcn = dzxint;
1322395Swnj 		pdp++, tp++;
1332395Swnj 	}
1342395Swnj 	return (1);
1352395Swnj }
1362395Swnj 
13717Sbill /*ARGSUSED*/
1382395Swnj dzopen(dev, flag)
1392395Swnj 	dev_t dev;
14017Sbill {
14117Sbill 	register struct tty *tp;
1422395Swnj 	register int unit;
14317Sbill 	extern dzscan();
14417Sbill 
1452395Swnj 	unit = minor(dev);
1462395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
14717Sbill 		u.u_error = ENXIO;
14817Sbill 		return;
14917Sbill 	}
15017Sbill 	if (dz_timer == 0) {
15117Sbill 		dz_timer++;
152*2469Swnj 		timeout(dzscan, (caddr_t)0, HZ);
15317Sbill 	}
1542395Swnj 	tp = &dz_tty[unit];
1552395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
15617Sbill 	tp->t_oproc = dzstart;
15717Sbill 	tp->t_iproc = NULL;
15817Sbill 	tp->t_state |= WOPEN;
15917Sbill 	if ((tp->t_state & ISOPEN) == 0) {
16017Sbill 		ttychars(tp);
161*2469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
16217Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
163*2469Swnj 		/* tp->t_state |= HUPCLS; */
1642395Swnj 		dzparam(unit);
16517Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
16617Sbill 		u.u_error = EBUSY;
16717Sbill 		return;
16817Sbill 	}
169*2469Swnj 	dzmodem(unit, DZ_ON);
170114Sbill 	(void) spl5();
17117Sbill 	while ((tp->t_state & CARR_ON) == 0) {
17217Sbill 		tp->t_state |= WOPEN;
17317Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17417Sbill 	}
175114Sbill 	(void) spl0();
1762395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
17717Sbill }
17817Sbill 
1792395Swnj /*ARGSUSED*/
1802395Swnj dzclose(dev, flag)
1812395Swnj 	dev_t dev;
18217Sbill {
18317Sbill 	register struct tty *tp;
1842395Swnj 	register int unit;
1852395Swnj 	int dz;
18617Sbill 
1872395Swnj 	unit = minor(dev);
1882395Swnj 	dz = unit >> 3;
1892395Swnj 	tp = &dz_tty[unit];
19017Sbill 	(*linesw[tp->t_line].l_close)(tp);
1912197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1922395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
19317Sbill 	if (tp->t_state & HUPCLS)
194*2469Swnj 		dzmodem(unit, DZ_OFF);
19517Sbill 	ttyclose(tp);
19617Sbill }
19717Sbill 
1982395Swnj dzread(dev)
1992395Swnj 	dev_t dev;
20017Sbill {
20117Sbill 	register struct tty *tp;
20217Sbill 
2032395Swnj 	tp = &dz_tty[minor(dev)];
20417Sbill 	(*linesw[tp->t_line].l_read)(tp);
20517Sbill }
20617Sbill 
2072395Swnj dzwrite(dev)
2082395Swnj 	dev_t dev;
20917Sbill {
21017Sbill 	register struct tty *tp;
21117Sbill 
2122395Swnj 	tp = &dz_tty[minor(dev)];
21317Sbill 	(*linesw[tp->t_line].l_write)(tp);
21417Sbill }
21517Sbill 
216119Sbill /*ARGSUSED*/
2172395Swnj dzrint(dz)
2182395Swnj 	int dz;
21917Sbill {
22017Sbill 	register struct tty *tp;
22117Sbill 	register int c;
22217Sbill 	register struct device *dzaddr;
223119Sbill 	register struct tty *tp0;
2242395Swnj 	register int unit;
225140Sbill 	int s;
22617Sbill 
2272457Swnj 	if ((dzact & (1<<dz)) == 0)
2282457Swnj 		return;
2292457Swnj 	unit = dz * 8;
2302457Swnj 	dzaddr = dzpdma[unit].p_addr;
2312457Swnj 	tp0 = &dz_tty[unit];
2322457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
2332457Swnj 		tp = tp0 + ((c>>8)&07);
2342457Swnj 		if (tp >= &dz_tty[dz_cnt])
23517Sbill 			continue;
2362457Swnj 		if ((tp->t_state & ISOPEN) == 0) {
2372457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2382457Swnj 			continue;
2392457Swnj 		}
240*2469Swnj 		if (c&DZ_FE)
2412457Swnj 			if (tp->t_flags & RAW)
242*2469Swnj 				c = 0;
2432457Swnj 			else
2442457Swnj 				c = tun.t_intrc;
245*2469Swnj 		if (c&DZ_DO)
2462457Swnj 			printf("o");
247*2469Swnj 		if (c&DZ_PE)
2482457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2492457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
25017Sbill 				continue;
2512457Swnj 		if (tp->t_line == NETLDISC) {
2522457Swnj 			c &= 0177;
2532457Swnj 			BKINPUT(c, tp);
2542457Swnj 		} else
2552457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
25617Sbill 	}
25717Sbill }
25817Sbill 
25917Sbill /*ARGSUSED*/
26017Sbill dzioctl(dev, cmd, addr, flag)
2612395Swnj 	dev_t dev;
2622395Swnj 	caddr_t addr;
26317Sbill {
26417Sbill 	register struct tty *tp;
2652395Swnj 	register int unit = minor(dev);
2662395Swnj 	register int dz = unit >> 3;
26717Sbill 
2682395Swnj 	tp = &dz_tty[unit];
269114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
270114Sbill 	if (cmd == 0)
271114Sbill 		return;
2721896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
27317Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2742395Swnj 			dzparam(unit);
275170Sbill 	} else switch(cmd) {
2762395Swnj 
277170Sbill 	case TIOCSBRK:
278882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2792395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
280170Sbill 		break;
281170Sbill 	case TIOCCBRK:
282882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2832395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
284170Sbill 		break;
285170Sbill 	case TIOCSDTR:
286*2469Swnj 		dzmodem(unit, DZ_ON);
287170Sbill 		break;
288170Sbill 	case TIOCCDTR:
289*2469Swnj 		dzmodem(unit, DZ_OFF);
290170Sbill 		break;
291170Sbill 	default:
29217Sbill 		u.u_error = ENOTTY;
293170Sbill 	}
29417Sbill }
29517Sbill 
2962395Swnj dzparam(unit)
2972395Swnj 	register int unit;
29817Sbill {
29917Sbill 	register struct tty *tp;
30017Sbill 	register struct device *dzaddr;
3012395Swnj 	register int lpr;
30217Sbill 
3032395Swnj 	tp = &dz_tty[unit];
3042395Swnj 	dzaddr = dzpdma[unit].p_addr;
30517Sbill 	dzaddr->dzcsr = DZ_IEN;
3062395Swnj 	dzact |= (1<<(unit>>3));
30717Sbill 	if (tp->t_ispeed == 0) {
308*2469Swnj 		dzmodem(unit, DZ_OFF);		/* hang up line */
30917Sbill 		return;
31017Sbill 	}
3112395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3122296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
31317Sbill 		lpr |= BITS8;
31417Sbill 	else
31517Sbill 		lpr |= (BITS7|PENABLE);
31617Sbill 	if ((tp->t_flags & EVENP) == 0)
31717Sbill 		lpr |= OPAR;
318*2469Swnj 	if (tp->t_ispeed == B110)
319*2469Swnj 		lpr |= TWOSB;
32017Sbill 	dzaddr->dzlpr = lpr;
32117Sbill }
32217Sbill 
32317Sbill dzxint(tp)
3242395Swnj 	register struct tty *tp;
32517Sbill {
32617Sbill 	register struct pdma *dp;
327145Sbill 	register s;
32817Sbill 
329*2469Swnj 	s = spl5();		/* block pdma interrupts */
3302395Swnj 	dp = (struct pdma *)tp->t_addr;
33117Sbill 	tp->t_state &= ~BUSY;
33217Sbill 	if (tp->t_state & FLUSH)
33317Sbill 		tp->t_state &= ~FLUSH;
33417Sbill 	else
335281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
33617Sbill 	if (tp->t_line)
33717Sbill 		(*linesw[tp->t_line].l_start)(tp);
33817Sbill 	else
33917Sbill 		dzstart(tp);
34017Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3412395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
342145Sbill 	splx(s);
34317Sbill }
34417Sbill 
34517Sbill dzstart(tp)
3462395Swnj 	register struct tty *tp;
34717Sbill {
34817Sbill 	register struct pdma *dp;
34917Sbill 	register struct device *dzaddr;
3502395Swnj 	register int cc;
3512395Swnj 	int s;
35217Sbill 
3532395Swnj 	dp = (struct pdma *)tp->t_addr;
35417Sbill 	dzaddr = dp->p_addr;
3552395Swnj 	s = spl5();
35617Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
35717Sbill 		goto out;
358921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
35917Sbill 		tp->t_state &= ~ASLEEP;
36017Sbill 		if (tp->t_chan)
36117Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
36217Sbill 		else
36317Sbill 			wakeup((caddr_t)&tp->t_outq);
36417Sbill 	}
36517Sbill 	if (tp->t_outq.c_cc == 0)
36617Sbill 		goto out;
36717Sbill 	if (tp->t_flags&RAW)
36817Sbill 		cc = ndqb(&tp->t_outq, 0);
36917Sbill 	else {
37017Sbill 		cc = ndqb(&tp->t_outq, 0200);
37117Sbill 		if (cc == 0) {
37217Sbill 			cc = getc(&tp->t_outq);
373*2469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
37417Sbill 			tp->t_state |= TIMEOUT;
37517Sbill 			goto out;
37617Sbill 		}
37717Sbill 	}
37817Sbill 	tp->t_state |= BUSY;
37917Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
38017Sbill 	dp->p_end += cc;
381*2469Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
3822395Swnj out:
3832395Swnj 	splx(s);
38417Sbill }
38517Sbill 
38617Sbill /*
38717Sbill  * Stop output on a line.
38817Sbill  */
38917Sbill /*ARGSUSED*/
39017Sbill dzstop(tp, flag)
3912395Swnj 	register struct tty *tp;
39217Sbill {
39317Sbill 	register struct pdma *dp;
39417Sbill 	register int s;
39517Sbill 
3962395Swnj 	dp = (struct pdma *)tp->t_addr;
3972457Swnj 	s = spl5();
39817Sbill 	if (tp->t_state & BUSY) {
39917Sbill 		dp->p_end = dp->p_mem;
4002395Swnj 		if ((tp->t_state&TTSTOP)==0)
40117Sbill 			tp->t_state |= FLUSH;
40217Sbill 	}
40317Sbill 	splx(s);
40417Sbill }
40517Sbill 
4062395Swnj dzmodem(unit, flag)
4072395Swnj 	register int unit;
40817Sbill {
40917Sbill 	register struct device *dzaddr;
41017Sbill 	register char bit;
41117Sbill 
4122395Swnj 	dzaddr = dzpdma[unit].p_addr;
4132395Swnj 	bit = 1<<(unit&07);
414*2469Swnj 	if (flag == DZ_OFF)
41517Sbill 		dzaddr->dzdtr &= ~bit;
41617Sbill 	else
41717Sbill 		dzaddr->dzdtr |= bit;
41817Sbill }
41917Sbill 
42017Sbill dzscan()
42117Sbill {
42217Sbill 	register i;
42317Sbill 	register struct device *dzaddr;
42417Sbill 	register bit;
42517Sbill 	register struct tty *tp;
42617Sbill 
42717Sbill 	for (i = 0; i < dz_cnt ; i++) {
42817Sbill 		dzaddr = dzpdma[i].p_addr;
42917Sbill 		tp = &dz_tty[i];
43017Sbill 		bit = 1<<(i&07);
4312422Skre #ifdef BERT
4322422Skre 		if (dzaddr->dzmsr & bit || i == 6 || i == 7) {
4332422Skre #else
4342422Skre 		if (dzaddr->dzmsr & bit) {
4352422Skre #endif
43617Sbill 			/* carrier present */
43717Sbill 			if ((tp->t_state & CARR_ON) == 0) {
43817Sbill 				wakeup((caddr_t)&tp->t_rawq);
43917Sbill 				tp->t_state |= CARR_ON;
44017Sbill 			}
44117Sbill 		} else {
442*2469Swnj 			if ((tp->t_state&CARR_ON) &&
443*2469Swnj 			    (tp->t_local&LNOHANG)==0) {
44417Sbill 				/* carrier lost */
445882Sbill 				if (tp->t_state&ISOPEN) {
446170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
447205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
448170Sbill 					dzaddr->dzdtr &= ~bit;
449871Sbill 					flushtty(tp, FREAD|FWRITE);
450170Sbill 				}
451170Sbill 				tp->t_state &= ~CARR_ON;
45217Sbill 			}
45317Sbill 		}
45417Sbill 	}
45517Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
45617Sbill }
457119Sbill 
458119Sbill dztimer()
459119Sbill {
4602457Swnj 	int dz;
461119Sbill 
4622457Swnj 	for (dz = 0; dz < NDZ11; dz++)
4632457Swnj 		dzrint(dz);
464119Sbill }
465281Sbill 
466281Sbill /*
467281Sbill  * Reset state of driver if UBA reset was necessary.
468301Sbill  * Reset parameters and restart transmission on open lines.
469281Sbill  */
4702395Swnj dzreset(uban)
4712422Skre 	int uban;
472281Sbill {
4732395Swnj 	register int unit;
474281Sbill 	register struct tty *tp;
4752422Skre 	register struct uba_dinfo *ui;
4762422Skre 	int any = 0;
477281Sbill 
4782395Swnj 	for (unit = 0; unit < NDZ; unit++) {
4792422Skre 		ui = dzinfo[unit >> 3];
4802422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4812422Skre 			continue;
4822422Skre 		if (any == 0) {
4832422Skre 			printf(" dz");
4842422Skre 			any++;
4852422Skre 		}
4862395Swnj 		tp = &dz_tty[unit];
487281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4882395Swnj 			dzparam(unit);
489*2469Swnj 			dzmodem(unit, DZ_ON);
490301Sbill 			tp->t_state &= ~BUSY;
491301Sbill 			dzstart(tp);
492281Sbill 		}
493281Sbill 	}
494281Sbill 	dztimer();
495281Sbill }
4961562Sbill #endif
497