xref: /csrg-svn/sys/vax/uba/dz.c (revision 17)
1*17Sbill /*	dz.c	3.1	10/14/12	*/
2*17Sbill 
3*17Sbill /*
4*17Sbill  *  DZ-11 Driver
5*17Sbill  */
6*17Sbill #include "../h/param.h"
7*17Sbill #include "../h/systm.h"
8*17Sbill #include "../h/tty.h"
9*17Sbill #include "../h/dir.h"
10*17Sbill #include "../h/user.h"
11*17Sbill #include "../h/map.h"
12*17Sbill #include "../h/pte.h"
13*17Sbill #include "../h/uba.h"
14*17Sbill #include "../h/conf.h"
15*17Sbill #include "../h/pdma.h"
16*17Sbill 
17*17Sbill #define DZADDR  (UBA0_DEV + 0160100)
18*17Sbill #ifdef ERNIE
19*17Sbill #define NDZ 	(3*8)
20*17Sbill #else
21*17Sbill #define	NDZ	(8)
22*17Sbill #endif
23*17Sbill 
24*17Sbill #define BITS7	020
25*17Sbill #define BITS8	030
26*17Sbill #define TWOSB	040
27*17Sbill #define PENABLE	0100
28*17Sbill #define OPAR	0200
29*17Sbill #define MSE	040		/* Master Scan Enable */
30*17Sbill #define RIE	0100		/* Receiver Interrupt Enable */
31*17Sbill #define TIE	040000		/* Transmit interrupt enable */
32*17Sbill #define DZ_IEN	(MSE+RIE+TIE)
33*17Sbill #define PERROR	010000
34*17Sbill #define FRERROR	020000
35*17Sbill #define SSPEED	7		/* std speed = 300 baud */
36*17Sbill 
37*17Sbill 
38*17Sbill #define	dzlpr	dzrbuf
39*17Sbill #define dzmsr	dzbrk
40*17Sbill #define ON	1
41*17Sbill #define OFF	0
42*17Sbill 
43*17Sbill int	dzstart();
44*17Sbill int	dzxint();
45*17Sbill struct	tty dz_tty[NDZ];
46*17Sbill int	dz_cnt = { NDZ };
47*17Sbill 
48*17Sbill struct device {
49*17Sbill 	short	dzcsr;
50*17Sbill 	short	dzrbuf;
51*17Sbill 	char	dztcr;
52*17Sbill 	char	dzdtr;
53*17Sbill 	char	dztbuf;
54*17Sbill 	char	dzbrk;
55*17Sbill };
56*17Sbill 
57*17Sbill struct pdma dzpdma[] = {
58*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[0], dzxint,
59*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[1], dzxint,
60*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[2], dzxint,
61*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[3], dzxint,
62*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[4], dzxint,
63*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[5], dzxint,
64*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[6], dzxint,
65*17Sbill 	(struct device *)(DZADDR), NULL, NULL, (int)&dz_tty[7], dzxint,
66*17Sbill #ifdef ERNIE
67*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[8], dzxint,
68*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[9], dzxint,
69*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[10], dzxint,
70*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[11], dzxint,
71*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[12], dzxint,
72*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[13], dzxint,
73*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[14], dzxint,
74*17Sbill 	(struct device *)(DZADDR+010), NULL, NULL, (int)&dz_tty[15], dzxint,
75*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[16], dzxint,
76*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[17], dzxint,
77*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[18], dzxint,
78*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[19], dzxint,
79*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[20], dzxint,
80*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[21], dzxint,
81*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[22], dzxint,
82*17Sbill 	(struct device *)(DZADDR+020), NULL, NULL, (int)&dz_tty[23], dzxint,
83*17Sbill #endif
84*17Sbill };
85*17Sbill char	dz_timer;
86*17Sbill char	dz_speeds[] = {
87*17Sbill 	0, 020 , 021 , 022 , 023 , 024 , 0, 025,
88*17Sbill 	026 , 027 , 030 , 032 , 034 , 036 , 0 , 0,
89*17Sbill };
90*17Sbill 
91*17Sbill /*ARGSUSED*/
92*17Sbill dzopen(d, flag)
93*17Sbill {
94*17Sbill 	register struct tty *tp;
95*17Sbill 	register dev;
96*17Sbill 	extern dzscan();
97*17Sbill 
98*17Sbill 	dev = minor(d);
99*17Sbill 	if (dev >= dz_cnt) {
100*17Sbill 		u.u_error = ENXIO;
101*17Sbill 		return;
102*17Sbill 	}
103*17Sbill 	if (dz_timer == 0) {
104*17Sbill 		dz_timer++;
105*17Sbill 		timeout(dzscan, (caddr_t)0, 60);
106*17Sbill 	}
107*17Sbill 	tp = &dz_tty[dev];
108*17Sbill 	tp->t_addr = (caddr_t)&dzpdma[dev];
109*17Sbill 	tp->t_oproc = dzstart;
110*17Sbill 	tp->t_iproc = NULL;
111*17Sbill 	tp->t_state |= WOPEN;
112*17Sbill 	if ((tp->t_state & ISOPEN) == 0) {
113*17Sbill 		ttychars(tp);
114*17Sbill 		tp->t_ospeed = tp->t_ispeed = SSPEED;
115*17Sbill 		tp->t_flags = ODDP|EVENP|ECHO;
116*17Sbill 		/*tp->t_state |= HUPCLS;*/
117*17Sbill 		dzparam(dev);
118*17Sbill 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
119*17Sbill 		u.u_error = EBUSY;
120*17Sbill 		return;
121*17Sbill 	}
122*17Sbill 	dzmodem(dev, ON);
123*17Sbill 	VOID spl5();
124*17Sbill 	while ((tp->t_state & CARR_ON) == 0) {
125*17Sbill 		tp->t_state |= WOPEN;
126*17Sbill 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
127*17Sbill 	}
128*17Sbill 	VOID spl0();
129*17Sbill 	(*linesw[tp->t_line].l_open)(d, tp);
130*17Sbill }
131*17Sbill 
132*17Sbill dzclose(d)
133*17Sbill {
134*17Sbill 	register struct tty *tp;
135*17Sbill 	register dev;
136*17Sbill 
137*17Sbill 	dev = minor(d);
138*17Sbill 	tp = &dz_tty[dev];
139*17Sbill 	(*linesw[tp->t_line].l_close)(tp);
140*17Sbill 	if (tp->t_state & HUPCLS)
141*17Sbill 		dzmodem(dev, OFF);
142*17Sbill 	ttyclose(tp);
143*17Sbill }
144*17Sbill 
145*17Sbill dzread(d)
146*17Sbill {
147*17Sbill 	register struct tty *tp;
148*17Sbill 
149*17Sbill 	tp = &dz_tty[minor(d)];
150*17Sbill 	(*linesw[tp->t_line].l_read)(tp);
151*17Sbill }
152*17Sbill 
153*17Sbill dzwrite(d)
154*17Sbill {
155*17Sbill 	register struct tty *tp;
156*17Sbill 
157*17Sbill 	tp = &dz_tty[minor(d)];
158*17Sbill 	(*linesw[tp->t_line].l_write)(tp);
159*17Sbill }
160*17Sbill 
161*17Sbill dzrint(dev)
162*17Sbill {
163*17Sbill 	register struct tty *tp;
164*17Sbill 	register int c;
165*17Sbill 	register struct device *dzaddr;
166*17Sbill 
167*17Sbill 	dzaddr = dzpdma[dev*8].p_addr;
168*17Sbill 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
169*17Sbill 		tp = &dz_tty[((c>>8)&07)|(dev<<3)];
170*17Sbill 		if (tp >= &dz_tty[dz_cnt])
171*17Sbill 			continue;
172*17Sbill 		if ((tp->t_state & ISOPEN) == 0) {
173*17Sbill 			wakeup((caddr_t)&tp->t_rawq);
174*17Sbill 			continue;
175*17Sbill 		}
176*17Sbill 		if (c & FRERROR)
177*17Sbill 			/* framing error = break */
178*17Sbill 			if (tp->t_flags & RAW)
179*17Sbill 				c = 0;		/* null for getty */
180*17Sbill 			else
181*17Sbill 				c = 0177;	/* DEL = interrupt */
182*17Sbill 		if (c & PERROR)
183*17Sbill 			/* parity error */
184*17Sbill 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
185*17Sbill 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
186*17Sbill 				continue;
187*17Sbill 		(*linesw[tp->t_line].l_rint)(c, tp);
188*17Sbill 	}
189*17Sbill }
190*17Sbill 
191*17Sbill /*ARGSUSED*/
192*17Sbill dzioctl(dev, cmd, addr, flag)
193*17Sbill caddr_t addr;
194*17Sbill dev_t dev;
195*17Sbill {
196*17Sbill 	register struct tty *tp;
197*17Sbill 
198*17Sbill 	tp = &dz_tty[minor(dev)];
199*17Sbill 	if (ttioccomm(cmd, tp, addr, dev)) {
200*17Sbill 		if (cmd==TIOCSETP || cmd==TIOCSETN)
201*17Sbill 			dzparam(minor(dev));
202*17Sbill 	} else
203*17Sbill 		u.u_error = ENOTTY;
204*17Sbill }
205*17Sbill 
206*17Sbill dzparam(dev)
207*17Sbill {
208*17Sbill 	register struct tty *tp;
209*17Sbill 	register struct device *dzaddr;
210*17Sbill 	register short lpr;
211*17Sbill 
212*17Sbill 	tp = &dz_tty[dev];
213*17Sbill 	dzaddr = dzpdma[dev].p_addr;
214*17Sbill 	dzaddr->dzcsr = DZ_IEN;
215*17Sbill 	if (tp->t_ispeed == 0) {
216*17Sbill 		dzmodem(dev, OFF);		/* hang up line */
217*17Sbill 		return;
218*17Sbill 	}
219*17Sbill 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (dev & 07);
220*17Sbill 	if (tp->t_flags & RAW)
221*17Sbill 		lpr |= BITS8;
222*17Sbill 	else
223*17Sbill 		lpr |= (BITS7|PENABLE);
224*17Sbill 	if ((tp->t_flags & EVENP) == 0)
225*17Sbill 		lpr |= OPAR;
226*17Sbill 	if (tp->t_ispeed == 3)
227*17Sbill 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
228*17Sbill 	dzaddr->dzlpr = lpr;
229*17Sbill }
230*17Sbill 
231*17Sbill dzxint(tp)
232*17Sbill register struct tty *tp;
233*17Sbill {
234*17Sbill 	register struct pdma *dp;
235*17Sbill 
236*17Sbill 	dp = &dzpdma[tp-dz_tty];
237*17Sbill 	tp->t_state &= ~BUSY;
238*17Sbill 	if (tp->t_state & FLUSH)
239*17Sbill 		tp->t_state &= ~FLUSH;
240*17Sbill 	else
241*17Sbill 		ndflush(&tp->t_outq, dp->p_end-tp->t_outq.c_cf);
242*17Sbill 	if (tp->t_line)
243*17Sbill 		(*linesw[tp->t_line].l_start)(tp);
244*17Sbill 	else
245*17Sbill 		dzstart(tp);
246*17Sbill 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
247*17Sbill 		dp->p_addr->dztcr &= ~(1 << ((tp-dz_tty) % 8));
248*17Sbill }
249*17Sbill 
250*17Sbill dzstart(tp)
251*17Sbill register struct tty *tp;
252*17Sbill {
253*17Sbill 	register struct pdma *dp;
254*17Sbill 	register struct device *dzaddr;
255*17Sbill 	register cc;
256*17Sbill 	int sps;
257*17Sbill 	extern ttrstrt();
258*17Sbill 
259*17Sbill 	dp = &dzpdma[tp-dz_tty];
260*17Sbill 	dzaddr = dp->p_addr;
261*17Sbill 	sps = spl5();
262*17Sbill 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
263*17Sbill 		goto out;
264*17Sbill 	if (tp->t_outq.c_cc <= TTLOWAT && tp->t_state&ASLEEP) {
265*17Sbill 		tp->t_state &= ~ASLEEP;
266*17Sbill 		if (tp->t_chan)
267*17Sbill 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
268*17Sbill 		else
269*17Sbill 			wakeup((caddr_t)&tp->t_outq);
270*17Sbill 	}
271*17Sbill 	if (tp->t_outq.c_cc == 0)
272*17Sbill 		goto out;
273*17Sbill 	if (tp->t_flags&RAW)
274*17Sbill 		cc = ndqb(&tp->t_outq, 0);
275*17Sbill 	else {
276*17Sbill 		cc = ndqb(&tp->t_outq, 0200);
277*17Sbill 		if (cc == 0) {
278*17Sbill 			cc = getc(&tp->t_outq);
279*17Sbill 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
280*17Sbill 			tp->t_state |= TIMEOUT;
281*17Sbill 			goto out;
282*17Sbill 		}
283*17Sbill 	}
284*17Sbill 	tp->t_state |= BUSY;
285*17Sbill 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
286*17Sbill 	dp->p_end += cc;
287*17Sbill 	dzaddr->dztcr |= 1 << ((tp-dz_tty) % 8);
288*17Sbill    out:
289*17Sbill 	splx(sps);
290*17Sbill }
291*17Sbill 
292*17Sbill /*
293*17Sbill  * Stop output on a line.
294*17Sbill  * Assume call is made at spl6.
295*17Sbill  */
296*17Sbill /*ARGSUSED*/
297*17Sbill dzstop(tp, flag)
298*17Sbill register struct tty *tp;
299*17Sbill {
300*17Sbill 	register struct pdma *dp;
301*17Sbill 	register int s;
302*17Sbill 
303*17Sbill 	dp = &dzpdma[tp-dz_tty];
304*17Sbill 	s = spl6();
305*17Sbill 	if (tp->t_state & BUSY) {
306*17Sbill 		dp->p_end = dp->p_mem;
307*17Sbill 		if ((tp->t_state&TTSTOP)==0) {
308*17Sbill 			tp->t_state |= FLUSH;
309*17Sbill 		}
310*17Sbill 	}
311*17Sbill 	splx(s);
312*17Sbill }
313*17Sbill 
314*17Sbill dzmodem(dev, flag)
315*17Sbill register int dev;
316*17Sbill {
317*17Sbill 	register struct device *dzaddr;
318*17Sbill 	register char bit;
319*17Sbill 
320*17Sbill 	dzaddr = dzpdma[dev].p_addr;
321*17Sbill 	bit = 1<<(dev&07);
322*17Sbill 	if (flag == OFF)
323*17Sbill 		dzaddr->dzdtr &= ~bit;
324*17Sbill 	else
325*17Sbill 		dzaddr->dzdtr |= bit;
326*17Sbill }
327*17Sbill 
328*17Sbill dzscan()
329*17Sbill {
330*17Sbill 	register i;
331*17Sbill 	register struct device *dzaddr;
332*17Sbill 	register bit;
333*17Sbill 	register struct tty *tp;
334*17Sbill 
335*17Sbill 	for (i = 0; i < dz_cnt ; i++) {
336*17Sbill 		dzaddr = dzpdma[i].p_addr;
337*17Sbill 		tp = &dz_tty[i];
338*17Sbill 		bit = 1<<(i&07);
339*17Sbill 		if (dzaddr->dzmsr & bit) {
340*17Sbill 			/* carrier present */
341*17Sbill 			if ((tp->t_state & CARR_ON) == 0) {
342*17Sbill 				wakeup((caddr_t)&tp->t_rawq);
343*17Sbill 				tp->t_state |= CARR_ON;
344*17Sbill 			}
345*17Sbill 		} else {
346*17Sbill 			if ((tp->t_state & CARR_ON)) {
347*17Sbill 				/* carrier lost */
348*17Sbill 				signal(tp->t_pgrp, SIGHUP);
349*17Sbill 				dzaddr->dzdtr &= ~bit;
350*17Sbill 				flushtty(tp);
351*17Sbill 			}
352*17Sbill 			tp->t_state &= ~CARR_ON;
353*17Sbill 		}
354*17Sbill 	}
355*17Sbill 	timeout(dzscan, (caddr_t)0, 2*HZ);
356*17Sbill }
357