xref: /csrg-svn/sys/vax/uba/dz.c (revision 2923)
1*2923Swnj /*	dz.c	4.20	03/06/81	*/
217Sbill 
31935Swnj #include "dz.h"
42645Swnj #if NDZ > 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  */
112731Swnj #include "bk.h"
1217Sbill #include "../h/param.h"
1317Sbill #include "../h/systm.h"
1417Sbill #include "../h/tty.h"
1517Sbill #include "../h/dir.h"
1617Sbill #include "../h/user.h"
1717Sbill #include "../h/map.h"
1817Sbill #include "../h/pte.h"
192395Swnj #include "../h/buf.h"
202567Swnj #include "../h/vm.h"
2117Sbill #include "../h/uba.h"
2217Sbill #include "../h/conf.h"
2317Sbill #include "../h/pdma.h"
24114Sbill #include "../h/bk.h"
25871Sbill #include "../h/file.h"
261786Sbill #include "../h/mx.h"
27145Sbill 
282469Swnj /*
292469Swnj  * Driver information for auto-configuration stuff.
302469Swnj  */
312606Swnj int	dzprobe(), dzattach(), dzrint();
322645Swnj struct	uba_dinfo *dzinfo[NDZ];
332395Swnj u_short	dzstd[] = { 0 };
342395Swnj struct	uba_driver dzdriver =
352606Swnj 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
362395Swnj 
372645Swnj #define	NDZLINE 	(NDZ*8)
3817Sbill 
392469Swnj /*
402469Swnj  * Registers and bits
412469Swnj  */
422469Swnj 
432469Swnj /* Bits in dzlpr */
442457Swnj #define	BITS7	020
452457Swnj #define	BITS8	030
462457Swnj #define	TWOSB	040
472457Swnj #define	PENABLE	0100
482457Swnj #define	OPAR	0200
4917Sbill 
502469Swnj /* Bits in dzrbuf */
512469Swnj #define	DZ_PE	010000
522469Swnj #define	DZ_FE	020000
532469Swnj #define	DZ_DO	040000
542469Swnj 
552469Swnj /* Bits in dzcsr */
562469Swnj #define	DZ_CLR	020		/* Reset dz */
572469Swnj #define	DZ_MSE	040		/* Master Scan Enable */
582469Swnj #define	DZ_RIE	0100		/* Receiver Interrupt Enable */
592469Swnj #define	DZ_SAE	010000		/* Silo Alarm Enable */
602469Swnj #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
612469Swnj #define	DZ_IEN	(DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE)
622469Swnj 
632469Swnj /* Flags for modem-control */
642469Swnj #define	DZ_ON	1
652469Swnj #define	DZ_OFF	0
6617Sbill 
672469Swnj int	dzstart(), dzxint(), dzdma();
68114Sbill int	ttrstrt();
692645Swnj struct	tty dz_tty[NDZLINE];
702645Swnj int	dz_cnt = { NDZLINE };
71119Sbill int	dzact;
7217Sbill 
7317Sbill struct device {
742469Swnj 	short	dzcsr;		/* control-status register */
752469Swnj 	short	dzrbuf;		/* receiver buffer */
762469Swnj #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
772469Swnj 	char	dztcr;		/* transmit control register */
782469Swnj 	char	dzdtr;		/* data terminal ready */
792469Swnj 	char	dztbuf;		/* transmit buffer */
802469Swnj 	char	dzbrk;		/* break control */
812469Swnj #define	dzmsr	dzbrk		/* modem status register */
8217Sbill };
832469Swnj /*
842469Swnj  * Software copy of dzbrk since it isn't readable
852469Swnj  */
862645Swnj char	dz_brk[NDZ];
872645Swnj char	dzsoftCAR[NDZ];
8817Sbill 
892469Swnj /*
902469Swnj  * The dz doesn't interrupt on carrier transitions, so
912469Swnj  * we have to use a timer to watch it.
922469Swnj  */
932469Swnj char	dz_timer;		/* timer started? */
942469Swnj 
952469Swnj /*
962469Swnj  * Pdma structures for fast output code
972469Swnj  */
982645Swnj struct	pdma dzpdma[NDZLINE];
992469Swnj 
1002395Swnj char	dz_speeds[] =
1012395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
10217Sbill 
1032606Swnj dzprobe(reg)
1042395Swnj 	caddr_t reg;
1052395Swnj {
1062457Swnj 	register int br, cvec;
1072457Swnj 	register struct device *dzaddr = (struct device *)reg;
1082395Swnj 
1092606Swnj #ifdef lint
1102606Swnj 	br = 0; br = cvec; cvec = br;
1112606Swnj #endif
1122469Swnj 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
1132422Skre 	dzaddr->dztcr = 1;		/* enable any line */
1142457Swnj 	DELAY(100000);
1152469Swnj 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
1162457Swnj 	if (cvec && cvec != 0x200)
1172457Swnj 		cvec -= 4;
1182457Swnj 	return (1);
1192395Swnj }
1202395Swnj 
1212606Swnj dzattach(ui)
1222395Swnj 	register struct uba_dinfo *ui;
1232395Swnj {
1242395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
1252395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
1262606Swnj 	register int cntr;
1272645Swnj 	extern dzscan();
1282395Swnj 
1292606Swnj 	for (cntr = 0; cntr < 8; cntr++) {
1302606Swnj 		pdp->p_addr = (struct device *)ui->ui_addr;
1312395Swnj 		pdp->p_arg = (int)tp;
1322395Swnj 		pdp->p_fcn = dzxint;
1332395Swnj 		pdp++, tp++;
1342395Swnj 	}
1352567Swnj 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
1362627Swnj 	if (dz_timer == 0) {
1372627Swnj 		dz_timer++;
1382756Swnj 		timeout(dzscan, (caddr_t)0, hz);
1392627Swnj 	}
1402395Swnj 	return (1);
1412395Swnj }
1422395Swnj 
14317Sbill /*ARGSUSED*/
1442395Swnj dzopen(dev, flag)
1452395Swnj 	dev_t dev;
14617Sbill {
14717Sbill 	register struct tty *tp;
1482395Swnj 	register int unit;
14917Sbill 
1502395Swnj 	unit = minor(dev);
1512395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
15217Sbill 		u.u_error = ENXIO;
15317Sbill 		return;
15417Sbill 	}
1552395Swnj 	tp = &dz_tty[unit];
1562395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
15717Sbill 	tp->t_oproc = dzstart;
15817Sbill 	tp->t_iproc = NULL;
15917Sbill 	tp->t_state |= WOPEN;
16017Sbill 	if ((tp->t_state & ISOPEN) == 0) {
16117Sbill 		ttychars(tp);
1622469Swnj 		tp->t_ospeed = tp->t_ispeed = B300;
16317Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
1642469Swnj 		/* tp->t_state |= HUPCLS; */
1652395Swnj 		dzparam(unit);
16617Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
16717Sbill 		u.u_error = EBUSY;
16817Sbill 		return;
16917Sbill 	}
1702469Swnj 	dzmodem(unit, DZ_ON);
171114Sbill 	(void) spl5();
17217Sbill 	while ((tp->t_state & CARR_ON) == 0) {
17317Sbill 		tp->t_state |= WOPEN;
17417Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
17517Sbill 	}
176114Sbill 	(void) spl0();
1772395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
17817Sbill }
17917Sbill 
1802395Swnj /*ARGSUSED*/
1812395Swnj dzclose(dev, flag)
1822395Swnj 	dev_t dev;
18317Sbill {
18417Sbill 	register struct tty *tp;
1852395Swnj 	register int unit;
1862395Swnj 	int dz;
18717Sbill 
1882395Swnj 	unit = minor(dev);
1892395Swnj 	dz = unit >> 3;
1902395Swnj 	tp = &dz_tty[unit];
19117Sbill 	(*linesw[tp->t_line].l_close)(tp);
1922197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1932395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
19417Sbill 	if (tp->t_state & HUPCLS)
1952469Swnj 		dzmodem(unit, DZ_OFF);
19617Sbill 	ttyclose(tp);
19717Sbill }
19817Sbill 
1992395Swnj dzread(dev)
2002395Swnj 	dev_t dev;
20117Sbill {
20217Sbill 	register struct tty *tp;
20317Sbill 
2042395Swnj 	tp = &dz_tty[minor(dev)];
20517Sbill 	(*linesw[tp->t_line].l_read)(tp);
20617Sbill }
20717Sbill 
2082395Swnj dzwrite(dev)
2092395Swnj 	dev_t dev;
21017Sbill {
21117Sbill 	register struct tty *tp;
21217Sbill 
2132395Swnj 	tp = &dz_tty[minor(dev)];
21417Sbill 	(*linesw[tp->t_line].l_write)(tp);
21517Sbill }
21617Sbill 
217119Sbill /*ARGSUSED*/
2182395Swnj dzrint(dz)
2192395Swnj 	int dz;
22017Sbill {
22117Sbill 	register struct tty *tp;
22217Sbill 	register int c;
22317Sbill 	register struct device *dzaddr;
224119Sbill 	register struct tty *tp0;
2252395Swnj 	register int unit;
226*2923Swnj 	int overrun = 0;
22717Sbill 
2282457Swnj 	if ((dzact & (1<<dz)) == 0)
2292457Swnj 		return;
2302457Swnj 	unit = dz * 8;
2312457Swnj 	dzaddr = dzpdma[unit].p_addr;
2322457Swnj 	tp0 = &dz_tty[unit];
2332457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
2342457Swnj 		tp = tp0 + ((c>>8)&07);
2352457Swnj 		if (tp >= &dz_tty[dz_cnt])
23617Sbill 			continue;
2372457Swnj 		if ((tp->t_state & ISOPEN) == 0) {
2382457Swnj 			wakeup((caddr_t)&tp->t_rawq);
2392457Swnj 			continue;
2402457Swnj 		}
2412469Swnj 		if (c&DZ_FE)
2422457Swnj 			if (tp->t_flags & RAW)
2432469Swnj 				c = 0;
2442457Swnj 			else
2452457Swnj 				c = tun.t_intrc;
246*2923Swnj 		if (c&DZ_DO && overrun == 0) {
247*2923Swnj 			printf("dz%d: silo overflow\n", dz);
248*2923Swnj 			overrun = 1;
249*2923Swnj 		}
2502469Swnj 		if (c&DZ_PE)
2512457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
2522457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
25317Sbill 				continue;
2542731Swnj #if NBK > 0
2552457Swnj 		if (tp->t_line == NETLDISC) {
2562457Swnj 			c &= 0177;
2572457Swnj 			BKINPUT(c, tp);
2582457Swnj 		} else
2592731Swnj #endif
2602457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
26117Sbill 	}
26217Sbill }
26317Sbill 
26417Sbill /*ARGSUSED*/
26517Sbill dzioctl(dev, cmd, addr, flag)
2662395Swnj 	dev_t dev;
2672395Swnj 	caddr_t addr;
26817Sbill {
26917Sbill 	register struct tty *tp;
2702395Swnj 	register int unit = minor(dev);
2712395Swnj 	register int dz = unit >> 3;
27217Sbill 
2732395Swnj 	tp = &dz_tty[unit];
274114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
275114Sbill 	if (cmd == 0)
276114Sbill 		return;
2771896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
27817Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2792395Swnj 			dzparam(unit);
280170Sbill 	} else switch(cmd) {
2812395Swnj 
282170Sbill 	case TIOCSBRK:
283882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2842395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
285170Sbill 		break;
286170Sbill 	case TIOCCBRK:
287882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2882395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
289170Sbill 		break;
290170Sbill 	case TIOCSDTR:
2912469Swnj 		dzmodem(unit, DZ_ON);
292170Sbill 		break;
293170Sbill 	case TIOCCDTR:
2942469Swnj 		dzmodem(unit, DZ_OFF);
295170Sbill 		break;
296170Sbill 	default:
29717Sbill 		u.u_error = ENOTTY;
298170Sbill 	}
29917Sbill }
30017Sbill 
3012395Swnj dzparam(unit)
3022395Swnj 	register int unit;
30317Sbill {
30417Sbill 	register struct tty *tp;
30517Sbill 	register struct device *dzaddr;
3062395Swnj 	register int lpr;
30717Sbill 
3082395Swnj 	tp = &dz_tty[unit];
3092395Swnj 	dzaddr = dzpdma[unit].p_addr;
31017Sbill 	dzaddr->dzcsr = DZ_IEN;
3112395Swnj 	dzact |= (1<<(unit>>3));
31217Sbill 	if (tp->t_ispeed == 0) {
3132469Swnj 		dzmodem(unit, DZ_OFF);		/* hang up line */
31417Sbill 		return;
31517Sbill 	}
3162395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3172296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
31817Sbill 		lpr |= BITS8;
31917Sbill 	else
32017Sbill 		lpr |= (BITS7|PENABLE);
32117Sbill 	if ((tp->t_flags & EVENP) == 0)
32217Sbill 		lpr |= OPAR;
3232469Swnj 	if (tp->t_ispeed == B110)
3242469Swnj 		lpr |= TWOSB;
32517Sbill 	dzaddr->dzlpr = lpr;
32617Sbill }
32717Sbill 
32817Sbill dzxint(tp)
3292395Swnj 	register struct tty *tp;
33017Sbill {
33117Sbill 	register struct pdma *dp;
332145Sbill 	register s;
33317Sbill 
3342469Swnj 	s = spl5();		/* block pdma interrupts */
3352395Swnj 	dp = (struct pdma *)tp->t_addr;
33617Sbill 	tp->t_state &= ~BUSY;
33717Sbill 	if (tp->t_state & FLUSH)
33817Sbill 		tp->t_state &= ~FLUSH;
33917Sbill 	else
340281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
34117Sbill 	if (tp->t_line)
34217Sbill 		(*linesw[tp->t_line].l_start)(tp);
34317Sbill 	else
34417Sbill 		dzstart(tp);
34517Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3462395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
347145Sbill 	splx(s);
34817Sbill }
34917Sbill 
35017Sbill dzstart(tp)
3512395Swnj 	register struct tty *tp;
35217Sbill {
35317Sbill 	register struct pdma *dp;
35417Sbill 	register struct device *dzaddr;
3552395Swnj 	register int cc;
3562395Swnj 	int s;
35717Sbill 
3582395Swnj 	dp = (struct pdma *)tp->t_addr;
35917Sbill 	dzaddr = dp->p_addr;
3602395Swnj 	s = spl5();
36117Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
36217Sbill 		goto out;
363921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
36417Sbill 		tp->t_state &= ~ASLEEP;
36517Sbill 		if (tp->t_chan)
36617Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
36717Sbill 		else
36817Sbill 			wakeup((caddr_t)&tp->t_outq);
36917Sbill 	}
37017Sbill 	if (tp->t_outq.c_cc == 0)
37117Sbill 		goto out;
37217Sbill 	if (tp->t_flags&RAW)
37317Sbill 		cc = ndqb(&tp->t_outq, 0);
37417Sbill 	else {
37517Sbill 		cc = ndqb(&tp->t_outq, 0200);
37617Sbill 		if (cc == 0) {
37717Sbill 			cc = getc(&tp->t_outq);
3782469Swnj 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
37917Sbill 			tp->t_state |= TIMEOUT;
38017Sbill 			goto out;
38117Sbill 		}
38217Sbill 	}
38317Sbill 	tp->t_state |= BUSY;
38417Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
38517Sbill 	dp->p_end += cc;
3862469Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
3872395Swnj out:
3882395Swnj 	splx(s);
38917Sbill }
39017Sbill 
39117Sbill /*
39217Sbill  * Stop output on a line.
39317Sbill  */
39417Sbill /*ARGSUSED*/
39517Sbill dzstop(tp, flag)
3962395Swnj 	register struct tty *tp;
39717Sbill {
39817Sbill 	register struct pdma *dp;
39917Sbill 	register int s;
40017Sbill 
4012395Swnj 	dp = (struct pdma *)tp->t_addr;
4022457Swnj 	s = spl5();
40317Sbill 	if (tp->t_state & BUSY) {
40417Sbill 		dp->p_end = dp->p_mem;
4052395Swnj 		if ((tp->t_state&TTSTOP)==0)
40617Sbill 			tp->t_state |= FLUSH;
40717Sbill 	}
40817Sbill 	splx(s);
40917Sbill }
41017Sbill 
4112395Swnj dzmodem(unit, flag)
4122395Swnj 	register int unit;
41317Sbill {
41417Sbill 	register struct device *dzaddr;
41517Sbill 	register char bit;
41617Sbill 
4172395Swnj 	dzaddr = dzpdma[unit].p_addr;
4182395Swnj 	bit = 1<<(unit&07);
4192469Swnj 	if (flag == DZ_OFF)
42017Sbill 		dzaddr->dzdtr &= ~bit;
42117Sbill 	else
42217Sbill 		dzaddr->dzdtr |= bit;
42317Sbill }
42417Sbill 
42517Sbill dzscan()
42617Sbill {
42717Sbill 	register i;
42817Sbill 	register struct device *dzaddr;
42917Sbill 	register bit;
43017Sbill 	register struct tty *tp;
43117Sbill 
43217Sbill 	for (i = 0; i < dz_cnt ; i++) {
43317Sbill 		dzaddr = dzpdma[i].p_addr;
4342627Swnj 		if (dzaddr == 0)
4352627Swnj 			continue;
43617Sbill 		tp = &dz_tty[i];
43717Sbill 		bit = 1<<(i&07);
4382606Swnj 		if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
43917Sbill 			/* carrier present */
44017Sbill 			if ((tp->t_state & CARR_ON) == 0) {
44117Sbill 				wakeup((caddr_t)&tp->t_rawq);
44217Sbill 				tp->t_state |= CARR_ON;
44317Sbill 			}
44417Sbill 		} else {
4452469Swnj 			if ((tp->t_state&CARR_ON) &&
4462469Swnj 			    (tp->t_local&LNOHANG)==0) {
44717Sbill 				/* carrier lost */
448882Sbill 				if (tp->t_state&ISOPEN) {
449170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
450205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
451170Sbill 					dzaddr->dzdtr &= ~bit;
452871Sbill 					flushtty(tp, FREAD|FWRITE);
453170Sbill 				}
454170Sbill 				tp->t_state &= ~CARR_ON;
45517Sbill 			}
45617Sbill 		}
45717Sbill 	}
4582756Swnj 	timeout(dzscan, (caddr_t)0, 2*hz);
45917Sbill }
460119Sbill 
461119Sbill dztimer()
462119Sbill {
4632457Swnj 	int dz;
464119Sbill 
4652645Swnj 	for (dz = 0; dz < NDZ; dz++)
4662457Swnj 		dzrint(dz);
467119Sbill }
468281Sbill 
469281Sbill /*
470281Sbill  * Reset state of driver if UBA reset was necessary.
471301Sbill  * Reset parameters and restart transmission on open lines.
472281Sbill  */
4732395Swnj dzreset(uban)
4742422Skre 	int uban;
475281Sbill {
4762395Swnj 	register int unit;
477281Sbill 	register struct tty *tp;
4782422Skre 	register struct uba_dinfo *ui;
479281Sbill 
4802645Swnj 	for (unit = 0; unit < NDZLINE; unit++) {
4812422Skre 		ui = dzinfo[unit >> 3];
4822422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4832422Skre 			continue;
484*2923Swnj 		if (unit%8 == 0)
485*2923Swnj 			printf(" dz%d", unit>>3);
4862395Swnj 		tp = &dz_tty[unit];
487281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4882395Swnj 			dzparam(unit);
4892469Swnj 			dzmodem(unit, DZ_ON);
490301Sbill 			tp->t_state &= ~BUSY;
491301Sbill 			dzstart(tp);
492281Sbill 		}
493281Sbill 	}
494281Sbill 	dztimer();
495281Sbill }
4961562Sbill #endif
497