xref: /csrg-svn/sys/vax/uba/dz.c (revision 140)
1*140Sbill /*	dz.c	3.4	10/14/12	*/
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"
1717Sbill 
1817Sbill #define DZADDR  (UBA0_DEV + 0160100)
1917Sbill #ifdef ERNIE
2017Sbill #define NDZ 	(3*8)
2117Sbill #else
2217Sbill #define	NDZ	(8)
2317Sbill #endif
2417Sbill 
2517Sbill #define BITS7	020
2617Sbill #define BITS8	030
2717Sbill #define TWOSB	040
2817Sbill #define PENABLE	0100
2917Sbill #define OPAR	0200
3017Sbill #define MSE	040		/* Master Scan Enable */
3117Sbill #define RIE	0100		/* Receiver Interrupt Enable */
32119Sbill #define	SAE	010000		/* Silo Alarm Enable */
33119Sbill #define TIE	040000		/* Transmit Interrupt Enable */
34119Sbill #define DZ_IEN	(MSE+RIE+TIE+SAE)
3517Sbill #define PERROR	010000
3617Sbill #define FRERROR	020000
37119Sbill #define	OVERRUN	040000
3817Sbill #define SSPEED	7		/* std speed = 300 baud */
3917Sbill 
4017Sbill 
4117Sbill #define	dzlpr	dzrbuf
4217Sbill #define dzmsr	dzbrk
4317Sbill #define ON	1
4417Sbill #define OFF	0
4517Sbill 
4617Sbill int	dzstart();
4717Sbill int	dzxint();
48114Sbill int	ttrstrt();
4917Sbill struct	tty dz_tty[NDZ];
5017Sbill int	dz_cnt = { NDZ };
51119Sbill int	dzact;
5217Sbill 
5317Sbill struct device {
5417Sbill 	short	dzcsr;
5517Sbill 	short	dzrbuf;
5617Sbill 	char	dztcr;
5717Sbill 	char	dzdtr;
5817Sbill 	char	dztbuf;
5917Sbill 	char	dzbrk;
6017Sbill };
6117Sbill 
6217Sbill struct pdma dzpdma[] = {
6317Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint,
6417Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint,
6517Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint,
6617Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint,
6717Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint,
6817Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint,
6917Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint,
7017Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint,
7117Sbill #ifdef ERNIE
7217Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint,
7317Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint,
7417Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint,
7517Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint,
7617Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint,
7717Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint,
7817Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint,
7917Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint,
8017Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint,
8117Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint,
8217Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint,
8317Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint,
8417Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint,
8517Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint,
8617Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint,
8717Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint,
8817Sbill #endif
8917Sbill };
9017Sbill char	dz_timer;
9117Sbill char	dz_speeds[] = {
9217Sbill 	0, 020 , 021 , 022 , 023 , 024 , 0, 025,
9317Sbill 	026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
9417Sbill };
9517Sbill 
9617Sbill /*ARGSUSED*/
9717Sbill dzopen(d, flag)
9817Sbill {
9917Sbill 	register struct tty *tp;
10017Sbill 	register dev;
10117Sbill 	extern dzscan();
10217Sbill 
10317Sbill 	dev = minor(d);
10417Sbill 	if (dev >= dz_cnt) {
10517Sbill 		u.u_error = ENXIO;
10617Sbill 		return;
10717Sbill 	}
10817Sbill 	if (dz_timer == 0) {
10917Sbill 		dz_timer++;
11017Sbill 		timeout(dzscan, (caddr_t)0, 60);
11117Sbill 	}
11217Sbill 	tp = &dz_tty[dev];
11317Sbill 	tp->t_addr = (caddr_t)&dzpdma[dev];
11417Sbill 	tp->t_oproc = dzstart;
11517Sbill 	tp->t_iproc = NULL;
11617Sbill 	tp->t_state |= WOPEN;
11717Sbill 	if ((tp->t_state & ISOPEN) == 0) {
11817Sbill 		ttychars(tp);
11917Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
12017Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
12117Sbill 		/*tp->t_state |= HUPCLS;*/
12217Sbill 		dzparam(dev);
12317Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
12417Sbill 		u.u_error = EBUSY;
12517Sbill 		return;
12617Sbill 	}
12717Sbill 	dzmodem(dev, ON);
128114Sbill 	(void) spl5();
12917Sbill 	while ((tp->t_state & CARR_ON) == 0) {
13017Sbill 		tp->t_state |= WOPEN;
13117Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
13217Sbill 	}
133114Sbill 	(void) spl0();
13417Sbill 	(*linesw[tp->t_line].l_open)(d, tp);
13517Sbill }
13617Sbill 
13717Sbill dzclose(d)
13817Sbill {
13917Sbill 	register struct tty *tp;
14017Sbill 	register dev;
14117Sbill 
14217Sbill 	dev = minor(d);
14317Sbill 	tp = &dz_tty[dev];
14417Sbill 	(*linesw[tp->t_line].l_close)(tp);
14517Sbill 	if (tp->t_state & HUPCLS)
14617Sbill 		dzmodem(dev, OFF);
14717Sbill 	ttyclose(tp);
14817Sbill }
14917Sbill 
15017Sbill dzread(d)
15117Sbill {
15217Sbill 	register struct tty *tp;
15317Sbill 
15417Sbill 	tp = &dz_tty[minor(d)];
15517Sbill 	(*linesw[tp->t_line].l_read)(tp);
15617Sbill }
15717Sbill 
15817Sbill dzwrite(d)
15917Sbill {
16017Sbill 	register struct tty *tp;
16117Sbill 
16217Sbill 	tp = &dz_tty[minor(d)];
16317Sbill 	(*linesw[tp->t_line].l_write)(tp);
16417Sbill }
16517Sbill 
166119Sbill /*ARGSUSED*/
16717Sbill dzrint(dev)
16817Sbill {
16917Sbill 	register struct tty *tp;
17017Sbill 	register int c;
17117Sbill 	register struct device *dzaddr;
172119Sbill 	register struct tty *tp0;
173*140Sbill 	int s;
17417Sbill 
175*140Sbill 	s = spl6();	/* see comment in clock.c */
176119Sbill 	/* as long as we are here, service them all */
177119Sbill 	for (dev = 0; dev < NDZ; dev += 8) {
178119Sbill 		if ((dzact & (1<<(dev>>3))) == 0)
17917Sbill 			continue;
180119Sbill 		dzaddr = dzpdma[dev].p_addr;
181119Sbill 		tp0 = &dz_tty[dev];
182119Sbill 		while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
183119Sbill 			tp = tp0 + ((c>>8)&07);
184119Sbill 			if (tp >= &dz_tty[dz_cnt])
18517Sbill 				continue;
186119Sbill 			if ((tp->t_state & ISOPEN) == 0) {
187119Sbill 				wakeup((caddr_t)&tp->t_rawq);
188119Sbill 				continue;
189119Sbill 			}
190119Sbill 			if (c&FRERROR)
191119Sbill 				/* framing error = break */
192119Sbill 				if (tp->t_flags & RAW)
193119Sbill 					c = 0;		/* null for getty */
194119Sbill 				else
195119Sbill 					c = 0177;	/* DEL = interrupt */
196119Sbill 			if (c&OVERRUN)
197119Sbill 				printf("o");
198119Sbill 			if (c&PERROR)
199119Sbill 				/* parity error */
200119Sbill 				if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
201119Sbill 				  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
202119Sbill 					continue;
203114Sbill #ifdef BERKNET
204*140Sbill 			if (tp->t_line == NETLDISC) {
205114Sbill 				c &= 0177;
206114Sbill 				NETINPUT(c, tp);
207114Sbill 			} else
208114Sbill #endif
209114Sbill 				(*linesw[tp->t_line].l_rint)(c, tp);
210119Sbill 		}
21117Sbill 	}
212*140Sbill 	splx(s);
21317Sbill }
21417Sbill 
21517Sbill /*ARGSUSED*/
21617Sbill dzioctl(dev, cmd, addr, flag)
21717Sbill caddr_t addr;
21817Sbill dev_t dev;
21917Sbill {
22017Sbill 	register struct tty *tp;
22117Sbill 
22217Sbill 	tp = &dz_tty[minor(dev)];
223114Sbill 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
224114Sbill 	if (cmd == 0)
225114Sbill 		return;
22617Sbill 	if (ttioccomm(cmd, tp, addr, dev)) {
22717Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
22817Sbill 			dzparam(minor(dev));
22917Sbill 	} else
23017Sbill 		u.u_error = ENOTTY;
23117Sbill }
23217Sbill 
23317Sbill dzparam(dev)
23417Sbill {
23517Sbill 	register struct tty *tp;
23617Sbill 	register struct device *dzaddr;
23717Sbill 	register short lpr;
23817Sbill 
23917Sbill 	tp = &dz_tty[dev];
24017Sbill 	dzaddr = dzpdma[dev].p_addr;
24117Sbill 	dzaddr->dzcsr = DZ_IEN;
242119Sbill 	dzact |= (1<<(dev>>3));
24317Sbill 	if (tp->t_ispeed == 0) {
24417Sbill 		dzmodem(dev, OFF);		/* hang up line */
24517Sbill 		return;
24617Sbill 	}
24717Sbill 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07);
24817Sbill 	if (tp->t_flags & RAW)
24917Sbill 		lpr |= BITS8;
25017Sbill 	else
25117Sbill 		lpr |= (BITS7|PENABLE);
25217Sbill 	if ((tp->t_flags & EVENP) == 0)
25317Sbill 		lpr |= OPAR;
25417Sbill 	if (tp->t_ispeed == 3)
25517Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
25617Sbill 	dzaddr->dzlpr = lpr;
25717Sbill }
25817Sbill 
25917Sbill dzxint(tp)
26017Sbill register struct tty *tp;
26117Sbill {
26217Sbill 	register struct pdma *dp;
26317Sbill 
26417Sbill 	dp = &dzpdma[tp-dz_tty];
26517Sbill 	tp->t_state &= ~BUSY;
26617Sbill 	if (tp->t_state & FLUSH)
26717Sbill 		tp->t_state &= ~FLUSH;
26817Sbill 	else
26917Sbill 		ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf);
27017Sbill 	if (tp->t_line)
27117Sbill 		(*linesw[tp->t_line].l_start)(tp);
27217Sbill 	else
27317Sbill 		dzstart(tp);
27417Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
27517Sbill 		dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8));
27617Sbill }
27717Sbill 
27817Sbill dzstart(tp)
27917Sbill register struct tty *tp;
28017Sbill {
28117Sbill 	register struct pdma *dp;
28217Sbill 	register struct device *dzaddr;
28317Sbill 	register cc;
28417Sbill 	int sps;
28517Sbill 
28617Sbill 	dp = &dzpdma[tp-dz_tty];
28717Sbill 	dzaddr = dp->p_addr;
28817Sbill 	sps = spl5();
28917Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
29017Sbill 		goto out;
29117Sbill 	if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) {
29217Sbill 		tp->t_state &= ~ASLEEP;
29317Sbill 		if (tp->t_chan)
29417Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
29517Sbill 		else
29617Sbill 			wakeup((caddr_t)&tp->t_outq);
29717Sbill 	}
29817Sbill 	if (tp->t_outq.c_cc == 0)
29917Sbill 		goto out;
30017Sbill 	if (tp->t_flags&RAW)
30117Sbill 		cc = ndqb(&tp->t_outq, 0);
30217Sbill 	else {
30317Sbill 		cc = ndqb(&tp->t_outq, 0200);
30417Sbill 		if (cc == 0) {
30517Sbill 			cc = getc(&tp->t_outq);
30617Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
30717Sbill 			tp->t_state |= TIMEOUT;
30817Sbill 			goto out;
30917Sbill 		}
31017Sbill 	}
31117Sbill 	tp->t_state |= BUSY;
31217Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
31317Sbill 	dp->p_end += cc;
31417Sbill 	dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8);
31517Sbill    out:
31617Sbill 	splx(sps);
31717Sbill }
31817Sbill 
31917Sbill /*
32017Sbill  * Stop output on a line.
32117Sbill  * Assume call is made at spl6.
32217Sbill  */
32317Sbill /*ARGSUSED*/
32417Sbill dzstop(tp, flag)
32517Sbill register struct tty *tp;
32617Sbill {
32717Sbill 	register struct pdma *dp;
32817Sbill 	register int s;
32917Sbill 
33017Sbill 	dp = &dzpdma[tp-dz_tty];
33117Sbill 	s = spl6();
33217Sbill 	if (tp->t_state & BUSY) {
33317Sbill 		dp->p_end = dp->p_mem;
33417Sbill 		if ((tp->t_state&TTSTOP)==0) {
33517Sbill 			tp->t_state |= FLUSH;
33617Sbill 		}
33717Sbill 	}
33817Sbill 	splx(s);
33917Sbill }
34017Sbill 
34117Sbill dzmodem(dev, flag)
34217Sbill register int dev;
34317Sbill {
34417Sbill 	register struct device *dzaddr;
34517Sbill 	register char bit;
34617Sbill 
34717Sbill 	dzaddr = dzpdma[dev].p_addr;
34817Sbill 	bit = 1<<(dev&07);
34917Sbill 	if (flag == OFF)
35017Sbill 		dzaddr->dzdtr &= ~bit;
35117Sbill 	else
35217Sbill 		dzaddr->dzdtr |= bit;
35317Sbill }
35417Sbill 
35517Sbill dzscan()
35617Sbill {
35717Sbill 	register i;
35817Sbill 	register struct device *dzaddr;
35917Sbill 	register bit;
36017Sbill 	register struct tty *tp;
36117Sbill 
36217Sbill 	for (i = 0; i < dz_cnt ; i++) {
36317Sbill 		dzaddr = dzpdma[i].p_addr;
36417Sbill 		tp = &dz_tty[i];
36517Sbill 		bit = 1<<(i&07);
36617Sbill 		if (dzaddr->dzmsr & bit) {
36717Sbill 			/* carrier present */
36817Sbill 			if ((tp->t_state & CARR_ON) == 0) {
36917Sbill 				wakeup((caddr_t)&tp->t_rawq);
37017Sbill 				tp->t_state |= CARR_ON;
37117Sbill 			}
37217Sbill 		} else {
37317Sbill 			if ((tp->t_state & CARR_ON)) {
37417Sbill 				/* carrier lost */
37517Sbill 				signal(tp->t_pgrp, SIGHUP);
37617Sbill 				dzaddr->dzdtr &= ~bit;
37717Sbill 				flushtty(tp);
37817Sbill 			}
37917Sbill 			tp->t_state &= ~CARR_ON;
38017Sbill 		}
38117Sbill 	}
38217Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
38317Sbill }
384119Sbill 
385119Sbill dztimer()
386119Sbill {
387119Sbill 
388119Sbill 	dzrint(0);
389119Sbill }
390