xref: /csrg-svn/sys/vax/uba/dz.c (revision 281)
1*281Sbill /*	dz.c	3.11	06/22/80	*/
217Sbill 
317Sbill /*
417Sbill  *  DZ-11 Driver
517Sbill  */
617Sbill #include "../h/param.h"
717Sbill #include "../h/systm.h"
817Sbill #include "../h/tty.h"
917Sbill #include "../h/dir.h"
1017Sbill #include "../h/user.h"
1117Sbill #include "../h/map.h"
1217Sbill #include "../h/pte.h"
1317Sbill #include "../h/uba.h"
1417Sbill #include "../h/conf.h"
1517Sbill #include "../h/pdma.h"
16114Sbill #include "../h/bk.h"
17145Sbill 
18145Sbill /*
19145Sbill  * When running dz's using only SAE (silo alarm) on input
20145Sbill  * it is necessary to call dzrint() at clock interrupt time.
21145Sbill  * This is unsafe unless spl5()s in tty code are changed to
22145Sbill  * spl6()s to block clock interrupts.  Note that the dh driver
23145Sbill  * currently in use works the same way as the dz, even though
24145Sbill  * we could try to more intelligently manage its silo.
25145Sbill  * Thus don't take this out if you have no dz's unless you
26145Sbill  * change clock.c and dhtimer().
27145Sbill  */
28145Sbill #define	spl5	spl6
2917Sbill 
3017Sbill #define DZADDR  (UBA0_DEV + 0160100)
3117Sbill #ifdef ERNIE
3217Sbill #define NDZ 	(3*8)
3317Sbill #else
3417Sbill #define	NDZ	(8)
3517Sbill #endif
3617Sbill 
3717Sbill #define BITS7	020
3817Sbill #define BITS8	030
3917Sbill #define TWOSB	040
4017Sbill #define PENABLE	0100
4117Sbill #define OPAR	0200
4217Sbill #define MSE	040		/* Master Scan Enable */
4317Sbill #define RIE	0100		/* Receiver Interrupt Enable */
44119Sbill #define	SAE	010000		/* Silo Alarm Enable */
45119Sbill #define TIE	040000		/* Transmit Interrupt Enable */
46119Sbill #define DZ_IEN	(MSE+RIE+TIE+SAE)
4717Sbill #define PERROR	010000
4817Sbill #define FRERROR	020000
49119Sbill #define	OVERRUN	040000
5017Sbill #define SSPEED	7		/* std speed = 300 baud */
5117Sbill 
5217Sbill 
5317Sbill #define	dzlpr	dzrbuf
5417Sbill #define dzmsr	dzbrk
5517Sbill #define ON	1
5617Sbill #define OFF	0
5717Sbill 
5817Sbill int	dzstart();
5917Sbill int	dzxint();
60114Sbill int	ttrstrt();
6117Sbill struct	tty dz_tty[NDZ];
6217Sbill int	dz_cnt = { NDZ };
63119Sbill int	dzact;
64*281Sbill int	dzinit;
65*281Sbill int	dzdtr[(NDZ+7)/8];
6617Sbill 
6717Sbill struct device {
6817Sbill 	short	dzcsr;
6917Sbill 	short	dzrbuf;
7017Sbill 	char	dztcr;
7117Sbill 	char	dzdtr;
7217Sbill 	char	dztbuf;
7317Sbill 	char	dzbrk;
7417Sbill };
7517Sbill 
7617Sbill struct pdma dzpdma[] = {
7717Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint,
7817Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint,
7917Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint,
8017Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint,
8117Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint,
8217Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint,
8317Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint,
8417Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint,
8517Sbill #ifdef ERNIE
8617Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint,
8717Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint,
8817Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint,
8917Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint,
9017Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint,
9117Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint,
9217Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint,
9317Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint,
9417Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint,
9517Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint,
9617Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint,
9717Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint,
9817Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint,
9917Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint,
10017Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint,
10117Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint,
10217Sbill #endif
10317Sbill };
10417Sbill char	dz_timer;
10517Sbill char	dz_speeds[] = {
10617Sbill 	0, 020 , 021 , 022 , 023 , 024 , 0, 025,
10717Sbill 	026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
10817Sbill };
10917Sbill 
11017Sbill /*ARGSUSED*/
11117Sbill dzopen(d, flag)
11217Sbill {
11317Sbill 	register struct tty *tp;
11417Sbill 	register dev;
11517Sbill 	extern dzscan();
11617Sbill 
11717Sbill 	dev = minor(d);
11817Sbill 	if (dev >= dz_cnt) {
11917Sbill 		u.u_error = ENXIO;
12017Sbill 		return;
12117Sbill 	}
12217Sbill 	if (dz_timer == 0) {
12317Sbill 		dz_timer++;
12417Sbill 		timeout(dzscan, (caddr_t)0, 60);
12517Sbill 	}
12617Sbill 	tp = &dz_tty[dev];
12717Sbill 	tp->t_addr = (caddr_t)&dzpdma[dev];
12817Sbill 	tp->t_oproc = dzstart;
12917Sbill 	tp->t_iproc = NULL;
13017Sbill 	tp->t_state |= WOPEN;
13117Sbill 	if ((tp->t_state & ISOPEN) == 0) {
13217Sbill 		ttychars(tp);
13317Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
13417Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
13517Sbill 		/*tp->t_state |= HUPCLS;*/
13617Sbill 		dzparam(dev);
13717Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
13817Sbill 		u.u_error = EBUSY;
13917Sbill 		return;
14017Sbill 	}
14117Sbill 	dzmodem(dev, ON);
142114Sbill 	(void) spl5();
14317Sbill 	while ((tp->t_state & CARR_ON) == 0) {
14417Sbill 		tp->t_state |= WOPEN;
14517Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
14617Sbill 	}
147114Sbill 	(void) spl0();
14817Sbill 	(*linesw[tp->t_line].l_open)(d, tp);
14917Sbill }
15017Sbill 
15117Sbill dzclose(d)
15217Sbill {
15317Sbill 	register struct tty *tp;
15417Sbill 	register dev;
15517Sbill 
15617Sbill 	dev = minor(d);
15717Sbill 	tp = &dz_tty[dev];
15817Sbill 	(*linesw[tp->t_line].l_close)(tp);
15917Sbill 	if (tp->t_state & HUPCLS)
16017Sbill 		dzmodem(dev, OFF);
16117Sbill 	ttyclose(tp);
16217Sbill }
16317Sbill 
16417Sbill dzread(d)
16517Sbill {
16617Sbill 	register struct tty *tp;
16717Sbill 
16817Sbill 	tp = &dz_tty[minor(d)];
16917Sbill 	(*linesw[tp->t_line].l_read)(tp);
17017Sbill }
17117Sbill 
17217Sbill dzwrite(d)
17317Sbill {
17417Sbill 	register struct tty *tp;
17517Sbill 
17617Sbill 	tp = &dz_tty[minor(d)];
17717Sbill 	(*linesw[tp->t_line].l_write)(tp);
17817Sbill }
17917Sbill 
180119Sbill /*ARGSUSED*/
18117Sbill dzrint(dev)
18217Sbill {
18317Sbill 	register struct tty *tp;
18417Sbill 	register int c;
18517Sbill 	register struct device *dzaddr;
186119Sbill 	register struct tty *tp0;
187140Sbill 	int s;
18817Sbill 
189140Sbill 	s = spl6();	/* see comment in clock.c */
190119Sbill 	/* as long as we are here, service them all */
191119Sbill 	for (dev = 0; dev < NDZ; dev += 8) {
192119Sbill 		if ((dzact & (1<<(dev>>3))) == 0)
19317Sbill 			continue;
194119Sbill 		dzaddr = dzpdma[dev].p_addr;
195119Sbill 		tp0 = &dz_tty[dev];
196119Sbill 		while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
197119Sbill 			tp = tp0 + ((c>>8)&07);
198119Sbill 			if (tp >= &dz_tty[dz_cnt])
19917Sbill 				continue;
200119Sbill 			if ((tp->t_state & ISOPEN) == 0) {
201119Sbill 				wakeup((caddr_t)&tp->t_rawq);
202119Sbill 				continue;
203119Sbill 			}
204119Sbill 			if (c&FRERROR)
205119Sbill 				/* framing error = break */
206119Sbill 				if (tp->t_flags & RAW)
207119Sbill 					c = 0;		/* null for getty */
208119Sbill 				else
209170Sbill #ifdef IIASA
210170Sbill 					continue;
211170Sbill #else
212185Sbill 					c = tun.t_intrc;
213170Sbill #endif
214119Sbill 			if (c&OVERRUN)
215119Sbill 				printf("o");
216119Sbill 			if (c&PERROR)
217119Sbill 				/* parity error */
218119Sbill 				if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
219119Sbill 				  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
220119Sbill 					continue;
221140Sbill 			if (tp->t_line == NETLDISC) {
222114Sbill 				c &= 0177;
223170Sbill 				BKINPUT(c, tp);
224114Sbill 			} else
225114Sbill 				(*linesw[tp->t_line].l_rint)(c, tp);
226119Sbill 		}
22717Sbill 	}
228140Sbill 	splx(s);
22917Sbill }
23017Sbill 
23117Sbill /*ARGSUSED*/
23217Sbill dzioctl(dev, cmd, addr, flag)
23317Sbill caddr_t addr;
23417Sbill dev_t dev;
23517Sbill {
23617Sbill 	register struct tty *tp;
23717Sbill 
23817Sbill 	tp = &dz_tty[minor(dev)];
239114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
240114Sbill 	if (cmd == 0)
241114Sbill 		return;
24217Sbill 	if (ttioccomm(cmd, tp, addr, dev)) {
24317Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
24417Sbill 			dzparam(minor(dev));
245170Sbill 	} else switch(cmd) {
246170Sbill 	case TIOCSBRK:
247170Sbill 		((struct device *)(tp->t_addr))->dzbrk |= 1 << (dev&07);
248170Sbill 		break;
249170Sbill 	case TIOCCBRK:
250170Sbill 		((struct device *)(tp->t_addr))->dzbrk &= ~(1 << (dev&07));
251170Sbill 		break;
252170Sbill 	case TIOCSDTR:
253210Sbill 		dzmodem(minor(dev), ON);
254170Sbill 		break;
255170Sbill 	case TIOCCDTR:
256210Sbill 		dzmodem(minor(dev), OFF);
257170Sbill 		break;
258170Sbill 	default:
25917Sbill 		u.u_error = ENOTTY;
260170Sbill 	}
26117Sbill }
26217Sbill 
26317Sbill dzparam(dev)
26417Sbill {
26517Sbill 	register struct tty *tp;
26617Sbill 	register struct device *dzaddr;
26717Sbill 	register short lpr;
26817Sbill 
26917Sbill 	tp = &dz_tty[dev];
27017Sbill 	dzaddr = dzpdma[dev].p_addr;
27117Sbill 	dzaddr->dzcsr = DZ_IEN;
272119Sbill 	dzact |= (1<<(dev>>3));
27317Sbill 	if (tp->t_ispeed == 0) {
27417Sbill 		dzmodem(dev, OFF);		/* hang up line */
27517Sbill 		return;
27617Sbill 	}
27717Sbill 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07);
27817Sbill 	if (tp->t_flags & RAW)
27917Sbill 		lpr |= BITS8;
28017Sbill 	else
28117Sbill 		lpr |= (BITS7|PENABLE);
28217Sbill 	if ((tp->t_flags & EVENP) == 0)
28317Sbill 		lpr |= OPAR;
28417Sbill 	if (tp->t_ispeed == 3)
28517Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
28617Sbill 	dzaddr->dzlpr = lpr;
28717Sbill }
28817Sbill 
28917Sbill dzxint(tp)
29017Sbill register struct tty *tp;
29117Sbill {
29217Sbill 	register struct pdma *dp;
293145Sbill 	register s;
294145Sbill 	s = spl6();	/* block the clock */
29517Sbill 
29617Sbill 	dp = &dzpdma[tp-dz_tty];
29717Sbill 	tp->t_state &= ~BUSY;
29817Sbill 	if (tp->t_state & FLUSH)
29917Sbill 		tp->t_state &= ~FLUSH;
30017Sbill 	else
301*281Sbill 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
30217Sbill 	if (tp->t_line)
30317Sbill 		(*linesw[tp->t_line].l_start)(tp);
30417Sbill 	else
30517Sbill 		dzstart(tp);
30617Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
30717Sbill 		dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8));
308145Sbill 	splx(s);
30917Sbill }
31017Sbill 
31117Sbill dzstart(tp)
31217Sbill register struct tty *tp;
31317Sbill {
31417Sbill 	register struct pdma *dp;
31517Sbill 	register struct device *dzaddr;
31617Sbill 	register cc;
31717Sbill 	int sps;
31817Sbill 
31917Sbill 	dp = &dzpdma[tp-dz_tty];
32017Sbill 	dzaddr = dp->p_addr;
32117Sbill 	sps = spl5();
32217Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
32317Sbill 		goto out;
32417Sbill 	if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) {
32517Sbill 		tp->t_state &= ~ASLEEP;
32617Sbill 		if (tp->t_chan)
32717Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
32817Sbill 		else
32917Sbill 			wakeup((caddr_t)&tp->t_outq);
33017Sbill 	}
33117Sbill 	if (tp->t_outq.c_cc == 0)
33217Sbill 		goto out;
33317Sbill 	if (tp->t_flags&RAW)
33417Sbill 		cc = ndqb(&tp->t_outq, 0);
33517Sbill 	else {
33617Sbill 		cc = ndqb(&tp->t_outq, 0200);
33717Sbill 		if (cc == 0) {
33817Sbill 			cc = getc(&tp->t_outq);
33917Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
34017Sbill 			tp->t_state |= TIMEOUT;
34117Sbill 			goto out;
34217Sbill 		}
34317Sbill 	}
34417Sbill 	tp->t_state |= BUSY;
34517Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
34617Sbill 	dp->p_end += cc;
34717Sbill 	dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8);
34817Sbill    out:
34917Sbill 	splx(sps);
35017Sbill }
35117Sbill 
35217Sbill /*
35317Sbill  * Stop output on a line.
35417Sbill  * Assume call is made at spl6.
35517Sbill  */
35617Sbill /*ARGSUSED*/
35717Sbill dzstop(tp, flag)
35817Sbill register struct tty *tp;
35917Sbill {
36017Sbill 	register struct pdma *dp;
36117Sbill 	register int s;
36217Sbill 
36317Sbill 	dp = &dzpdma[tp-dz_tty];
36417Sbill 	s = spl6();
36517Sbill 	if (tp->t_state & BUSY) {
36617Sbill 		dp->p_end = dp->p_mem;
36717Sbill 		if ((tp->t_state&TTSTOP)==0) {
36817Sbill 			tp->t_state |= FLUSH;
36917Sbill 		}
37017Sbill 	}
37117Sbill 	splx(s);
37217Sbill }
37317Sbill 
37417Sbill dzmodem(dev, flag)
37517Sbill register int dev;
37617Sbill {
37717Sbill 	register struct device *dzaddr;
37817Sbill 	register char bit;
37917Sbill 
38017Sbill 	dzaddr = dzpdma[dev].p_addr;
38117Sbill 	bit = 1<<(dev&07);
38217Sbill 	if (flag == OFF)
38317Sbill 		dzaddr->dzdtr &= ~bit;
38417Sbill 	else
38517Sbill 		dzaddr->dzdtr |= bit;
386*281Sbill 	dzdtr[minor(dev)>>3] = dzaddr->dzdtr;
38717Sbill }
38817Sbill 
38917Sbill dzscan()
39017Sbill {
39117Sbill 	register i;
39217Sbill 	register struct device *dzaddr;
39317Sbill 	register bit;
39417Sbill 	register struct tty *tp;
39517Sbill 
39617Sbill 	for (i = 0; i < dz_cnt ; i++) {
39717Sbill 		dzaddr = dzpdma[i].p_addr;
39817Sbill 		tp = &dz_tty[i];
39917Sbill 		bit = 1<<(i&07);
40017Sbill 		if (dzaddr->dzmsr & bit) {
40117Sbill 			/* carrier present */
40217Sbill 			if ((tp->t_state & CARR_ON) == 0) {
40317Sbill 				wakeup((caddr_t)&tp->t_rawq);
40417Sbill 				tp->t_state |= CARR_ON;
40517Sbill 			}
40617Sbill 		} else {
40717Sbill 			if ((tp->t_state & CARR_ON)) {
40817Sbill 				/* carrier lost */
409170Sbill 				if (tp->t_state&ISOPEN &&
410170Sbill 				    (tp->t_local&LNOHANG) == 0) {
411170Sbill 					gsignal(tp->t_pgrp, SIGHUP);
412205Sbill 					gsignal(tp->t_pgrp, SIGCONT);
413170Sbill 					dzaddr->dzdtr &= ~bit;
414*281Sbill 					dzdtr[i>>3] = dzaddr->dzdtr;
415170Sbill 					flushtty(tp);
416170Sbill 				}
417170Sbill 				tp->t_state &= ~CARR_ON;
41817Sbill 			}
41917Sbill 		}
42017Sbill 	}
42117Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
42217Sbill }
423119Sbill 
424119Sbill dztimer()
425119Sbill {
426119Sbill 
427119Sbill 	dzrint(0);
428119Sbill }
429*281Sbill 
430*281Sbill /*
431*281Sbill  * Reset state of driver if UBA reset was necessary.
432*281Sbill  * Reset all the dzdtr registers, then the csr and lpr
433*281Sbill  * registers, then restart all pending transmissions.
434*281Sbill  */
435*281Sbill dzreset()
436*281Sbill {
437*281Sbill 	int d;
438*281Sbill 	register struct tty *tp;
439*281Sbill 
440*281Sbill 	printf(" dz");
441*281Sbill 	dzinit = 1;
442*281Sbill 	for (d = 0; d < NDZ; d += 8)
443*281Sbill 		dzpdma[d].p_addr->dzdtr = dzdtr[d>>3];
444*281Sbill 	for (d = 0; d < NDZ; d++) {
445*281Sbill 		tp = &dz_tty[d];
446*281Sbill 		if (tp->t_state & (ISOPEN|WOPEN)) {
447*281Sbill 			dzparam(d);
448*281Sbill 			dzxint(tp);
449*281Sbill 		}
450*281Sbill 	}
451*281Sbill 	dztimer();
452*281Sbill 	dzinit = 0;
453*281Sbill }
454