xref: /csrg-svn/sys/vax/uba/dz.c (revision 2457)
1*2457Swnj /*	dz.c	4.12	02/16/81	*/
217Sbill 
31935Swnj #include "dz.h"
41562Sbill #if NDZ11 > 0
5*2457Swnj #define	DELAY(i)	{ register int j = i; while (--j > 0); }
617Sbill /*
717Sbill  *  DZ-11 Driver
817Sbill  */
917Sbill #include "../h/param.h"
1017Sbill #include "../h/systm.h"
1117Sbill #include "../h/tty.h"
1217Sbill #include "../h/dir.h"
1317Sbill #include "../h/user.h"
1417Sbill #include "../h/map.h"
1517Sbill #include "../h/pte.h"
162395Swnj #include "../h/buf.h"
1717Sbill #include "../h/uba.h"
1817Sbill #include "../h/conf.h"
1917Sbill #include "../h/pdma.h"
20114Sbill #include "../h/bk.h"
21871Sbill #include "../h/file.h"
221786Sbill #include "../h/mx.h"
23145Sbill 
242395Swnj int	dzcntrlr(), dzslave(), dzrint();
252395Swnj struct	uba_dinfo *dzinfo[NDZ11];
262395Swnj u_short	dzstd[] = { 0 };
272395Swnj struct	uba_driver dzdriver =
28*2457Swnj 	{ dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo };
292395Swnj 
30*2457Swnj #define	NDZ 	(NDZ11*8)
3117Sbill 
32*2457Swnj #define	BITS7	020
33*2457Swnj #define	BITS8	030
34*2457Swnj #define	TWOSB	040
35*2457Swnj #define	PENABLE	0100
36*2457Swnj #define	OPAR	0200
372422Skre #define	CLR	020		/* Reset dz */
38*2457Swnj #define	MSE	040		/* Master Scan Enable */
39*2457Swnj #define	RIE	0100		/* Receiver Interrupt Enable */
40119Sbill #define	SAE	010000		/* Silo Alarm Enable */
41*2457Swnj #define	TIE	040000		/* Transmit Interrupt Enable */
42*2457Swnj #define	DZ_IEN	(MSE+RIE+TIE+SAE)
43*2457Swnj #define	PERROR	010000
44*2457Swnj #define	FRERROR	020000
45119Sbill #define	OVERRUN	040000
46*2457Swnj #define	SSPEED	7		/* std speed = 300 baud */
4717Sbill 
4817Sbill #define	dzlpr	dzrbuf
49*2457Swnj #define	dzmsr	dzbrk
50*2457Swnj #define	ON	1
51*2457Swnj #define	OFF	0
5217Sbill 
5317Sbill int	dzstart();
5417Sbill int	dzxint();
552395Swnj int	dzdma();
56114Sbill int	ttrstrt();
5717Sbill struct	tty dz_tty[NDZ];
5817Sbill int	dz_cnt = { NDZ };
59119Sbill int	dzact;
6017Sbill 
6117Sbill struct device {
6217Sbill 	short	dzcsr;
6317Sbill 	short	dzrbuf;
6417Sbill 	char	dztcr;
6517Sbill 	char	dzdtr;
6617Sbill 	char	dztbuf;
6717Sbill 	char	dzbrk;
6817Sbill };
6917Sbill 
702395Swnj struct	pdma dzpdma[NDZ];
7117Sbill char	dz_timer;
722395Swnj char	dz_speeds[] =
732395Swnj 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
742395Swnj char	dz_brk[NDZ11];
7517Sbill 
762395Swnj dzcntrlr(ui, reg)
772395Swnj 	struct uba_dinfo *ui;
782395Swnj 	caddr_t reg;
792395Swnj {
80*2457Swnj 	register int br, cvec;
81*2457Swnj 	register struct device *dzaddr = (struct device *)reg;
822395Swnj 
832422Skre 	dzaddr->dzcsr = TIE|MSE;
842422Skre 	dzaddr->dztcr = 1;		/* enable any line */
85*2457Swnj 	DELAY(100000);
862422Skre 	dzaddr->dzcsr = CLR;		/* reset everything */
87*2457Swnj 	if (cvec && cvec != 0x200)
88*2457Swnj 		cvec -= 4;
89*2457Swnj 	return (1);
902395Swnj }
912395Swnj 
922395Swnj dzslave(ui, reg, slaveno, uban)
932395Swnj 	register struct uba_dinfo *ui;
942395Swnj 	caddr_t reg;
952395Swnj {
962395Swnj 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
972395Swnj 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
982395Swnj 	register int cnt;
992395Swnj 	caddr_t cp;
1002395Swnj 
1012395Swnj 	for (cnt = 0; cnt < 8; cnt++) {
1022395Swnj 		pdp->p_addr = (struct device *)reg;
1032395Swnj 		pdp->p_arg = (int)tp;
1042395Swnj 		pdp->p_fcn = dzxint;
1052395Swnj 		pdp++, tp++;
1062395Swnj 	}
1072395Swnj 	return (1);
1082395Swnj }
1092395Swnj 
11017Sbill /*ARGSUSED*/
1112395Swnj dzopen(dev, flag)
1122395Swnj 	dev_t dev;
11317Sbill {
11417Sbill 	register struct tty *tp;
1152395Swnj 	register int unit;
11617Sbill 	extern dzscan();
11717Sbill 
1182395Swnj 	unit = minor(dev);
1192395Swnj 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
12017Sbill 		u.u_error = ENXIO;
12117Sbill 		return;
12217Sbill 	}
12317Sbill 	if (dz_timer == 0) {
12417Sbill 		dz_timer++;
12517Sbill 		timeout(dzscan, (caddr_t)0, 60);
12617Sbill 	}
1272395Swnj 	tp = &dz_tty[unit];
1282395Swnj 	tp->t_addr = (caddr_t)&dzpdma[unit];
12917Sbill 	tp->t_oproc = dzstart;
13017Sbill 	tp->t_iproc = NULL;
13117Sbill 	tp->t_state |= WOPEN;
13217Sbill 	if ((tp->t_state & ISOPEN) == 0) {
13317Sbill 		ttychars(tp);
13417Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
13517Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
13617Sbill 		/*tp->t_state |= HUPCLS;*/
1372395Swnj 		dzparam(unit);
13817Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
13917Sbill 		u.u_error = EBUSY;
14017Sbill 		return;
14117Sbill 	}
1422395Swnj 	dzmodem(unit, ON);
143114Sbill 	(void) spl5();
14417Sbill 	while ((tp->t_state & CARR_ON) == 0) {
14517Sbill 		tp->t_state |= WOPEN;
14617Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
14717Sbill 	}
148114Sbill 	(void) spl0();
1492395Swnj 	(*linesw[tp->t_line].l_open)(dev, tp);
15017Sbill }
15117Sbill 
1522395Swnj /*ARGSUSED*/
1532395Swnj dzclose(dev, flag)
1542395Swnj 	dev_t dev;
15517Sbill {
15617Sbill 	register struct tty *tp;
1572395Swnj 	register int unit;
1582395Swnj 	int dz;
15917Sbill 
1602395Swnj 	unit = minor(dev);
1612395Swnj 	dz = unit >> 3;
1622395Swnj 	tp = &dz_tty[unit];
16317Sbill 	(*linesw[tp->t_line].l_close)(tp);
1642197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
1652395Swnj 	    (dz_brk[dz] &= ~(1 << (unit&07)));
16617Sbill 	if (tp->t_state & HUPCLS)
1672395Swnj 		dzmodem(unit, OFF);
16817Sbill 	ttyclose(tp);
16917Sbill }
17017Sbill 
1712395Swnj dzread(dev)
1722395Swnj 	dev_t dev;
17317Sbill {
17417Sbill 	register struct tty *tp;
17517Sbill 
1762395Swnj 	tp = &dz_tty[minor(dev)];
17717Sbill 	(*linesw[tp->t_line].l_read)(tp);
17817Sbill }
17917Sbill 
1802395Swnj dzwrite(dev)
1812395Swnj 	dev_t dev;
18217Sbill {
18317Sbill 	register struct tty *tp;
18417Sbill 
1852395Swnj 	tp = &dz_tty[minor(dev)];
18617Sbill 	(*linesw[tp->t_line].l_write)(tp);
18717Sbill }
18817Sbill 
189119Sbill /*ARGSUSED*/
1902395Swnj dzrint(dz)
1912395Swnj 	int dz;
19217Sbill {
19317Sbill 	register struct tty *tp;
19417Sbill 	register int c;
19517Sbill 	register struct device *dzaddr;
196119Sbill 	register struct tty *tp0;
1972395Swnj 	register int unit;
198140Sbill 	int s;
19917Sbill 
200*2457Swnj 	if ((dzact & (1<<dz)) == 0)
201*2457Swnj 		return;
202*2457Swnj 	unit = dz * 8;
203*2457Swnj 	dzaddr = dzpdma[unit].p_addr;
204*2457Swnj 	tp0 = &dz_tty[unit];
205*2457Swnj 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
206*2457Swnj 		tp = tp0 + ((c>>8)&07);
207*2457Swnj 		if (tp >= &dz_tty[dz_cnt])
20817Sbill 			continue;
209*2457Swnj 		if ((tp->t_state & ISOPEN) == 0) {
210*2457Swnj 			wakeup((caddr_t)&tp->t_rawq);
211*2457Swnj 			continue;
212*2457Swnj 		}
213*2457Swnj 		if (c&FRERROR)
214*2457Swnj 			/* framing error = break */
215*2457Swnj 			if (tp->t_flags & RAW)
216*2457Swnj 				c = 0;		/* null for getty */
217*2457Swnj 			else
218*2457Swnj 				c = tun.t_intrc;
219*2457Swnj 		if (c&OVERRUN)
220*2457Swnj 			printf("o");
221*2457Swnj 		if (c&PERROR)
222*2457Swnj 			/* parity error */
223*2457Swnj 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
224*2457Swnj 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
22517Sbill 				continue;
226*2457Swnj 		if (tp->t_line == NETLDISC) {
227*2457Swnj 			c &= 0177;
228*2457Swnj 			BKINPUT(c, tp);
229*2457Swnj 		} else
230*2457Swnj 			(*linesw[tp->t_line].l_rint)(c, tp);
23117Sbill 	}
23217Sbill }
23317Sbill 
23417Sbill /*ARGSUSED*/
23517Sbill dzioctl(dev, cmd, addr, flag)
2362395Swnj 	dev_t dev;
2372395Swnj 	caddr_t addr;
23817Sbill {
23917Sbill 	register struct tty *tp;
2402395Swnj 	register int unit = minor(dev);
2412395Swnj 	register int dz = unit >> 3;
24217Sbill 
2432395Swnj 	tp = &dz_tty[unit];
244114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
245114Sbill 	if (cmd == 0)
246114Sbill 		return;
2471896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
24817Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
2492395Swnj 			dzparam(unit);
250170Sbill 	} else switch(cmd) {
2512395Swnj 
252170Sbill 	case TIOCSBRK:
253882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2542395Swnj 			(dz_brk[dz] |= 1 << (unit&07));
255170Sbill 		break;
256170Sbill 	case TIOCCBRK:
257882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
2582395Swnj 			(dz_brk[dz] &= ~(1 << (unit&07)));
259170Sbill 		break;
260170Sbill 	case TIOCSDTR:
2612395Swnj 		dzmodem(unit, ON);
262170Sbill 		break;
263170Sbill 	case TIOCCDTR:
2642395Swnj 		dzmodem(unit, OFF);
265170Sbill 		break;
266170Sbill 	default:
26717Sbill 		u.u_error = ENOTTY;
268170Sbill 	}
26917Sbill }
27017Sbill 
2712395Swnj dzparam(unit)
2722395Swnj 	register int unit;
27317Sbill {
27417Sbill 	register struct tty *tp;
27517Sbill 	register struct device *dzaddr;
2762395Swnj 	register int lpr;
27717Sbill 
2782395Swnj 	tp = &dz_tty[unit];
2792395Swnj 	dzaddr = dzpdma[unit].p_addr;
28017Sbill 	dzaddr->dzcsr = DZ_IEN;
2812395Swnj 	dzact |= (1<<(unit>>3));
28217Sbill 	if (tp->t_ispeed == 0) {
2832395Swnj 		dzmodem(unit, OFF);		/* hang up line */
28417Sbill 		return;
28517Sbill 	}
2862395Swnj 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
2872296Swnj 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
28817Sbill 		lpr |= BITS8;
28917Sbill 	else
29017Sbill 		lpr |= (BITS7|PENABLE);
29117Sbill 	if ((tp->t_flags & EVENP) == 0)
29217Sbill 		lpr |= OPAR;
29317Sbill 	if (tp->t_ispeed == 3)
29417Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
29517Sbill 	dzaddr->dzlpr = lpr;
29617Sbill }
29717Sbill 
29817Sbill dzxint(tp)
2992395Swnj 	register struct tty *tp;
30017Sbill {
30117Sbill 	register struct pdma *dp;
302145Sbill 	register s;
30317Sbill 
304*2457Swnj 	s = spl5();
3052395Swnj 	dp = (struct pdma *)tp->t_addr;
30617Sbill 	tp->t_state &= ~BUSY;
30717Sbill 	if (tp->t_state & FLUSH)
30817Sbill 		tp->t_state &= ~FLUSH;
30917Sbill 	else
310281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
31117Sbill 	if (tp->t_line)
31217Sbill 		(*linesw[tp->t_line].l_start)(tp);
31317Sbill 	else
31417Sbill 		dzstart(tp);
31517Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3162395Swnj 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
317145Sbill 	splx(s);
31817Sbill }
31917Sbill 
32017Sbill dzstart(tp)
3212395Swnj 	register struct tty *tp;
32217Sbill {
32317Sbill 	register struct pdma *dp;
32417Sbill 	register struct device *dzaddr;
3252395Swnj 	register int cc;
3262395Swnj 	int s;
32717Sbill 
3282395Swnj 	dp = (struct pdma *)tp->t_addr;
32917Sbill 	dzaddr = dp->p_addr;
3302395Swnj 	s = spl5();
33117Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
33217Sbill 		goto out;
333921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
33417Sbill 		tp->t_state &= ~ASLEEP;
33517Sbill 		if (tp->t_chan)
33617Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
33717Sbill 		else
33817Sbill 			wakeup((caddr_t)&tp->t_outq);
33917Sbill 	}
34017Sbill 	if (tp->t_outq.c_cc == 0)
34117Sbill 		goto out;
34217Sbill 	if (tp->t_flags&RAW)
34317Sbill 		cc = ndqb(&tp->t_outq, 0);
34417Sbill 	else {
34517Sbill 		cc = ndqb(&tp->t_outq, 0200);
34617Sbill 		if (cc == 0) {
34717Sbill 			cc = getc(&tp->t_outq);
34817Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
34917Sbill 			tp->t_state |= TIMEOUT;
35017Sbill 			goto out;
35117Sbill 		}
35217Sbill 	}
35317Sbill 	tp->t_state |= BUSY;
35417Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
35517Sbill 	dp->p_end += cc;
3562395Swnj 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);
3572395Swnj out:
3582395Swnj 	splx(s);
35917Sbill }
36017Sbill 
36117Sbill /*
36217Sbill  * Stop output on a line.
36317Sbill  */
36417Sbill /*ARGSUSED*/
36517Sbill dzstop(tp, flag)
3662395Swnj 	register struct tty *tp;
36717Sbill {
36817Sbill 	register struct pdma *dp;
36917Sbill 	register int s;
37017Sbill 
3712395Swnj 	dp = (struct pdma *)tp->t_addr;
372*2457Swnj 	s = spl5();
37317Sbill 	if (tp->t_state & BUSY) {
37417Sbill 		dp->p_end = dp->p_mem;
3752395Swnj 		if ((tp->t_state&TTSTOP)==0)
37617Sbill 			tp->t_state |= FLUSH;
37717Sbill 	}
37817Sbill 	splx(s);
37917Sbill }
38017Sbill 
3812395Swnj dzmodem(unit, flag)
3822395Swnj 	register int unit;
38317Sbill {
38417Sbill 	register struct device *dzaddr;
38517Sbill 	register char bit;
38617Sbill 
3872395Swnj 	dzaddr = dzpdma[unit].p_addr;
3882395Swnj 	bit = 1<<(unit&07);
38917Sbill 	if (flag == OFF)
39017Sbill 		dzaddr->dzdtr &= ~bit;
39117Sbill 	else
39217Sbill 		dzaddr->dzdtr |= bit;
39317Sbill }
39417Sbill 
39517Sbill dzscan()
39617Sbill {
39717Sbill 	register i;
39817Sbill 	register struct device *dzaddr;
39917Sbill 	register bit;
40017Sbill 	register struct tty *tp;
40117Sbill 
40217Sbill 	for (i = 0; i < dz_cnt ; i++) {
40317Sbill 		dzaddr = dzpdma[i].p_addr;
40417Sbill 		tp = &dz_tty[i];
40517Sbill 		bit = 1<<(i&07);
4062422Skre #ifdef BERT
4072422Skre 		if (dzaddr->dzmsr & bit || i == 6 || i == 7) {
4082422Skre #else
4092422Skre 		if (dzaddr->dzmsr & bit) {
4102422Skre #endif
41117Sbill 			/* carrier present */
41217Sbill 			if ((tp->t_state & CARR_ON) == 0) {
41317Sbill 				wakeup((caddr_t)&tp->t_rawq);
41417Sbill 				tp->t_state |= CARR_ON;
41517Sbill 			}
41617Sbill 		} else {
4172395Swnj 			if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) {
41817Sbill 				/* carrier lost */
419882Sbill 				if (tp->t_state&ISOPEN) {
420170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
421205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
422170Sbill 					dzaddr->dzdtr &= ~bit;
423871Sbill 					flushtty(tp, FREAD|FWRITE);
424170Sbill 				}
425170Sbill 				tp->t_state &= ~CARR_ON;
42617Sbill 			}
42717Sbill 		}
42817Sbill 	}
42917Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
43017Sbill }
431119Sbill 
432119Sbill dztimer()
433119Sbill {
434*2457Swnj 	int dz;
435119Sbill 
436*2457Swnj 	for (dz = 0; dz < NDZ11; dz++)
437*2457Swnj 		dzrint(dz);
438119Sbill }
439281Sbill 
440281Sbill /*
441281Sbill  * Reset state of driver if UBA reset was necessary.
442301Sbill  * Reset parameters and restart transmission on open lines.
443281Sbill  */
4442395Swnj dzreset(uban)
4452422Skre 	int uban;
446281Sbill {
4472395Swnj 	register int unit;
448281Sbill 	register struct tty *tp;
4492422Skre 	register struct uba_dinfo *ui;
4502422Skre 	int any = 0;
451281Sbill 
4522395Swnj 	for (unit = 0; unit < NDZ; unit++) {
4532422Skre 		ui = dzinfo[unit >> 3];
4542422Skre 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
4552422Skre 			continue;
4562422Skre 		if (any == 0) {
4572422Skre 			printf(" dz");
4582422Skre 			any++;
4592422Skre 		}
4602395Swnj 		tp = &dz_tty[unit];
461281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
4622395Swnj 			dzparam(unit);
4632395Swnj 			dzmodem(unit, ON);
464301Sbill 			tp->t_state &= ~BUSY;
465301Sbill 			dzstart(tp);
466281Sbill 		}
467281Sbill 	}
468281Sbill 	dztimer();
469281Sbill }
4701562Sbill #endif
471