xref: /csrg-svn/sys/vax/uba/dz.c (revision 3819)
1*3819Swnj /*	dz.c	4.26	81/05/29	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 0
517Sbill /*
617Sbill  *  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"
251786Sbill #include "../h/mx.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 
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 */
603440Sroot #if NBK == 0
613440Sroot #define	DZ_IEN	(DZ_MSE|DZ_RIE|DZ_TIE)
623440Sroot #else
633440Sroot #define	DZ_IEN	(DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
643440Sroot #endif
652469Swnj 
662469Swnj /* Flags for modem-control */
672469Swnj #define	DZ_ON	1
682469Swnj #define	DZ_OFF	0
6917Sbill 
702469Swnj int	dzstart(), dzxint(), dzdma();
71114Sbill int	ttrstrt();
722645Swnj struct	tty dz_tty[NDZLINE];
732645Swnj int	dz_cnt = { NDZLINE };
74119Sbill int	dzact;
7517Sbill 
7617Sbill struct device {
772469Swnj 	short	dzcsr;		/* control-status register */
782469Swnj 	short	dzrbuf;		/* receiver buffer */
792469Swnj #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
802469Swnj 	char	dztcr;		/* transmit control register */
812469Swnj 	char	dzdtr;		/* data terminal ready */
822469Swnj 	char	dztbuf;		/* transmit buffer */
832469Swnj 	char	dzbrk;		/* break control */
842469Swnj #define	dzmsr	dzbrk		/* modem status register */
8517Sbill };
862469Swnj /*
872469Swnj  * Software copy of dzbrk since it isn't readable
882469Swnj  */
892645Swnj char	dz_brk[NDZ];
902645Swnj char	dzsoftCAR[NDZ];
9117Sbill 
922469Swnj /*
932469Swnj  * The dz doesn't interrupt on carrier transitions, so
942469Swnj  * we have to use a timer to watch it.
952469Swnj  */
962469Swnj char	dz_timer;		/* timer started? */
972469Swnj 
982469Swnj /*
992469Swnj  * Pdma structures for fast output code
1002469Swnj  */
1012645Swnj struct	pdma dzpdma[NDZLINE];
1022469Swnj 
1032395Swnj char	dz_speeds[] =
1042395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
10517Sbill 
1062606Swnj dzprobe(reg)
1072395Swnj 	caddr_t reg;
1082395Swnj {
1092457Swnj 	register int br, cvec;
1102457Swnj 	register struct device *dzaddr = (struct device *)reg;
1112395Swnj 
1122606Swnj #ifdef lint
1133102Swnj 	br = 0; cvec = br; br = cvec;
1142606Swnj #endif
1152469Swnj 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
1162422Skre 	dzaddr->dztcr = 1;		/* enable any line */
1172457Swnj 	DELAY(100000);
1182469Swnj 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
1192457Swnj 	if (cvec && cvec != 0x200)
1202457Swnj 		cvec -= 4;
1212457Swnj 	return (1);
1222395Swnj }
1232395Swnj 
1242606Swnj dzattach(ui)
1252976Swnj 	register struct uba_device *ui;
1262395Swnj {
1272395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1282395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1292606Swnj 	register int cntr;
1302645Swnj 	extern dzscan();
1312395Swnj 
1322606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1332606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1342395Swnj 		pdp->p_arg = (int)tp;
1352395Swnj 		pdp->p_fcn = dzxint;
1362395Swnj 		pdp++, tp++;
1372395Swnj 	}
1382567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1392627Swnj 	if (dz_timer == 0) {
1402627Swnj 		dz_timer++;
1412756Swnj 		timeout(dzscan, (caddr_t)0, hz);
1422627Swnj 	}
1432395Swnj 	return (1);
1442395Swnj }
1452395Swnj 
14617Sbill /*ARGSUSED*/
1472395Swnj dzopen(dev, flag)
1482395Swnj 	dev_t dev;
14917Sbill {
15017Sbill 	register struct tty *tp;
1512395Swnj 	register int unit;
15217Sbill 
1532395Swnj 	unit = minor(dev);
1542395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
15517Sbill 		u.u_error = ENXIO;
15617Sbill 		return;
15717Sbill 	}
1582395Swnj 	tp = &dz_tty[unit];
1592395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
16017Sbill 	tp->t_oproc = dzstart;
16117Sbill 	tp->t_iproc = NULL;
16217Sbill 	tp->t_state |= WOPEN;
16317Sbill 	if ((tp->t_state & ISOPEN) == 0) {
16417Sbill 		ttychars(tp);
1652469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
16617Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
1672469Swnj 		/* tp->t_state |= HUPCLS; */
1682395Swnj 		dzparam(unit);
16917Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
17017Sbill 		u.u_error = EBUSY;
17117Sbill 		return;
17217Sbill 	}
1732469Swnj 	dzmodem(unit, DZ_ON);
174114Sbill 	(void) spl5();
17517Sbill 	while ((tp->t_state & CARR_ON) == 0) {
17617Sbill 		tp->t_state |= WOPEN;
17717Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17817Sbill 	}
179114Sbill 	(void) spl0();
1802395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
18117Sbill }
18217Sbill 
1832395Swnj /*ARGSUSED*/
1842395Swnj dzclose(dev, flag)
1852395Swnj 	dev_t dev;
18617Sbill {
18717Sbill 	register struct tty *tp;
1882395Swnj 	register int unit;
1892395Swnj 	int dz;
19017Sbill 
1912395Swnj 	unit = minor(dev);
1922395Swnj 	dz = unit >> 3;
1932395Swnj 	tp = &dz_tty[unit];
19417Sbill 	(*linesw[tp->t_line].l_close)(tp);
1952197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1962395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
19717Sbill 	if (tp->t_state & HUPCLS)
1982469Swnj 		dzmodem(unit, DZ_OFF);
19917Sbill 	ttyclose(tp);
20017Sbill }
20117Sbill 
2022395Swnj dzread(dev)
2032395Swnj 	dev_t dev;
20417Sbill {
20517Sbill 	register struct tty *tp;
20617Sbill 
2072395Swnj 	tp = &dz_tty[minor(dev)];
20817Sbill 	(*linesw[tp->t_line].l_read)(tp);
20917Sbill }
21017Sbill 
2112395Swnj dzwrite(dev)
2122395Swnj 	dev_t dev;
21317Sbill {
21417Sbill 	register struct tty *tp;
21517Sbill 
2162395Swnj 	tp = &dz_tty[minor(dev)];
21717Sbill 	(*linesw[tp->t_line].l_write)(tp);
21817Sbill }
21917Sbill 
220119Sbill /*ARGSUSED*/
2212395Swnj dzrint(dz)
2222395Swnj 	int dz;
22317Sbill {
22417Sbill 	register struct tty *tp;
22517Sbill 	register int c;
22617Sbill 	register struct device *dzaddr;
227119Sbill 	register struct tty *tp0;
2282395Swnj 	register int unit;
2292923Swnj 	int overrun = 0;
23017Sbill 
2312457Swnj 	if ((dzact & (1<<dz)) == 0)
2322457Swnj 		return;
2332457Swnj 	unit = dz * 8;
2342457Swnj 	dzaddr = dzpdma[unit].p_addr;
2352457Swnj 	tp0 = &dz_tty[unit];
2362457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
2372457Swnj 		tp = tp0 + ((c>>8)&07);
2382457Swnj 		if (tp >= &dz_tty[dz_cnt])
23917Sbill 			continue;
2402457Swnj 		if ((tp->t_state & ISOPEN) == 0) {
2412457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2422457Swnj 			continue;
2432457Swnj 		}
2442469Swnj 		if (c&DZ_FE)
2452457Swnj 			if (tp->t_flags & RAW)
2462469Swnj 				c = 0;
2472457Swnj 			else
2482457Swnj 				c = tun.t_intrc;
2492923Swnj 		if (c&DZ_DO && overrun == 0) {
2502923Swnj 			printf("dz%d: silo overflow\n", dz);
2512923Swnj 			overrun = 1;
2522923Swnj 		}
2532469Swnj 		if (c&DZ_PE)
2542457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2552457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
25617Sbill 				continue;
2572731Swnj #if NBK > 0
2582457Swnj 		if (tp->t_line == NETLDISC) {
2592457Swnj 			c &= 0177;
2602457Swnj 			BKINPUT(c, tp);
2612457Swnj 		} else
2622731Swnj #endif
2632457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
26417Sbill 	}
26517Sbill }
26617Sbill 
26717Sbill /*ARGSUSED*/
26817Sbill dzioctl(dev, cmd, addr, flag)
2692395Swnj 	dev_t dev;
2702395Swnj 	caddr_t addr;
27117Sbill {
27217Sbill 	register struct tty *tp;
2732395Swnj 	register int unit = minor(dev);
2742395Swnj 	register int dz = unit >> 3;
27517Sbill 
2762395Swnj 	tp = &dz_tty[unit];
277114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
278114Sbill 	if (cmd == 0)
279114Sbill 		return;
2801896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
28117Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2822395Swnj 			dzparam(unit);
283170Sbill 	} else switch(cmd) {
2842395Swnj 
285170Sbill 	case TIOCSBRK:
286882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2872395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
288170Sbill 		break;
289170Sbill 	case TIOCCBRK:
290882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2912395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
292170Sbill 		break;
293170Sbill 	case TIOCSDTR:
2942469Swnj 		dzmodem(unit, DZ_ON);
295170Sbill 		break;
296170Sbill 	case TIOCCDTR:
2972469Swnj 		dzmodem(unit, DZ_OFF);
298170Sbill 		break;
299170Sbill 	default:
30017Sbill 		u.u_error = ENOTTY;
301170Sbill 	}
30217Sbill }
30317Sbill 
3042395Swnj dzparam(unit)
3052395Swnj 	register int unit;
30617Sbill {
30717Sbill 	register struct tty *tp;
30817Sbill 	register struct device *dzaddr;
3092395Swnj 	register int lpr;
31017Sbill 
3112395Swnj 	tp = &dz_tty[unit];
3122395Swnj 	dzaddr = dzpdma[unit].p_addr;
31317Sbill 	dzaddr->dzcsr = DZ_IEN;
3142395Swnj 	dzact |= (1<<(unit>>3));
31517Sbill 	if (tp->t_ispeed == 0) {
3162469Swnj 		dzmodem(unit, DZ_OFF);		/* hang up line */
31717Sbill 		return;
31817Sbill 	}
3192395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3202296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
32117Sbill 		lpr |= BITS8;
32217Sbill 	else
32317Sbill 		lpr |= (BITS7|PENABLE);
32417Sbill 	if ((tp->t_flags & EVENP) == 0)
32517Sbill 		lpr |= OPAR;
3262469Swnj 	if (tp->t_ispeed == B110)
3272469Swnj 		lpr |= TWOSB;
32817Sbill 	dzaddr->dzlpr = lpr;
32917Sbill }
33017Sbill 
33117Sbill dzxint(tp)
3322395Swnj 	register struct tty *tp;
33317Sbill {
33417Sbill 	register struct pdma *dp;
335145Sbill 	register s;
33617Sbill 
3372469Swnj 	s = spl5();		/* block pdma interrupts */
3382395Swnj 	dp = (struct pdma *)tp->t_addr;
33917Sbill 	tp->t_state &= ~BUSY;
34017Sbill 	if (tp->t_state & FLUSH)
34117Sbill 		tp->t_state &= ~FLUSH;
34217Sbill 	else
343281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
34417Sbill 	if (tp->t_line)
34517Sbill 		(*linesw[tp->t_line].l_start)(tp);
34617Sbill 	else
34717Sbill 		dzstart(tp);
34817Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3492395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
350145Sbill 	splx(s);
35117Sbill }
35217Sbill 
35317Sbill dzstart(tp)
3542395Swnj 	register struct tty *tp;
35517Sbill {
35617Sbill 	register struct pdma *dp;
35717Sbill 	register struct device *dzaddr;
3582395Swnj 	register int cc;
3592395Swnj 	int s;
36017Sbill 
3612395Swnj 	dp = (struct pdma *)tp->t_addr;
36217Sbill 	dzaddr = dp->p_addr;
3632395Swnj 	s = spl5();
36417Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
36517Sbill 		goto out;
366921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
36717Sbill 		tp->t_state &= ~ASLEEP;
36817Sbill 		if (tp->t_chan)
36917Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
37017Sbill 		else
37117Sbill 			wakeup((caddr_t)&tp->t_outq);
37217Sbill 	}
37317Sbill 	if (tp->t_outq.c_cc == 0)
37417Sbill 		goto out;
375*3819Swnj 	if (tp->t_flags&RAW || tp->t_local&LLITOUT)
37617Sbill 		cc = ndqb(&tp->t_outq, 0);
37717Sbill 	else {
37817Sbill 		cc = ndqb(&tp->t_outq, 0200);
37917Sbill 		if (cc == 0) {
38017Sbill 			cc = getc(&tp->t_outq);
3812469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
38217Sbill 			tp->t_state |= TIMEOUT;
38317Sbill 			goto out;
38417Sbill 		}
38517Sbill 	}
38617Sbill 	tp->t_state |= BUSY;
38717Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
38817Sbill 	dp->p_end += cc;
3892469Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
3902395Swnj out:
3912395Swnj 	splx(s);
39217Sbill }
39317Sbill 
39417Sbill /*
39517Sbill  * Stop output on a line.
39617Sbill  */
39717Sbill /*ARGSUSED*/
39817Sbill dzstop(tp, flag)
3992395Swnj 	register struct tty *tp;
40017Sbill {
40117Sbill 	register struct pdma *dp;
40217Sbill 	register int s;
40317Sbill 
4042395Swnj 	dp = (struct pdma *)tp->t_addr;
4052457Swnj 	s = spl5();
40617Sbill 	if (tp->t_state & BUSY) {
40717Sbill 		dp->p_end = dp->p_mem;
4082395Swnj 		if ((tp->t_state&TTSTOP)==0)
40917Sbill 			tp->t_state |= FLUSH;
41017Sbill 	}
41117Sbill 	splx(s);
41217Sbill }
41317Sbill 
4142395Swnj dzmodem(unit, flag)
4152395Swnj 	register int unit;
41617Sbill {
41717Sbill 	register struct device *dzaddr;
41817Sbill 	register char bit;
41917Sbill 
4202395Swnj 	dzaddr = dzpdma[unit].p_addr;
4212395Swnj 	bit = 1<<(unit&07);
4222469Swnj 	if (flag == DZ_OFF)
42317Sbill 		dzaddr->dzdtr &= ~bit;
42417Sbill 	else
42517Sbill 		dzaddr->dzdtr |= bit;
42617Sbill }
42717Sbill 
42817Sbill dzscan()
42917Sbill {
43017Sbill 	register i;
43117Sbill 	register struct device *dzaddr;
43217Sbill 	register bit;
43317Sbill 	register struct tty *tp;
43417Sbill 
43517Sbill 	for (i = 0; i < dz_cnt ; i++) {
43617Sbill 		dzaddr = dzpdma[i].p_addr;
4372627Swnj 		if (dzaddr == 0)
4382627Swnj 			continue;
43917Sbill 		tp = &dz_tty[i];
44017Sbill 		bit = 1<<(i&07);
4412606Swnj 		if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
44217Sbill 			/* carrier present */
44317Sbill 			if ((tp->t_state & CARR_ON) == 0) {
44417Sbill 				wakeup((caddr_t)&tp->t_rawq);
44517Sbill 				tp->t_state |= CARR_ON;
44617Sbill 			}
44717Sbill 		} else {
4482469Swnj 			if ((tp->t_state&CARR_ON) &&
4492469Swnj 			    (tp->t_local&LNOHANG)==0) {
45017Sbill 				/* carrier lost */
451882Sbill 				if (tp->t_state&ISOPEN) {
452170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
453205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
454170Sbill 					dzaddr->dzdtr &= ~bit;
455871Sbill 					flushtty(tp, FREAD|FWRITE);
456170Sbill 				}
457170Sbill 				tp->t_state &= ~CARR_ON;
45817Sbill 			}
45917Sbill 		}
46017Sbill 	}
4612756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
46217Sbill }
463119Sbill 
464119Sbill dztimer()
465119Sbill {
4662457Swnj 	int dz;
467119Sbill 
4682645Swnj 	for (dz = 0; dz < NDZ; dz++)
4692457Swnj 		dzrint(dz);
470119Sbill }
471281Sbill 
472281Sbill /*
473281Sbill  * Reset state of driver if UBA reset was necessary.
474301Sbill  * Reset parameters and restart transmission on open lines.
475281Sbill  */
4762395Swnj dzreset(uban)
4772422Skre 	int uban;
478281Sbill {
4792395Swnj 	register int unit;
480281Sbill 	register struct tty *tp;
4812976Swnj 	register struct uba_device *ui;
482281Sbill 
4832645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
4842422Skre 		ui = dzinfo[unit >> 3];
4852422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4862422Skre 			continue;
4872923Swnj 		if (unit%8 == 0)
4882923Swnj 			printf(" dz%d", unit>>3);
4892395Swnj 		tp = &dz_tty[unit];
490281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4912395Swnj 			dzparam(unit);
4922469Swnj 			dzmodem(unit, DZ_ON);
493301Sbill 			tp->t_state &= ~BUSY;
494301Sbill 			dzstart(tp);
495281Sbill 		}
496281Sbill 	}
497281Sbill 	dztimer();
498281Sbill }
4991562Sbill #endif
500