xref: /csrg-svn/sys/vax/uba/dz.c (revision 5407)
1*5407Swnj /*	dz.c	4.32	82/01/14	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 0
517Sbill /*
64933Swnj  * DZ-11 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 
412469Swnj /* Bits in dzlpr */
422457Swnj #define	BITS7	020
432457Swnj #define	BITS8	030
442457Swnj #define	TWOSB	040
452457Swnj #define	PENABLE	0100
462457Swnj #define	OPAR	0200
4717Sbill 
482469Swnj /* Bits in dzrbuf */
492469Swnj #define	DZ_PE	010000
502469Swnj #define	DZ_FE	020000
512469Swnj #define	DZ_DO	040000
522469Swnj 
532469Swnj /* Bits in dzcsr */
542469Swnj #define	DZ_CLR	020		/* Reset dz */
552469Swnj #define	DZ_MSE	040		/* Master Scan Enable */
562469Swnj #define	DZ_RIE	0100		/* Receiver Interrupt Enable */
572469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
582469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
593440Sroot #define	DZ_IEN	(DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
602469Swnj 
612469Swnj /* Flags for modem-control */
622469Swnj #define	DZ_ON	1
632469Swnj #define	DZ_OFF	0
6417Sbill 
652469Swnj int	dzstart(), dzxint(), dzdma();
66114Sbill int	ttrstrt();
672645Swnj struct	tty dz_tty[NDZLINE];
682645Swnj int	dz_cnt = { NDZLINE };
69119Sbill int	dzact;
7017Sbill 
7117Sbill struct device {
722469Swnj 	short	dzcsr;		/* control-status register */
732469Swnj 	short	dzrbuf;		/* receiver buffer */
742469Swnj #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
752469Swnj 	char	dztcr;		/* transmit control register */
762469Swnj 	char	dzdtr;		/* data terminal ready */
772469Swnj 	char	dztbuf;		/* transmit buffer */
782469Swnj 	char	dzbrk;		/* break control */
792469Swnj #define	dzmsr	dzbrk		/* modem status register */
8017Sbill };
812469Swnj /*
822469Swnj  * Software copy of dzbrk since it isn't readable
832469Swnj  */
842645Swnj char	dz_brk[NDZ];
852645Swnj char	dzsoftCAR[NDZ];
8617Sbill 
872469Swnj /*
882469Swnj  * The dz doesn't interrupt on carrier transitions, so
892469Swnj  * we have to use a timer to watch it.
902469Swnj  */
912469Swnj char	dz_timer;		/* timer started? */
922469Swnj 
932469Swnj /*
942469Swnj  * Pdma structures for fast output code
952469Swnj  */
962645Swnj struct	pdma dzpdma[NDZLINE];
972469Swnj 
982395Swnj char	dz_speeds[] =
992395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
10017Sbill 
1012606Swnj dzprobe(reg)
1022395Swnj 	caddr_t reg;
1032395Swnj {
1042457Swnj 	register int br, cvec;
1052457Swnj 	register struct device *dzaddr = (struct device *)reg;
1062395Swnj 
1072606Swnj #ifdef lint
1083102Swnj 	br = 0; cvec = br; br = cvec;
1094933Swnj 	dzrint(0); dzxint((struct tty *)0);
1102606Swnj #endif
1112469Swnj 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
1122422Skre 	dzaddr->dztcr = 1;		/* enable any line */
1132457Swnj 	DELAY(100000);
1142469Swnj 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
1152457Swnj 	if (cvec && cvec != 0x200)
1162457Swnj 		cvec -= 4;
1172457Swnj 	return (1);
1182395Swnj }
1192395Swnj 
1202606Swnj dzattach(ui)
1212976Swnj 	register struct uba_device *ui;
1222395Swnj {
1232395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1242395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1252606Swnj 	register int cntr;
1262645Swnj 	extern dzscan();
1272395Swnj 
1282606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1292606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1302395Swnj 		pdp->p_arg = (int)tp;
1312395Swnj 		pdp->p_fcn = dzxint;
1322395Swnj 		pdp++, tp++;
1332395Swnj 	}
1342567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1352627Swnj 	if (dz_timer == 0) {
1362627Swnj 		dz_timer++;
1372756Swnj 		timeout(dzscan, (caddr_t)0, hz);
1382627Swnj 	}
1392395Swnj }
1402395Swnj 
14117Sbill /*ARGSUSED*/
1422395Swnj dzopen(dev, flag)
1432395Swnj 	dev_t dev;
14417Sbill {
14517Sbill 	register struct tty *tp;
1462395Swnj 	register int unit;
14717Sbill 
1482395Swnj 	unit = minor(dev);
1492395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
15017Sbill 		u.u_error = ENXIO;
15117Sbill 		return;
15217Sbill 	}
1532395Swnj 	tp = &dz_tty[unit];
1542395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
15517Sbill 	tp->t_oproc = dzstart;
156*5407Swnj 	tp->t_state |= TS_WOPEN;
157*5407Swnj 	if ((tp->t_state & TS_ISOPEN) == 0) {
15817Sbill 		ttychars(tp);
1592469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
16017Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
161*5407Swnj 		/* tp->t_state |= TS_HUPCLS; */
1622395Swnj 		dzparam(unit);
163*5407Swnj 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) {
16417Sbill 		u.u_error = EBUSY;
16517Sbill 		return;
16617Sbill 	}
1672469Swnj 	dzmodem(unit, DZ_ON);
168114Sbill 	(void) spl5();
169*5407Swnj 	while ((tp->t_state & TS_CARR_ON) == 0) {
170*5407Swnj 		tp->t_state |= TS_WOPEN;
17117Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17217Sbill 	}
173114Sbill 	(void) spl0();
1742395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
17517Sbill }
17617Sbill 
1772395Swnj /*ARGSUSED*/
1782395Swnj dzclose(dev, flag)
1792395Swnj 	dev_t dev;
18017Sbill {
18117Sbill 	register struct tty *tp;
1822395Swnj 	register int unit;
1832395Swnj 	int dz;
18417Sbill 
1852395Swnj 	unit = minor(dev);
1862395Swnj 	dz = unit >> 3;
1872395Swnj 	tp = &dz_tty[unit];
18817Sbill 	(*linesw[tp->t_line].l_close)(tp);
1892197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1902395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
191*5407Swnj 	if (tp->t_state & TS_HUPCLS)
1922469Swnj 		dzmodem(unit, DZ_OFF);
19317Sbill 	ttyclose(tp);
19417Sbill }
19517Sbill 
1962395Swnj dzread(dev)
1972395Swnj 	dev_t dev;
19817Sbill {
19917Sbill 	register struct tty *tp;
20017Sbill 
2012395Swnj 	tp = &dz_tty[minor(dev)];
20217Sbill 	(*linesw[tp->t_line].l_read)(tp);
20317Sbill }
20417Sbill 
2052395Swnj dzwrite(dev)
2062395Swnj 	dev_t dev;
20717Sbill {
20817Sbill 	register struct tty *tp;
20917Sbill 
2102395Swnj 	tp = &dz_tty[minor(dev)];
21117Sbill 	(*linesw[tp->t_line].l_write)(tp);
21217Sbill }
21317Sbill 
214119Sbill /*ARGSUSED*/
2152395Swnj dzrint(dz)
2162395Swnj 	int dz;
21717Sbill {
21817Sbill 	register struct tty *tp;
21917Sbill 	register int c;
22017Sbill 	register struct device *dzaddr;
221119Sbill 	register struct tty *tp0;
2222395Swnj 	register int unit;
2232923Swnj 	int overrun = 0;
22417Sbill 
2252457Swnj 	if ((dzact & (1<<dz)) == 0)
2262457Swnj 		return;
2272457Swnj 	unit = dz * 8;
2282457Swnj 	dzaddr = dzpdma[unit].p_addr;
2292457Swnj 	tp0 = &dz_tty[unit];
2302457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
2312457Swnj 		tp = tp0 + ((c>>8)&07);
2322457Swnj 		if (tp >= &dz_tty[dz_cnt])
23317Sbill 			continue;
234*5407Swnj 		if ((tp->t_state & TS_ISOPEN) == 0) {
2352457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2362457Swnj 			continue;
2372457Swnj 		}
2382469Swnj 		if (c&DZ_FE)
2392457Swnj 			if (tp->t_flags & RAW)
2402469Swnj 				c = 0;
2412457Swnj 			else
2422457Swnj 				c = tun.t_intrc;
2432923Swnj 		if (c&DZ_DO && overrun == 0) {
2442923Swnj 			printf("dz%d: silo overflow\n", dz);
2452923Swnj 			overrun = 1;
2462923Swnj 		}
2472469Swnj 		if (c&DZ_PE)
2482457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2492457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
25017Sbill 				continue;
2512731Swnj #if NBK > 0
2522457Swnj 		if (tp->t_line == NETLDISC) {
2532457Swnj 			c &= 0177;
2542457Swnj 			BKINPUT(c, tp);
2552457Swnj 		} else
2562731Swnj #endif
2572457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
25817Sbill 	}
25917Sbill }
26017Sbill 
26117Sbill /*ARGSUSED*/
26217Sbill dzioctl(dev, cmd, addr, flag)
2632395Swnj 	dev_t dev;
2642395Swnj 	caddr_t addr;
26517Sbill {
26617Sbill 	register struct tty *tp;
2672395Swnj 	register int unit = minor(dev);
2682395Swnj 	register int dz = unit >> 3;
26917Sbill 
2702395Swnj 	tp = &dz_tty[unit];
271114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
272114Sbill 	if (cmd == 0)
273114Sbill 		return;
2741896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
27517Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2762395Swnj 			dzparam(unit);
277170Sbill 	} else switch(cmd) {
2782395Swnj 
279170Sbill 	case TIOCSBRK:
280882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2812395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
282170Sbill 		break;
283170Sbill 	case TIOCCBRK:
284882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2852395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
286170Sbill 		break;
287170Sbill 	case TIOCSDTR:
2882469Swnj 		dzmodem(unit, DZ_ON);
289170Sbill 		break;
290170Sbill 	case TIOCCDTR:
2912469Swnj 		dzmodem(unit, DZ_OFF);
292170Sbill 		break;
293170Sbill 	default:
29417Sbill 		u.u_error = ENOTTY;
295170Sbill 	}
29617Sbill }
29717Sbill 
2982395Swnj dzparam(unit)
2992395Swnj 	register int unit;
30017Sbill {
30117Sbill 	register struct tty *tp;
30217Sbill 	register struct device *dzaddr;
3032395Swnj 	register int lpr;
30417Sbill 
3052395Swnj 	tp = &dz_tty[unit];
3062395Swnj 	dzaddr = dzpdma[unit].p_addr;
30717Sbill 	dzaddr->dzcsr = DZ_IEN;
3082395Swnj 	dzact |= (1<<(unit>>3));
30917Sbill 	if (tp->t_ispeed == 0) {
3102469Swnj 		dzmodem(unit, DZ_OFF);		/* hang up line */
31117Sbill 		return;
31217Sbill 	}
3132395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3142296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
31517Sbill 		lpr |= BITS8;
31617Sbill 	else
31717Sbill 		lpr |= (BITS7|PENABLE);
31817Sbill 	if ((tp->t_flags & EVENP) == 0)
31917Sbill 		lpr |= OPAR;
3202469Swnj 	if (tp->t_ispeed == B110)
3212469Swnj 		lpr |= TWOSB;
32217Sbill 	dzaddr->dzlpr = lpr;
32317Sbill }
32417Sbill 
32517Sbill dzxint(tp)
3262395Swnj 	register struct tty *tp;
32717Sbill {
32817Sbill 	register struct pdma *dp;
329145Sbill 	register s;
33017Sbill 
3312469Swnj 	s = spl5();		/* block pdma interrupts */
3322395Swnj 	dp = (struct pdma *)tp->t_addr;
333*5407Swnj 	tp->t_state &= ~TS_BUSY;
334*5407Swnj 	if (tp->t_state & TS_FLUSH)
335*5407Swnj 		tp->t_state &= ~TS_FLUSH;
33617Sbill 	else
337281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
33817Sbill 	if (tp->t_line)
33917Sbill 		(*linesw[tp->t_line].l_start)(tp);
34017Sbill 	else
34117Sbill 		dzstart(tp);
342*5407Swnj 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
3432395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
344145Sbill 	splx(s);
34517Sbill }
34617Sbill 
34717Sbill dzstart(tp)
3482395Swnj 	register struct tty *tp;
34917Sbill {
35017Sbill 	register struct pdma *dp;
35117Sbill 	register struct device *dzaddr;
3522395Swnj 	register int cc;
3532395Swnj 	int s;
35417Sbill 
3552395Swnj 	dp = (struct pdma *)tp->t_addr;
35617Sbill 	dzaddr = dp->p_addr;
3572395Swnj 	s = spl5();
358*5407Swnj 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
35917Sbill 		goto out;
360*5407Swnj 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
361*5407Swnj 		if (tp->t_state&TS_ASLEEP) {
362*5407Swnj 			tp->t_state &= ~TS_ASLEEP;
363*5407Swnj 			wakeup((caddr_t)&tp->t_outq);
364*5407Swnj 		}
365*5407Swnj 		if (tp->t_wsel) {
366*5407Swnj 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
367*5407Swnj 			tp->t_wsel = 0;
368*5407Swnj 			tp->t_state &= ~TS_WCOLL;
369*5407Swnj 		}
37017Sbill 	}
37117Sbill 	if (tp->t_outq.c_cc == 0)
37217Sbill 		goto out;
3733819Swnj 	if (tp->t_flags&RAW || tp->t_local&LLITOUT)
37417Sbill 		cc = ndqb(&tp->t_outq, 0);
37517Sbill 	else {
37617Sbill 		cc = ndqb(&tp->t_outq, 0200);
37717Sbill 		if (cc == 0) {
37817Sbill 			cc = getc(&tp->t_outq);
3792469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
380*5407Swnj 			tp->t_state |= TS_TIMEOUT;
38117Sbill 			goto out;
38217Sbill 		}
38317Sbill 	}
384*5407Swnj 	tp->t_state |= TS_BUSY;
38517Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
38617Sbill 	dp->p_end += cc;
3872469Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
3882395Swnj out:
3892395Swnj 	splx(s);
39017Sbill }
39117Sbill 
39217Sbill /*
39317Sbill  * Stop output on a line.
39417Sbill  */
39517Sbill /*ARGSUSED*/
39617Sbill dzstop(tp, flag)
3972395Swnj 	register struct tty *tp;
39817Sbill {
39917Sbill 	register struct pdma *dp;
40017Sbill 	register int s;
40117Sbill 
4022395Swnj 	dp = (struct pdma *)tp->t_addr;
4032457Swnj 	s = spl5();
404*5407Swnj 	if (tp->t_state & TS_BUSY) {
40517Sbill 		dp->p_end = dp->p_mem;
406*5407Swnj 		if ((tp->t_state&TS_TTSTOP)==0)
407*5407Swnj 			tp->t_state |= TS_FLUSH;
40817Sbill 	}
40917Sbill 	splx(s);
41017Sbill }
41117Sbill 
4122395Swnj dzmodem(unit, flag)
4132395Swnj 	register int unit;
41417Sbill {
41517Sbill 	register struct device *dzaddr;
41617Sbill 	register char bit;
41717Sbill 
4182395Swnj 	dzaddr = dzpdma[unit].p_addr;
4192395Swnj 	bit = 1<<(unit&07);
4202469Swnj 	if (flag == DZ_OFF)
42117Sbill 		dzaddr->dzdtr &= ~bit;
42217Sbill 	else
42317Sbill 		dzaddr->dzdtr |= bit;
42417Sbill }
42517Sbill 
42617Sbill dzscan()
42717Sbill {
42817Sbill 	register i;
42917Sbill 	register struct device *dzaddr;
43017Sbill 	register bit;
43117Sbill 	register struct tty *tp;
43217Sbill 
43317Sbill 	for (i = 0; i < dz_cnt ; i++) {
43417Sbill 		dzaddr = dzpdma[i].p_addr;
4352627Swnj 		if (dzaddr == 0)
4362627Swnj 			continue;
43717Sbill 		tp = &dz_tty[i];
43817Sbill 		bit = 1<<(i&07);
4392606Swnj 		if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
44017Sbill 			/* carrier present */
441*5407Swnj 			if ((tp->t_state & TS_CARR_ON) == 0) {
44217Sbill 				wakeup((caddr_t)&tp->t_rawq);
443*5407Swnj 				tp->t_state |= TS_CARR_ON;
44417Sbill 			}
44517Sbill 		} else {
446*5407Swnj 			if ((tp->t_state&TS_CARR_ON) &&
4472469Swnj 			    (tp->t_local&LNOHANG)==0) {
44817Sbill 				/* carrier lost */
449*5407Swnj 				if (tp->t_state&TS_ISOPEN) {
450170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
451205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
452170Sbill 					dzaddr->dzdtr &= ~bit;
453871Sbill 					flushtty(tp, FREAD|FWRITE);
454170Sbill 				}
455*5407Swnj 				tp->t_state &= ~TS_CARR_ON;
45617Sbill 			}
45717Sbill 		}
45817Sbill 	}
4592756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
46017Sbill }
461119Sbill 
462119Sbill dztimer()
463119Sbill {
4642457Swnj 	int dz;
465119Sbill 
4662645Swnj 	for (dz = 0; dz < NDZ; dz++)
4672457Swnj 		dzrint(dz);
468119Sbill }
469281Sbill 
470281Sbill /*
471281Sbill  * Reset state of driver if UBA reset was necessary.
472301Sbill  * Reset parameters and restart transmission on open lines.
473281Sbill  */
4742395Swnj dzreset(uban)
4752422Skre 	int uban;
476281Sbill {
4772395Swnj 	register int unit;
478281Sbill 	register struct tty *tp;
4792976Swnj 	register struct uba_device *ui;
480281Sbill 
4812645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
4822422Skre 		ui = dzinfo[unit >> 3];
4832422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4842422Skre 			continue;
4852923Swnj 		if (unit%8 == 0)
4862923Swnj 			printf(" dz%d", unit>>3);
4872395Swnj 		tp = &dz_tty[unit];
488*5407Swnj 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
4892395Swnj 			dzparam(unit);
4902469Swnj 			dzmodem(unit, DZ_ON);
491*5407Swnj 			tp->t_state &= ~TS_BUSY;
492301Sbill 			dzstart(tp);
493281Sbill 		}
494281Sbill 	}
495281Sbill 	dztimer();
496281Sbill }
4971562Sbill #endif
498