xref: /csrg-svn/sys/vax/uba/dz.c (revision 2197)
1*2197Stoy /*	dz.c	4.6	01/19/81	*/
217Sbill 
31935Swnj #include "dz.h"
41562Sbill #if NDZ11 > 0
517Sbill /*
617Sbill  *  DZ-11 Driver
717Sbill  */
817Sbill #include "../h/param.h"
917Sbill #include "../h/systm.h"
1017Sbill #include "../h/tty.h"
1117Sbill #include "../h/dir.h"
1217Sbill #include "../h/user.h"
1317Sbill #include "../h/map.h"
1417Sbill #include "../h/pte.h"
1517Sbill #include "../h/uba.h"
1617Sbill #include "../h/conf.h"
1717Sbill #include "../h/pdma.h"
18114Sbill #include "../h/bk.h"
19871Sbill #include "../h/file.h"
201786Sbill #include "../h/mx.h"
21145Sbill 
22145Sbill /*
23145Sbill  * When running dz's using only SAE (silo alarm) on input
24145Sbill  * it is necessary to call dzrint() at clock interrupt time.
25145Sbill  * This is unsafe unless spl5()s in tty code are changed to
26145Sbill  * spl6()s to block clock interrupts.  Note that the dh driver
27145Sbill  * currently in use works the same way as the dz, even though
28145Sbill  * we could try to more intelligently manage its silo.
29145Sbill  * Thus don't take this out if you have no dz's unless you
30145Sbill  * change clock.c and dhtimer().
31145Sbill  */
32145Sbill #define	spl5	spl6
3317Sbill 
34882Sbill #define NDZ 	(NDZ11*8)
3517Sbill 
3617Sbill #define BITS7	020
3717Sbill #define BITS8	030
3817Sbill #define TWOSB	040
3917Sbill #define PENABLE	0100
4017Sbill #define OPAR	0200
4117Sbill #define MSE	040		/* Master Scan Enable */
4217Sbill #define RIE	0100		/* Receiver Interrupt Enable */
43119Sbill #define	SAE	010000		/* Silo Alarm Enable */
44119Sbill #define TIE	040000		/* Transmit Interrupt Enable */
45119Sbill #define DZ_IEN	(MSE+RIE+TIE+SAE)
4617Sbill #define PERROR	010000
4717Sbill #define FRERROR	020000
48119Sbill #define	OVERRUN	040000
4917Sbill #define SSPEED	7		/* std speed = 300 baud */
5017Sbill 
5117Sbill 
5217Sbill #define	dzlpr	dzrbuf
5317Sbill #define dzmsr	dzbrk
5417Sbill #define ON	1
5517Sbill #define OFF	0
5617Sbill 
5717Sbill int	dzstart();
5817Sbill int	dzxint();
59114Sbill int	ttrstrt();
6017Sbill struct	tty dz_tty[NDZ];
6117Sbill int	dz_cnt = { NDZ };
62119Sbill int	dzact;
6317Sbill 
6417Sbill struct device {
6517Sbill 	short	dzcsr;
6617Sbill 	short	dzrbuf;
6717Sbill 	char	dztcr;
6817Sbill 	char	dzdtr;
6917Sbill 	char	dztbuf;
7017Sbill 	char	dzbrk;
7117Sbill };
7217Sbill 
7317Sbill struct pdma dzpdma[] = {
7417Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint,
7517Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint,
7617Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint,
7717Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint,
7817Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint,
7917Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint,
8017Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint,
8117Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint,
821599Sbill #if NDZ11 >= 2
8317Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint,
8417Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint,
8517Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint,
8617Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint,
8717Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint,
8817Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint,
8917Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint,
9017Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint,
91882Sbill #endif
921599Sbill #if NDZ11 >= 3
9317Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint,
9417Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint,
9517Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint,
9617Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint,
9717Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint,
9817Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint,
9917Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint,
10017Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint,
10117Sbill #endif
1021599Sbill #if NDZ11 >= 4
103882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[24], dzxint,
104882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[25], dzxint,
105882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[26], dzxint,
106882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[27], dzxint,
107882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[28], dzxint,
108882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[29], dzxint,
109882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[30], dzxint,
110882Sbill 	(struct device *)(DZADDR+030), NULL, NULL, (int)&dz_tty[31], dzxint,
111882Sbill #endif
11217Sbill };
11317Sbill char	dz_timer;
11417Sbill char	dz_speeds[] = {
11517Sbill 	0, 020 , 021 , 022 , 023 , 024 , 0, 025,
11617Sbill 	026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
11717Sbill };
118*2197Stoy char dz_brk[NDZ11];
11917Sbill 
12017Sbill /*ARGSUSED*/
12117Sbill dzopen(d, flag)
12217Sbill {
12317Sbill 	register struct tty *tp;
12417Sbill 	register dev;
12517Sbill 	extern dzscan();
12617Sbill 
12717Sbill 	dev = minor(d);
12817Sbill 	if (dev >= dz_cnt) {
12917Sbill 		u.u_error = ENXIO;
13017Sbill 		return;
13117Sbill 	}
13217Sbill 	if (dz_timer == 0) {
13317Sbill 		dz_timer++;
13417Sbill 		timeout(dzscan, (caddr_t)0, 60);
13517Sbill 	}
13617Sbill 	tp = &dz_tty[dev];
13717Sbill 	tp->t_addr = (caddr_t)&dzpdma[dev];
13817Sbill 	tp->t_oproc = dzstart;
13917Sbill 	tp->t_iproc = NULL;
14017Sbill 	tp->t_state |= WOPEN;
14117Sbill 	if ((tp->t_state & ISOPEN) == 0) {
14217Sbill 		ttychars(tp);
14317Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
14417Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
14517Sbill 		/*tp->t_state |= HUPCLS;*/
14617Sbill 		dzparam(dev);
14717Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
14817Sbill 		u.u_error = EBUSY;
14917Sbill 		return;
15017Sbill 	}
15117Sbill 	dzmodem(dev, ON);
152114Sbill 	(void) spl5();
15317Sbill 	while ((tp->t_state & CARR_ON) == 0) {
15417Sbill 		tp->t_state |= WOPEN;
15517Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
15617Sbill 	}
157114Sbill 	(void) spl0();
15817Sbill 	(*linesw[tp->t_line].l_open)(d, tp);
15917Sbill }
16017Sbill 
16117Sbill dzclose(d)
16217Sbill {
16317Sbill 	register struct tty *tp;
16417Sbill 	register dev;
16517Sbill 
16617Sbill 	dev = minor(d);
16717Sbill 	tp = &dz_tty[dev];
16817Sbill 	(*linesw[tp->t_line].l_close)(tp);
169*2197Stoy 	/*
170*2197Stoy 	 * Turn the break bit off in case it was left on by a TIOCSBRK
171*2197Stoy 	 * but not turned off by TIOCCBRK
172*2197Stoy 	 */
173*2197Stoy 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
174*2197Stoy 		(dz_brk[minor(dev)>>3] &= ~(1 << (dev&07)));
17517Sbill 	if (tp->t_state & HUPCLS)
17617Sbill 		dzmodem(dev, OFF);
17717Sbill 	ttyclose(tp);
17817Sbill }
17917Sbill 
18017Sbill dzread(d)
18117Sbill {
18217Sbill 	register struct tty *tp;
18317Sbill 
18417Sbill 	tp = &dz_tty[minor(d)];
18517Sbill 	(*linesw[tp->t_line].l_read)(tp);
18617Sbill }
18717Sbill 
18817Sbill dzwrite(d)
18917Sbill {
19017Sbill 	register struct tty *tp;
19117Sbill 
19217Sbill 	tp = &dz_tty[minor(d)];
19317Sbill 	(*linesw[tp->t_line].l_write)(tp);
19417Sbill }
19517Sbill 
196119Sbill /*ARGSUSED*/
19717Sbill dzrint(dev)
19817Sbill {
19917Sbill 	register struct tty *tp;
20017Sbill 	register int c;
20117Sbill 	register struct device *dzaddr;
202119Sbill 	register struct tty *tp0;
203140Sbill 	int s;
20417Sbill 
205140Sbill 	s = spl6();	/* see comment in clock.c */
206119Sbill 	/* as long as we are here, service them all */
207119Sbill 	for (dev = 0; dev < NDZ; dev += 8) {
208119Sbill 		if ((dzact & (1<<(dev>>3))) == 0)
20917Sbill 			continue;
210119Sbill 		dzaddr = dzpdma[dev].p_addr;
211119Sbill 		tp0 = &dz_tty[dev];
212119Sbill 		while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
213119Sbill 			tp = tp0 + ((c>>8)&07);
214119Sbill 			if (tp >= &dz_tty[dz_cnt])
21517Sbill 				continue;
216119Sbill 			if ((tp->t_state & ISOPEN) == 0) {
217119Sbill 				wakeup((caddr_t)&tp->t_rawq);
218119Sbill 				continue;
219119Sbill 			}
220119Sbill 			if (c&FRERROR)
221119Sbill 				/* framing error = break */
222119Sbill 				if (tp->t_flags & RAW)
223119Sbill 					c = 0;		/* null for getty */
224119Sbill 				else
225170Sbill #ifdef IIASA
226170Sbill 					continue;
227170Sbill #else
228185Sbill 					c = tun.t_intrc;
229170Sbill #endif
230119Sbill 			if (c&OVERRUN)
231119Sbill 				printf("o");
232119Sbill 			if (c&PERROR)
233119Sbill 				/* parity error */
234119Sbill 				if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
235119Sbill 				  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
236119Sbill 					continue;
237140Sbill 			if (tp->t_line == NETLDISC) {
238114Sbill 				c &= 0177;
239170Sbill 				BKINPUT(c, tp);
240114Sbill 			} else
241114Sbill 				(*linesw[tp->t_line].l_rint)(c, tp);
242119Sbill 		}
24317Sbill 	}
244140Sbill 	splx(s);
24517Sbill }
24617Sbill 
24717Sbill /*ARGSUSED*/
24817Sbill dzioctl(dev, cmd, addr, flag)
24917Sbill caddr_t addr;
25017Sbill dev_t dev;
25117Sbill {
25217Sbill 	register struct tty *tp;
25317Sbill 
25417Sbill 	tp = &dz_tty[minor(dev)];
255114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
256114Sbill 	if (cmd == 0)
257114Sbill 		return;
2581896Swnj 	if (ttioctl(tp, cmd, addr, flag)) {
25917Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
26017Sbill 			dzparam(minor(dev));
261170Sbill 	} else switch(cmd) {
262170Sbill 	case TIOCSBRK:
263882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
264882Sbill 			(dz_brk[minor(dev)>>3] |= 1 << (dev&07));
265170Sbill 		break;
266170Sbill 	case TIOCCBRK:
267882Sbill 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
268882Sbill 			(dz_brk[minor(dev)>>3] &= ~(1 << (dev&07)));
269170Sbill 		break;
270170Sbill 	case TIOCSDTR:
271210Sbill 		dzmodem(minor(dev), ON);
272170Sbill 		break;
273170Sbill 	case TIOCCDTR:
274210Sbill 		dzmodem(minor(dev), OFF);
275170Sbill 		break;
276170Sbill 	default:
27717Sbill 		u.u_error = ENOTTY;
278170Sbill 	}
27917Sbill }
28017Sbill 
28117Sbill dzparam(dev)
28217Sbill {
28317Sbill 	register struct tty *tp;
28417Sbill 	register struct device *dzaddr;
28517Sbill 	register short lpr;
28617Sbill 
28717Sbill 	tp = &dz_tty[dev];
28817Sbill 	dzaddr = dzpdma[dev].p_addr;
28917Sbill 	dzaddr->dzcsr = DZ_IEN;
290119Sbill 	dzact |= (1<<(dev>>3));
29117Sbill 	if (tp->t_ispeed == 0) {
29217Sbill 		dzmodem(dev, OFF);		/* hang up line */
29317Sbill 		return;
29417Sbill 	}
29517Sbill 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07);
296882Sbill #ifndef IIASA
29717Sbill 	if (tp->t_flags & RAW)
29817Sbill 		lpr |= BITS8;
29917Sbill 	else
30017Sbill 		lpr |= (BITS7|PENABLE);
30117Sbill 	if ((tp->t_flags & EVENP) == 0)
30217Sbill 		lpr |= OPAR;
303882Sbill #else IIASA
304882Sbill 	if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP))
305882Sbill 		lpr |= BITS8;
306882Sbill 	else if (tp->t_flags & EVENP)
307882Sbill 		lpr |= (BITS7|PENABLE);
308882Sbill 	else if (tp->t_flags & ODDP)
309882Sbill 		lpr |= (BITS7|OPAR|PENABLE);
310882Sbill 	else
311882Sbill 		lpr |= BITS7;
312882Sbill #endif IIASA
31317Sbill 	if (tp->t_ispeed == 3)
31417Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
31517Sbill 	dzaddr->dzlpr = lpr;
31617Sbill }
31717Sbill 
31817Sbill dzxint(tp)
31917Sbill register struct tty *tp;
32017Sbill {
32117Sbill 	register struct pdma *dp;
322145Sbill 	register s;
323145Sbill 	s = spl6();	/* block the clock */
32417Sbill 
32517Sbill 	dp = &dzpdma[tp-dz_tty];
32617Sbill 	tp->t_state &= ~BUSY;
32717Sbill 	if (tp->t_state & FLUSH)
32817Sbill 		tp->t_state &= ~FLUSH;
32917Sbill 	else
330281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
33117Sbill 	if (tp->t_line)
33217Sbill 		(*linesw[tp->t_line].l_start)(tp);
33317Sbill 	else
33417Sbill 		dzstart(tp);
33517Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
33617Sbill 		dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8));
337145Sbill 	splx(s);
33817Sbill }
33917Sbill 
34017Sbill dzstart(tp)
34117Sbill register struct tty *tp;
34217Sbill {
34317Sbill 	register struct pdma *dp;
34417Sbill 	register struct device *dzaddr;
34517Sbill 	register cc;
34617Sbill 	int sps;
34717Sbill 
34817Sbill 	dp = &dzpdma[tp-dz_tty];
34917Sbill 	dzaddr = dp->p_addr;
35017Sbill 	sps = spl5();
35117Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
35217Sbill 		goto out;
353921Sbill 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
35417Sbill 		tp->t_state &= ~ASLEEP;
35517Sbill 		if (tp->t_chan)
35617Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
35717Sbill 		else
35817Sbill 			wakeup((caddr_t)&tp->t_outq);
35917Sbill 	}
36017Sbill 	if (tp->t_outq.c_cc == 0)
36117Sbill 		goto out;
36217Sbill 	if (tp->t_flags&RAW)
36317Sbill 		cc = ndqb(&tp->t_outq, 0);
36417Sbill 	else {
36517Sbill 		cc = ndqb(&tp->t_outq, 0200);
36617Sbill 		if (cc == 0) {
36717Sbill 			cc = getc(&tp->t_outq);
36817Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
36917Sbill 			tp->t_state |= TIMEOUT;
37017Sbill 			goto out;
37117Sbill 		}
37217Sbill 	}
37317Sbill 	tp->t_state |= BUSY;
37417Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
37517Sbill 	dp->p_end += cc;
37617Sbill 	dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8);
37717Sbill    out:
37817Sbill 	splx(sps);
37917Sbill }
38017Sbill 
38117Sbill /*
38217Sbill  * Stop output on a line.
38317Sbill  * Assume call is made at spl6.
38417Sbill  */
38517Sbill /*ARGSUSED*/
38617Sbill dzstop(tp, flag)
38717Sbill register struct tty *tp;
38817Sbill {
38917Sbill 	register struct pdma *dp;
39017Sbill 	register int s;
39117Sbill 
39217Sbill 	dp = &dzpdma[tp-dz_tty];
39317Sbill 	s = spl6();
39417Sbill 	if (tp->t_state & BUSY) {
39517Sbill 		dp->p_end = dp->p_mem;
39617Sbill 		if ((tp->t_state&TTSTOP)==0) {
39717Sbill 			tp->t_state |= FLUSH;
39817Sbill 		}
39917Sbill 	}
40017Sbill 	splx(s);
40117Sbill }
40217Sbill 
40317Sbill dzmodem(dev, flag)
40417Sbill register int dev;
40517Sbill {
40617Sbill 	register struct device *dzaddr;
40717Sbill 	register char bit;
40817Sbill 
40917Sbill 	dzaddr = dzpdma[dev].p_addr;
41017Sbill 	bit = 1<<(dev&07);
41117Sbill 	if (flag == OFF)
41217Sbill 		dzaddr->dzdtr &= ~bit;
41317Sbill 	else
41417Sbill 		dzaddr->dzdtr |= bit;
41517Sbill }
41617Sbill 
41717Sbill dzscan()
41817Sbill {
41917Sbill 	register i;
42017Sbill 	register struct device *dzaddr;
42117Sbill 	register bit;
42217Sbill 	register struct tty *tp;
42317Sbill 
42417Sbill 	for (i = 0; i < dz_cnt ; i++) {
42517Sbill 		dzaddr = dzpdma[i].p_addr;
42617Sbill 		tp = &dz_tty[i];
42717Sbill 		bit = 1<<(i&07);
42817Sbill 		if (dzaddr->dzmsr & bit) {
42917Sbill 			/* carrier present */
43017Sbill 			if ((tp->t_state & CARR_ON) == 0) {
43117Sbill 				wakeup((caddr_t)&tp->t_rawq);
43217Sbill 				tp->t_state |= CARR_ON;
43317Sbill 			}
43417Sbill 		} else {
435882Sbill 			if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG) == 0) {
43617Sbill 				/* carrier lost */
437882Sbill 				if (tp->t_state&ISOPEN) {
438170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
439205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
440170Sbill 					dzaddr->dzdtr &= ~bit;
441871Sbill 					flushtty(tp, FREAD|FWRITE);
442170Sbill 				}
443170Sbill 				tp->t_state &= ~CARR_ON;
44417Sbill 			}
44517Sbill 		}
44617Sbill 	}
44717Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
44817Sbill }
449119Sbill 
450119Sbill dztimer()
451119Sbill {
452119Sbill 
453119Sbill 	dzrint(0);
454119Sbill }
455281Sbill 
456281Sbill /*
457281Sbill  * Reset state of driver if UBA reset was necessary.
458301Sbill  * Reset parameters and restart transmission on open lines.
459281Sbill  */
460281Sbill dzreset()
461281Sbill {
462281Sbill 	int d;
463281Sbill 	register struct tty *tp;
464281Sbill 
465281Sbill 	printf(" dz");
466281Sbill 	for (d = 0; d < NDZ; d++) {
467281Sbill 		tp = &dz_tty[d];
468281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
469281Sbill 			dzparam(d);
470301Sbill 			dzmodem(d, ON);
471301Sbill 			tp->t_state &= ~BUSY;
472301Sbill 			dzstart(tp);
473281Sbill 		}
474281Sbill 	}
475281Sbill 	dztimer();
476281Sbill }
4771562Sbill #endif
478