xref: /csrg-svn/sys/vax/uba/dz.c (revision 2422)
1*2422Skre /*	dz.c	4.11	02/15/81	*/
217Sbill 
31935Swnj #include "dz.h"
41562Sbill #if NDZ11 > 0
517Sbill /*
617Sbill  *  DZ-11 Driver
717Sbill  */
817Sbill #include "../h/param.h"
917Sbill #include "../h/systm.h"
1017Sbill #include "../h/tty.h"
1117Sbill #include "../h/dir.h"
1217Sbill #include "../h/user.h"
1317Sbill #include "../h/map.h"
1417Sbill #include "../h/pte.h"
152395Swnj #include "../h/buf.h"
1617Sbill #include "../h/uba.h"
1717Sbill #include "../h/conf.h"
1817Sbill #include "../h/pdma.h"
19114Sbill #include "../h/bk.h"
20871Sbill #include "../h/file.h"
211786Sbill #include "../h/mx.h"
22145Sbill 
23145Sbill /*
24145Sbill  * When running dz's using only SAE (silo alarm) on input
25145Sbill  * it is necessary to call dzrint() at clock interrupt time.
26145Sbill  * This is unsafe unless spl5()s in tty code are changed to
27145Sbill  * spl6()s to block clock interrupts.  Note that the dh driver
28145Sbill  * currently in use works the same way as the dz, even though
29145Sbill  * we could try to more intelligently manage its silo.
30145Sbill  * Thus don't take this out if you have no dz's unless you
31145Sbill  * change clock.c and dhtimer().
322395Swnj  *
332395Swnj  * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME.
34145Sbill  */
35145Sbill #define	spl5	spl6
3617Sbill 
372395Swnj int	dzcntrlr(), dzslave(), dzrint();
382395Swnj struct	uba_dinfo *dzinfo[NDZ11];
392395Swnj u_short	dzstd[] = { 0 };
402395Swnj struct	uba_driver dzdriver =
41*2422Skre 	{ dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, "dz", dzinfo };
422395Swnj 
43882Sbill #define NDZ 	(NDZ11*8)
4417Sbill 
4517Sbill #define BITS7	020
4617Sbill #define BITS8	030
4717Sbill #define TWOSB	040
4817Sbill #define PENABLE	0100
4917Sbill #define OPAR	0200
50*2422Skre #define	CLR	020		/* Reset dz */
5117Sbill #define MSE	040		/* Master Scan Enable */
5217Sbill #define RIE	0100		/* Receiver Interrupt Enable */
53119Sbill #define	SAE	010000		/* Silo Alarm Enable */
54119Sbill #define TIE	040000		/* Transmit Interrupt Enable */
55119Sbill #define DZ_IEN	(MSE+RIE+TIE+SAE)
5617Sbill #define PERROR	010000
5717Sbill #define FRERROR	020000
58119Sbill #define	OVERRUN	040000
5917Sbill #define SSPEED	7		/* std speed = 300 baud */
6017Sbill 
6117Sbill #define	dzlpr	dzrbuf
6217Sbill #define dzmsr	dzbrk
6317Sbill #define ON	1
6417Sbill #define OFF	0
6517Sbill 
6617Sbill int	dzstart();
6717Sbill int	dzxint();
682395Swnj int	dzdma();
69114Sbill int	ttrstrt();
7017Sbill struct	tty dz_tty[NDZ];
7117Sbill int	dz_cnt = { NDZ };
72119Sbill int	dzact;
7317Sbill 
7417Sbill struct device {
7517Sbill 	short	dzcsr;
7617Sbill 	short	dzrbuf;
7717Sbill 	char	dztcr;
7817Sbill 	char	dzdtr;
7917Sbill 	char	dztbuf;
8017Sbill 	char	dzbrk;
8117Sbill };
8217Sbill 
832395Swnj struct	pdma dzpdma[NDZ];
8417Sbill char	dz_timer;
852395Swnj char	dz_speeds[] =
862395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
872395Swnj char	dz_brk[NDZ11];
8817Sbill 
892395Swnj dzcntrlr(ui, reg)
902395Swnj 	struct uba_dinfo *ui;
912395Swnj 	caddr_t reg;
922395Swnj {
93*2422Skre 	int	i;		/* NB: NOT REGISTER */
94*2422Skre 	struct	device *dzaddr = (struct device *)reg;
952395Swnj 
96*2422Skre 	dzaddr->dzcsr = TIE|MSE;
97*2422Skre 	dzaddr->dztcr = 1;		/* enable any line */
98*2422Skre 	for (i = 0; i < 1000000; i++)
99*2422Skre 		;
100*2422Skre 	dzaddr->dzcsr = CLR;		/* reset everything */
101*2422Skre 	asm("cmpl r10,$0x200;beql 1f;subl2 $4,r10;1:;");
102*2422Skre 	return(1);
1032395Swnj }
1042395Swnj 
1052395Swnj dzslave(ui, reg, slaveno, uban)
1062395Swnj 	register struct uba_dinfo *ui;
1072395Swnj 	caddr_t reg;
1082395Swnj {
1092395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1102395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1112395Swnj 	register int cnt;
1122395Swnj 	caddr_t cp;
1132395Swnj 
1142395Swnj 	for (cnt = 0; cnt < 8; cnt++) {
1152395Swnj 		pdp->p_addr = (struct device *)reg;
1162395Swnj 		pdp->p_arg = (int)tp;
1172395Swnj 		pdp->p_fcn = dzxint;
1182395Swnj 		pdp++, tp++;
1192395Swnj 	}
1202395Swnj 	return (1);
1212395Swnj }
1222395Swnj 
12317Sbill /*ARGSUSED*/
1242395Swnj dzopen(dev, flag)
1252395Swnj 	dev_t dev;
12617Sbill {
12717Sbill 	register struct tty *tp;
1282395Swnj 	register int unit;
12917Sbill 	extern dzscan();
13017Sbill 
1312395Swnj 	unit = minor(dev);
1322395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
13317Sbill 		u.u_error = ENXIO;
13417Sbill 		return;
13517Sbill 	}
13617Sbill 	if (dz_timer == 0) {
13717Sbill 		dz_timer++;
13817Sbill 		timeout(dzscan, (caddr_t)0, 60);
13917Sbill 	}
1402395Swnj 	tp = &dz_tty[unit];
1412395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
14217Sbill 	tp->t_oproc = dzstart;
14317Sbill 	tp->t_iproc = NULL;
14417Sbill 	tp->t_state |= WOPEN;
14517Sbill 	if ((tp->t_state & ISOPEN) == 0) {
14617Sbill 		ttychars(tp);
14717Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
14817Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
14917Sbill 		/*tp->t_state |= HUPCLS;*/
1502395Swnj 		dzparam(unit);
15117Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
15217Sbill 		u.u_error = EBUSY;
15317Sbill 		return;
15417Sbill 	}
1552395Swnj 	dzmodem(unit, ON);
156114Sbill 	(void) spl5();
15717Sbill 	while ((tp->t_state & CARR_ON) == 0) {
15817Sbill 		tp->t_state |= WOPEN;
15917Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
16017Sbill 	}
161114Sbill 	(void) spl0();
1622395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
16317Sbill }
16417Sbill 
1652395Swnj /*ARGSUSED*/
1662395Swnj dzclose(dev, flag)
1672395Swnj 	dev_t dev;
16817Sbill {
16917Sbill 	register struct tty *tp;
1702395Swnj 	register int unit;
1712395Swnj 	int dz;
17217Sbill 
1732395Swnj 	unit = minor(dev);
1742395Swnj 	dz = unit >> 3;
1752395Swnj 	tp = &dz_tty[unit];
17617Sbill 	(*linesw[tp->t_line].l_close)(tp);
1772197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1782395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
17917Sbill 	if (tp->t_state & HUPCLS)
1802395Swnj 		dzmodem(unit, OFF);
18117Sbill 	ttyclose(tp);
18217Sbill }
18317Sbill 
1842395Swnj dzread(dev)
1852395Swnj 	dev_t dev;
18617Sbill {
18717Sbill 	register struct tty *tp;
18817Sbill 
1892395Swnj 	tp = &dz_tty[minor(dev)];
19017Sbill 	(*linesw[tp->t_line].l_read)(tp);
19117Sbill }
19217Sbill 
1932395Swnj dzwrite(dev)
1942395Swnj 	dev_t dev;
19517Sbill {
19617Sbill 	register struct tty *tp;
19717Sbill 
1982395Swnj 	tp = &dz_tty[minor(dev)];
19917Sbill 	(*linesw[tp->t_line].l_write)(tp);
20017Sbill }
20117Sbill 
202119Sbill /*ARGSUSED*/
2032395Swnj dzrint(dz)
2042395Swnj 	int dz;
20517Sbill {
20617Sbill 	register struct tty *tp;
20717Sbill 	register int c;
20817Sbill 	register struct device *dzaddr;
209119Sbill 	register struct tty *tp0;
2102395Swnj 	register int unit;
211140Sbill 	int s;
21217Sbill 
213140Sbill 	s = spl6();	/* see comment in clock.c */
214119Sbill 	/* as long as we are here, service them all */
2152395Swnj 	for (unit = 0; unit < NDZ; unit += 8) {
2162395Swnj 		if ((dzact & (1<<(unit>>3))) == 0)
21717Sbill 			continue;
2182395Swnj 		dzaddr = dzpdma[unit].p_addr;
2192395Swnj 		tp0 = &dz_tty[unit];
220119Sbill 		while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
221119Sbill 			tp = tp0 + ((c>>8)&07);
222119Sbill 			if (tp >= &dz_tty[dz_cnt])
22317Sbill 				continue;
224119Sbill 			if ((tp->t_state & ISOPEN) == 0) {
225119Sbill 				wakeup((caddr_t)&tp->t_rawq);
226119Sbill 				continue;
227119Sbill 			}
228119Sbill 			if (c&FRERROR)
229119Sbill 				/* framing error = break */
230119Sbill 				if (tp->t_flags & RAW)
231119Sbill 					c = 0;		/* null for getty */
232119Sbill 				else
233185Sbill 					c = tun.t_intrc;
234119Sbill 			if (c&OVERRUN)
235119Sbill 				printf("o");
236119Sbill 			if (c&PERROR)
237119Sbill 				/* parity error */
238119Sbill 				if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
239119Sbill 				  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
240119Sbill 					continue;
241140Sbill 			if (tp->t_line == NETLDISC) {
242114Sbill 				c &= 0177;
243170Sbill 				BKINPUT(c, tp);
244114Sbill 			} else
245114Sbill 				(*linesw[tp->t_line].l_rint)(c, tp);
246119Sbill 		}
24717Sbill 	}
248140Sbill 	splx(s);
24917Sbill }
25017Sbill 
25117Sbill /*ARGSUSED*/
25217Sbill dzioctl(dev, cmd, addr, flag)
2532395Swnj 	dev_t dev;
2542395Swnj 	caddr_t addr;
25517Sbill {
25617Sbill 	register struct tty *tp;
2572395Swnj 	register int unit = minor(dev);
2582395Swnj 	register int dz = unit >> 3;
25917Sbill 
2602395Swnj 	tp = &dz_tty[unit];
261114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
262114Sbill 	if (cmd == 0)
263114Sbill 		return;
2641896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
26517Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2662395Swnj 			dzparam(unit);
267170Sbill 	} else switch(cmd) {
2682395Swnj 
269170Sbill 	case TIOCSBRK:
270882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2712395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
272170Sbill 		break;
273170Sbill 	case TIOCCBRK:
274882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2752395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
276170Sbill 		break;
277170Sbill 	case TIOCSDTR:
2782395Swnj 		dzmodem(unit, ON);
279170Sbill 		break;
280170Sbill 	case TIOCCDTR:
2812395Swnj 		dzmodem(unit, OFF);
282170Sbill 		break;
283170Sbill 	default:
28417Sbill 		u.u_error = ENOTTY;
285170Sbill 	}
28617Sbill }
28717Sbill 
2882395Swnj dzparam(unit)
2892395Swnj 	register int unit;
29017Sbill {
29117Sbill 	register struct tty *tp;
29217Sbill 	register struct device *dzaddr;
2932395Swnj 	register int lpr;
29417Sbill 
2952395Swnj 	tp = &dz_tty[unit];
2962395Swnj 	dzaddr = dzpdma[unit].p_addr;
29717Sbill 	dzaddr->dzcsr = DZ_IEN;
2982395Swnj 	dzact |= (1<<(unit>>3));
29917Sbill 	if (tp->t_ispeed == 0) {
3002395Swnj 		dzmodem(unit, OFF);		/* hang up line */
30117Sbill 		return;
30217Sbill 	}
3032395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3042296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
30517Sbill 		lpr |= BITS8;
30617Sbill 	else
30717Sbill 		lpr |= (BITS7|PENABLE);
30817Sbill 	if ((tp->t_flags & EVENP) == 0)
30917Sbill 		lpr |= OPAR;
31017Sbill 	if (tp->t_ispeed == 3)
31117Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
31217Sbill 	dzaddr->dzlpr = lpr;
31317Sbill }
31417Sbill 
31517Sbill dzxint(tp)
3162395Swnj 	register struct tty *tp;
31717Sbill {
31817Sbill 	register struct pdma *dp;
319145Sbill 	register s;
320145Sbill 	s = spl6();	/* block the clock */
32117Sbill 
3222395Swnj 	dp = (struct pdma *)tp->t_addr;
32317Sbill 	tp->t_state &= ~BUSY;
32417Sbill 	if (tp->t_state & FLUSH)
32517Sbill 		tp->t_state &= ~FLUSH;
32617Sbill 	else
327281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
32817Sbill 	if (tp->t_line)
32917Sbill 		(*linesw[tp->t_line].l_start)(tp);
33017Sbill 	else
33117Sbill 		dzstart(tp);
33217Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3332395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
334145Sbill 	splx(s);
33517Sbill }
33617Sbill 
33717Sbill dzstart(tp)
3382395Swnj 	register struct tty *tp;
33917Sbill {
34017Sbill 	register struct pdma *dp;
34117Sbill 	register struct device *dzaddr;
3422395Swnj 	register int cc;
3432395Swnj 	int s;
34417Sbill 
3452395Swnj 	dp = (struct pdma *)tp->t_addr;
34617Sbill 	dzaddr = dp->p_addr;
3472395Swnj 	s = spl5();
34817Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
34917Sbill 		goto out;
350921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
35117Sbill 		tp->t_state &= ~ASLEEP;
35217Sbill 		if (tp->t_chan)
35317Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
35417Sbill 		else
35517Sbill 			wakeup((caddr_t)&tp->t_outq);
35617Sbill 	}
35717Sbill 	if (tp->t_outq.c_cc == 0)
35817Sbill 		goto out;
35917Sbill 	if (tp->t_flags&RAW)
36017Sbill 		cc = ndqb(&tp->t_outq, 0);
36117Sbill 	else {
36217Sbill 		cc = ndqb(&tp->t_outq, 0200);
36317Sbill 		if (cc == 0) {
36417Sbill 			cc = getc(&tp->t_outq);
36517Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
36617Sbill 			tp->t_state |= TIMEOUT;
36717Sbill 			goto out;
36817Sbill 		}
36917Sbill 	}
37017Sbill 	tp->t_state |= BUSY;
37117Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
37217Sbill 	dp->p_end += cc;
3732395Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);
3742395Swnj out:
3752395Swnj 	splx(s);
37617Sbill }
37717Sbill 
37817Sbill /*
37917Sbill  * Stop output on a line.
38017Sbill  */
38117Sbill /*ARGSUSED*/
38217Sbill dzstop(tp, flag)
3832395Swnj 	register struct tty *tp;
38417Sbill {
38517Sbill 	register struct pdma *dp;
38617Sbill 	register int s;
38717Sbill 
3882395Swnj 	dp = (struct pdma *)tp->t_addr;
38917Sbill 	s = spl6();
39017Sbill 	if (tp->t_state & BUSY) {
39117Sbill 		dp->p_end = dp->p_mem;
3922395Swnj 		if ((tp->t_state&TTSTOP)==0)
39317Sbill 			tp->t_state |= FLUSH;
39417Sbill 	}
39517Sbill 	splx(s);
39617Sbill }
39717Sbill 
3982395Swnj dzmodem(unit, flag)
3992395Swnj 	register int unit;
40017Sbill {
40117Sbill 	register struct device *dzaddr;
40217Sbill 	register char bit;
40317Sbill 
4042395Swnj 	dzaddr = dzpdma[unit].p_addr;
4052395Swnj 	bit = 1<<(unit&07);
40617Sbill 	if (flag == OFF)
40717Sbill 		dzaddr->dzdtr &= ~bit;
40817Sbill 	else
40917Sbill 		dzaddr->dzdtr |= bit;
41017Sbill }
41117Sbill 
41217Sbill dzscan()
41317Sbill {
41417Sbill 	register i;
41517Sbill 	register struct device *dzaddr;
41617Sbill 	register bit;
41717Sbill 	register struct tty *tp;
41817Sbill 
41917Sbill 	for (i = 0; i < dz_cnt ; i++) {
42017Sbill 		dzaddr = dzpdma[i].p_addr;
42117Sbill 		tp = &dz_tty[i];
42217Sbill 		bit = 1<<(i&07);
423*2422Skre #ifdef BERT
424*2422Skre 		if (dzaddr->dzmsr & bit || i == 6 || i == 7) {
425*2422Skre #else
426*2422Skre 		if (dzaddr->dzmsr & bit) {
427*2422Skre #endif
42817Sbill 			/* carrier present */
42917Sbill 			if ((tp->t_state & CARR_ON) == 0) {
43017Sbill 				wakeup((caddr_t)&tp->t_rawq);
43117Sbill 				tp->t_state |= CARR_ON;
43217Sbill 			}
43317Sbill 		} else {
4342395Swnj 			if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) {
43517Sbill 				/* carrier lost */
436882Sbill 				if (tp->t_state&ISOPEN) {
437170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
438205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
439170Sbill 					dzaddr->dzdtr &= ~bit;
440871Sbill 					flushtty(tp, FREAD|FWRITE);
441170Sbill 				}
442170Sbill 				tp->t_state &= ~CARR_ON;
44317Sbill 			}
44417Sbill 		}
44517Sbill 	}
44617Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
44717Sbill }
448119Sbill 
449119Sbill dztimer()
450119Sbill {
451119Sbill 
452119Sbill 	dzrint(0);
453119Sbill }
454281Sbill 
455281Sbill /*
456281Sbill  * Reset state of driver if UBA reset was necessary.
457301Sbill  * Reset parameters and restart transmission on open lines.
458281Sbill  */
4592395Swnj dzreset(uban)
460*2422Skre 	int uban;
461281Sbill {
4622395Swnj 	register int unit;
463281Sbill 	register struct tty *tp;
464*2422Skre 	register struct uba_dinfo *ui;
465*2422Skre 	int any = 0;
466281Sbill 
4672395Swnj 	for (unit = 0; unit < NDZ; unit++) {
468*2422Skre 		ui = dzinfo[unit >> 3];
469*2422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
470*2422Skre 			continue;
471*2422Skre 		if (any == 0) {
472*2422Skre 			printf(" dz");
473*2422Skre 			any++;
474*2422Skre 		}
4752395Swnj 		tp = &dz_tty[unit];
476281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4772395Swnj 			dzparam(unit);
4782395Swnj 			dzmodem(unit, ON);
479301Sbill 			tp->t_state &= ~BUSY;
480301Sbill 			dzstart(tp);
481281Sbill 		}
482281Sbill 	}
483281Sbill 	dztimer();
484281Sbill }
4851562Sbill #endif
486