xref: /csrg-svn/sys/vax/uba/dz.c (revision 2567)
1*2567Swnj /*	dz.c	4.14	02/19/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
82469Swnj  *
92469Swnj  * 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"
19*2567Swnj #include "../h/vm.h"
2017Sbill #include "../h/uba.h"
2117Sbill #include "../h/conf.h"
2217Sbill #include "../h/pdma.h"
23114Sbill #include "../h/bk.h"
24871Sbill #include "../h/file.h"
251786Sbill #include "../h/mx.h"
26145Sbill 
272469Swnj /*
282469Swnj  * Driver information for auto-configuration stuff.
292469Swnj  */
302395Swnj int	dzcntrlr(), dzslave(), dzrint();
312395Swnj struct	uba_dinfo *dzinfo[NDZ11];
322395Swnj u_short	dzstd[] = { 0 };
332395Swnj struct	uba_driver dzdriver =
342457Swnj 	{ dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo };
352395Swnj 
362457Swnj #define	NDZ 	(NDZ11*8)
3717Sbill 
382469Swnj /*
392469Swnj  * Registers and bits
402469Swnj  */
412469Swnj 
422469Swnj /* Bits in dzlpr */
432457Swnj #define	BITS7	020
442457Swnj #define	BITS8	030
452457Swnj #define	TWOSB	040
462457Swnj #define	PENABLE	0100
472457Swnj #define	OPAR	0200
4817Sbill 
492469Swnj /* Bits in dzrbuf */
502469Swnj #define	DZ_PE	010000
512469Swnj #define	DZ_FE	020000
522469Swnj #define	DZ_DO	040000
532469Swnj 
542469Swnj /* Bits in dzcsr */
552469Swnj #define	DZ_CLR	020		/* Reset dz */
562469Swnj #define	DZ_MSE	040		/* Master Scan Enable */
572469Swnj #define	DZ_RIE	0100		/* Receiver Interrupt Enable */
582469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
592469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
602469Swnj #define	DZ_IEN	(DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE)
612469Swnj 
622469Swnj /* Flags for modem-control */
632469Swnj #define	DZ_ON	1
642469Swnj #define	DZ_OFF	0
6517Sbill 
662469Swnj int	dzstart(), dzxint(), dzdma();
67114Sbill int	ttrstrt();
6817Sbill struct	tty dz_tty[NDZ];
6917Sbill int	dz_cnt = { NDZ };
70119Sbill int	dzact;
7117Sbill 
7217Sbill struct device {
732469Swnj 	short	dzcsr;		/* control-status register */
742469Swnj 	short	dzrbuf;		/* receiver buffer */
752469Swnj #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
762469Swnj 	char	dztcr;		/* transmit control register */
772469Swnj 	char	dzdtr;		/* data terminal ready */
782469Swnj 	char	dztbuf;		/* transmit buffer */
792469Swnj 	char	dzbrk;		/* break control */
802469Swnj #define	dzmsr	dzbrk		/* modem status register */
8117Sbill };
822469Swnj /*
832469Swnj  * Software copy of dzbrk since it isn't readable
842469Swnj  */
852469Swnj char	dz_brk[NDZ11];
86*2567Swnj char	dzsoftCAR[NDZ11];
8717Sbill 
882469Swnj /*
892469Swnj  * The dz doesn't interrupt on carrier transitions, so
902469Swnj  * we have to use a timer to watch it.
912469Swnj  */
922469Swnj char	dz_timer;		/* timer started? */
932469Swnj 
942469Swnj /*
952469Swnj  * Pdma structures for fast output code
962469Swnj  */
972395Swnj struct	pdma dzpdma[NDZ];
982469Swnj 
992395Swnj char	dz_speeds[] =
1002395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
10117Sbill 
1022395Swnj dzcntrlr(ui, reg)
1032395Swnj 	struct uba_dinfo *ui;
1042395Swnj 	caddr_t reg;
1052395Swnj {
1062457Swnj 	register int br, cvec;
1072457Swnj 	register struct device *dzaddr = (struct device *)reg;
1082395Swnj 
1092469Swnj 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
1102422Skre 	dzaddr->dztcr = 1;		/* enable any line */
1112457Swnj 	DELAY(100000);
1122469Swnj 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
1132457Swnj 	if (cvec && cvec != 0x200)
1142457Swnj 		cvec -= 4;
1152457Swnj 	return (1);
1162395Swnj }
1172395Swnj 
1182469Swnj /*
1192469Swnj  * Called by auto-configure to initialize good dz's;
1202469Swnj  * set up pdma structures.
1212469Swnj  */
122*2567Swnj dzslave(ui, reg)
1232395Swnj 	register struct uba_dinfo *ui;
1242395Swnj 	caddr_t reg;
1252395Swnj {
1262395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1272395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1282395Swnj 	register int cnt;
1292395Swnj 
1302395Swnj 	for (cnt = 0; cnt < 8; cnt++) {
1312395Swnj 		pdp->p_addr = (struct device *)reg;
1322395Swnj 		pdp->p_arg = (int)tp;
1332395Swnj 		pdp->p_fcn = dzxint;
1342395Swnj 		pdp++, tp++;
1352395Swnj 	}
136*2567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1372395Swnj 	return (1);
1382395Swnj }
1392395Swnj 
14017Sbill /*ARGSUSED*/
1412395Swnj dzopen(dev, flag)
1422395Swnj 	dev_t dev;
14317Sbill {
14417Sbill 	register struct tty *tp;
1452395Swnj 	register int unit;
14617Sbill 	extern dzscan();
14717Sbill 
1482395Swnj 	unit = minor(dev);
1492395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
15017Sbill 		u.u_error = ENXIO;
15117Sbill 		return;
15217Sbill 	}
15317Sbill 	if (dz_timer == 0) {
15417Sbill 		dz_timer++;
1552469Swnj 		timeout(dzscan, (caddr_t)0, HZ);
15617Sbill 	}
1572395Swnj 	tp = &dz_tty[unit];
1582395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
15917Sbill 	tp->t_oproc = dzstart;
16017Sbill 	tp->t_iproc = NULL;
16117Sbill 	tp->t_state |= WOPEN;
16217Sbill 	if ((tp->t_state & ISOPEN) == 0) {
16317Sbill 		ttychars(tp);
1642469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
16517Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
1662469Swnj 		/* tp->t_state |= HUPCLS; */
1672395Swnj 		dzparam(unit);
16817Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
16917Sbill 		u.u_error = EBUSY;
17017Sbill 		return;
17117Sbill 	}
1722469Swnj 	dzmodem(unit, DZ_ON);
173114Sbill 	(void) spl5();
17417Sbill 	while ((tp->t_state & CARR_ON) == 0) {
17517Sbill 		tp->t_state |= WOPEN;
17617Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17717Sbill 	}
178114Sbill 	(void) spl0();
1792395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
18017Sbill }
18117Sbill 
1822395Swnj /*ARGSUSED*/
1832395Swnj dzclose(dev, flag)
1842395Swnj 	dev_t dev;
18517Sbill {
18617Sbill 	register struct tty *tp;
1872395Swnj 	register int unit;
1882395Swnj 	int dz;
18917Sbill 
1902395Swnj 	unit = minor(dev);
1912395Swnj 	dz = unit >> 3;
1922395Swnj 	tp = &dz_tty[unit];
19317Sbill 	(*linesw[tp->t_line].l_close)(tp);
1942197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1952395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
19617Sbill 	if (tp->t_state & HUPCLS)
1972469Swnj 		dzmodem(unit, DZ_OFF);
19817Sbill 	ttyclose(tp);
19917Sbill }
20017Sbill 
2012395Swnj dzread(dev)
2022395Swnj 	dev_t dev;
20317Sbill {
20417Sbill 	register struct tty *tp;
20517Sbill 
2062395Swnj 	tp = &dz_tty[minor(dev)];
20717Sbill 	(*linesw[tp->t_line].l_read)(tp);
20817Sbill }
20917Sbill 
2102395Swnj dzwrite(dev)
2112395Swnj 	dev_t dev;
21217Sbill {
21317Sbill 	register struct tty *tp;
21417Sbill 
2152395Swnj 	tp = &dz_tty[minor(dev)];
21617Sbill 	(*linesw[tp->t_line].l_write)(tp);
21717Sbill }
21817Sbill 
219119Sbill /*ARGSUSED*/
2202395Swnj dzrint(dz)
2212395Swnj 	int dz;
22217Sbill {
22317Sbill 	register struct tty *tp;
22417Sbill 	register int c;
22517Sbill 	register struct device *dzaddr;
226119Sbill 	register struct tty *tp0;
2272395Swnj 	register int unit;
228140Sbill 	int s;
22917Sbill 
2302457Swnj 	if ((dzact & (1<<dz)) == 0)
2312457Swnj 		return;
2322457Swnj 	unit = dz * 8;
2332457Swnj 	dzaddr = dzpdma[unit].p_addr;
2342457Swnj 	tp0 = &dz_tty[unit];
2352457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
2362457Swnj 		tp = tp0 + ((c>>8)&07);
2372457Swnj 		if (tp >= &dz_tty[dz_cnt])
23817Sbill 			continue;
2392457Swnj 		if ((tp->t_state & ISOPEN) == 0) {
2402457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2412457Swnj 			continue;
2422457Swnj 		}
2432469Swnj 		if (c&DZ_FE)
2442457Swnj 			if (tp->t_flags & RAW)
2452469Swnj 				c = 0;
2462457Swnj 			else
2472457Swnj 				c = tun.t_intrc;
2482469Swnj 		if (c&DZ_DO)
2492457Swnj 			printf("o");
2502469Swnj 		if (c&DZ_PE)
2512457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2522457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
25317Sbill 				continue;
2542457Swnj 		if (tp->t_line == NETLDISC) {
2552457Swnj 			c &= 0177;
2562457Swnj 			BKINPUT(c, tp);
2572457Swnj 		} else
2582457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
25917Sbill 	}
26017Sbill }
26117Sbill 
26217Sbill /*ARGSUSED*/
26317Sbill dzioctl(dev, cmd, addr, flag)
2642395Swnj 	dev_t dev;
2652395Swnj 	caddr_t addr;
26617Sbill {
26717Sbill 	register struct tty *tp;
2682395Swnj 	register int unit = minor(dev);
2692395Swnj 	register int dz = unit >> 3;
27017Sbill 
2712395Swnj 	tp = &dz_tty[unit];
272114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
273114Sbill 	if (cmd == 0)
274114Sbill 		return;
2751896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
27617Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2772395Swnj 			dzparam(unit);
278170Sbill 	} else switch(cmd) {
2792395Swnj 
280170Sbill 	case TIOCSBRK:
281882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2822395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
283170Sbill 		break;
284170Sbill 	case TIOCCBRK:
285882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2862395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
287170Sbill 		break;
288170Sbill 	case TIOCSDTR:
2892469Swnj 		dzmodem(unit, DZ_ON);
290170Sbill 		break;
291170Sbill 	case TIOCCDTR:
2922469Swnj 		dzmodem(unit, DZ_OFF);
293170Sbill 		break;
294170Sbill 	default:
29517Sbill 		u.u_error = ENOTTY;
296170Sbill 	}
29717Sbill }
29817Sbill 
2992395Swnj dzparam(unit)
3002395Swnj 	register int unit;
30117Sbill {
30217Sbill 	register struct tty *tp;
30317Sbill 	register struct device *dzaddr;
3042395Swnj 	register int lpr;
30517Sbill 
3062395Swnj 	tp = &dz_tty[unit];
3072395Swnj 	dzaddr = dzpdma[unit].p_addr;
30817Sbill 	dzaddr->dzcsr = DZ_IEN;
3092395Swnj 	dzact |= (1<<(unit>>3));
31017Sbill 	if (tp->t_ispeed == 0) {
3112469Swnj 		dzmodem(unit, DZ_OFF);		/* hang up line */
31217Sbill 		return;
31317Sbill 	}
3142395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3152296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
31617Sbill 		lpr |= BITS8;
31717Sbill 	else
31817Sbill 		lpr |= (BITS7|PENABLE);
31917Sbill 	if ((tp->t_flags & EVENP) == 0)
32017Sbill 		lpr |= OPAR;
3212469Swnj 	if (tp->t_ispeed == B110)
3222469Swnj 		lpr |= TWOSB;
32317Sbill 	dzaddr->dzlpr = lpr;
32417Sbill }
32517Sbill 
32617Sbill dzxint(tp)
3272395Swnj 	register struct tty *tp;
32817Sbill {
32917Sbill 	register struct pdma *dp;
330145Sbill 	register s;
33117Sbill 
3322469Swnj 	s = spl5();		/* block pdma interrupts */
3332395Swnj 	dp = (struct pdma *)tp->t_addr;
33417Sbill 	tp->t_state &= ~BUSY;
33517Sbill 	if (tp->t_state & FLUSH)
33617Sbill 		tp->t_state &= ~FLUSH;
33717Sbill 	else
338281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
33917Sbill 	if (tp->t_line)
34017Sbill 		(*linesw[tp->t_line].l_start)(tp);
34117Sbill 	else
34217Sbill 		dzstart(tp);
34317Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3442395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
345145Sbill 	splx(s);
34617Sbill }
34717Sbill 
34817Sbill dzstart(tp)
3492395Swnj 	register struct tty *tp;
35017Sbill {
35117Sbill 	register struct pdma *dp;
35217Sbill 	register struct device *dzaddr;
3532395Swnj 	register int cc;
3542395Swnj 	int s;
35517Sbill 
3562395Swnj 	dp = (struct pdma *)tp->t_addr;
35717Sbill 	dzaddr = dp->p_addr;
3582395Swnj 	s = spl5();
35917Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
36017Sbill 		goto out;
361921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
36217Sbill 		tp->t_state &= ~ASLEEP;
36317Sbill 		if (tp->t_chan)
36417Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
36517Sbill 		else
36617Sbill 			wakeup((caddr_t)&tp->t_outq);
36717Sbill 	}
36817Sbill 	if (tp->t_outq.c_cc == 0)
36917Sbill 		goto out;
37017Sbill 	if (tp->t_flags&RAW)
37117Sbill 		cc = ndqb(&tp->t_outq, 0);
37217Sbill 	else {
37317Sbill 		cc = ndqb(&tp->t_outq, 0200);
37417Sbill 		if (cc == 0) {
37517Sbill 			cc = getc(&tp->t_outq);
3762469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
37717Sbill 			tp->t_state |= TIMEOUT;
37817Sbill 			goto out;
37917Sbill 		}
38017Sbill 	}
38117Sbill 	tp->t_state |= BUSY;
38217Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
38317Sbill 	dp->p_end += cc;
3842469Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
3852395Swnj out:
3862395Swnj 	splx(s);
38717Sbill }
38817Sbill 
38917Sbill /*
39017Sbill  * Stop output on a line.
39117Sbill  */
39217Sbill /*ARGSUSED*/
39317Sbill dzstop(tp, flag)
3942395Swnj 	register struct tty *tp;
39517Sbill {
39617Sbill 	register struct pdma *dp;
39717Sbill 	register int s;
39817Sbill 
3992395Swnj 	dp = (struct pdma *)tp->t_addr;
4002457Swnj 	s = spl5();
40117Sbill 	if (tp->t_state & BUSY) {
40217Sbill 		dp->p_end = dp->p_mem;
4032395Swnj 		if ((tp->t_state&TTSTOP)==0)
40417Sbill 			tp->t_state |= FLUSH;
40517Sbill 	}
40617Sbill 	splx(s);
40717Sbill }
40817Sbill 
4092395Swnj dzmodem(unit, flag)
4102395Swnj 	register int unit;
41117Sbill {
41217Sbill 	register struct device *dzaddr;
41317Sbill 	register char bit;
41417Sbill 
4152395Swnj 	dzaddr = dzpdma[unit].p_addr;
4162395Swnj 	bit = 1<<(unit&07);
4172469Swnj 	if (flag == DZ_OFF)
41817Sbill 		dzaddr->dzdtr &= ~bit;
41917Sbill 	else
42017Sbill 		dzaddr->dzdtr |= bit;
42117Sbill }
42217Sbill 
42317Sbill dzscan()
42417Sbill {
42517Sbill 	register i;
42617Sbill 	register struct device *dzaddr;
42717Sbill 	register bit;
42817Sbill 	register struct tty *tp;
42917Sbill 
43017Sbill 	for (i = 0; i < dz_cnt ; i++) {
43117Sbill 		dzaddr = dzpdma[i].p_addr;
43217Sbill 		tp = &dz_tty[i];
43317Sbill 		bit = 1<<(i&07);
434*2567Swnj 		if ((dzsoftCAR[i]&bit) || (dzaddr->dzmsr&bit)) {
43517Sbill 			/* carrier present */
43617Sbill 			if ((tp->t_state & CARR_ON) == 0) {
43717Sbill 				wakeup((caddr_t)&tp->t_rawq);
43817Sbill 				tp->t_state |= CARR_ON;
43917Sbill 			}
44017Sbill 		} else {
4412469Swnj 			if ((tp->t_state&CARR_ON) &&
4422469Swnj 			    (tp->t_local&LNOHANG)==0) {
44317Sbill 				/* carrier lost */
444882Sbill 				if (tp->t_state&ISOPEN) {
445170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
446205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
447170Sbill 					dzaddr->dzdtr &= ~bit;
448871Sbill 					flushtty(tp, FREAD|FWRITE);
449170Sbill 				}
450170Sbill 				tp->t_state &= ~CARR_ON;
45117Sbill 			}
45217Sbill 		}
45317Sbill 	}
45417Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
45517Sbill }
456119Sbill 
457119Sbill dztimer()
458119Sbill {
4592457Swnj 	int dz;
460119Sbill 
4612457Swnj 	for (dz = 0; dz < NDZ11; dz++)
4622457Swnj 		dzrint(dz);
463119Sbill }
464281Sbill 
465281Sbill /*
466281Sbill  * Reset state of driver if UBA reset was necessary.
467301Sbill  * Reset parameters and restart transmission on open lines.
468281Sbill  */
4692395Swnj dzreset(uban)
4702422Skre 	int uban;
471281Sbill {
4722395Swnj 	register int unit;
473281Sbill 	register struct tty *tp;
4742422Skre 	register struct uba_dinfo *ui;
4752422Skre 	int any = 0;
476281Sbill 
4772395Swnj 	for (unit = 0; unit < NDZ; unit++) {
4782422Skre 		ui = dzinfo[unit >> 3];
4792422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4802422Skre 			continue;
4812422Skre 		if (any == 0) {
4822422Skre 			printf(" dz");
4832422Skre 			any++;
4842422Skre 		}
4852395Swnj 		tp = &dz_tty[unit];
486281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4872395Swnj 			dzparam(unit);
4882469Swnj 			dzmodem(unit, DZ_ON);
489301Sbill 			tp->t_state &= ~BUSY;
490301Sbill 			dzstart(tp);
491281Sbill 		}
492281Sbill 	}
493281Sbill 	dztimer();
494281Sbill }
4951562Sbill #endif
496