xref: /csrg-svn/sys/vax/uba/dz.c (revision 2395)
1 /*	dz.c	4.10	02/10/81	*/
2 
3 #include "dz.h"
4 #if NDZ11 > 0
5 /*
6  *  DZ-11 Driver
7  */
8 #include "../h/param.h"
9 #include "../h/systm.h"
10 #include "../h/tty.h"
11 #include "../h/dir.h"
12 #include "../h/user.h"
13 #include "../h/map.h"
14 #include "../h/pte.h"
15 #include "../h/buf.h"
16 #include "../h/uba.h"
17 #include "../h/conf.h"
18 #include "../h/pdma.h"
19 #include "../h/bk.h"
20 #include "../h/file.h"
21 #include "../h/mx.h"
22 
23 /*
24  * When running dz's using only SAE (silo alarm) on input
25  * it is necessary to call dzrint() at clock interrupt time.
26  * This is unsafe unless spl5()s in tty code are changed to
27  * spl6()s to block clock interrupts.  Note that the dh driver
28  * currently in use works the same way as the dz, even though
29  * we could try to more intelligently manage its silo.
30  * Thus don't take this out if you have no dz's unless you
31  * change clock.c and dhtimer().
32  *
33  * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME.
34  */
35 #define	spl5	spl6
36 
37 int	dzcntrlr(), dzslave(), dzrint();
38 struct	uba_dinfo *dzinfo[NDZ11];
39 u_short	dzstd[] = { 0 };
40 int	(*dzivec[])() = { dzrint, 0 }; /* omit dzxint so we can do it here */
41 struct	uba_driver dzdriver =
42 	{ dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, dzinfo, dzivec };
43 
44 #define NDZ 	(NDZ11*8)
45 
46 #define BITS7	020
47 #define BITS8	030
48 #define TWOSB	040
49 #define PENABLE	0100
50 #define OPAR	0200
51 #define MSE	040		/* Master Scan Enable */
52 #define RIE	0100		/* Receiver Interrupt Enable */
53 #define	SAE	010000		/* Silo Alarm Enable */
54 #define TIE	040000		/* Transmit Interrupt Enable */
55 #define DZ_IEN	(MSE+RIE+TIE+SAE)
56 #define PERROR	010000
57 #define FRERROR	020000
58 #define	OVERRUN	040000
59 #define SSPEED	7		/* std speed = 300 baud */
60 
61 #define	dzlpr	dzrbuf
62 #define dzmsr	dzbrk
63 #define ON	1
64 #define OFF	0
65 
66 int	dzstart();
67 int	dzxint();
68 int	dzdma();
69 int	ttrstrt();
70 struct	tty dz_tty[NDZ];
71 int	dz_cnt = { NDZ };
72 int	dzact;
73 
74 struct device {
75 	short	dzcsr;
76 	short	dzrbuf;
77 	char	dztcr;
78 	char	dzdtr;
79 	char	dztbuf;
80 	char	dzbrk;
81 };
82 
83 struct	pdma dzpdma[NDZ];
84 char	dz_timer;
85 char	dz_speeds[] =
86 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
87 char	dz_brk[NDZ11];
88 
89 dzcntrlr(ui, reg)
90 	struct uba_dinfo *ui;
91 	caddr_t reg;
92 {
93 
94 	((struct device *)reg)->dzcsr |= IENABLE;
95 	/* get it to interrupt */
96 }
97 
98 dzslave(ui, reg, slaveno, uban)
99 	register struct uba_dinfo *ui;
100 	caddr_t reg;
101 {
102 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
103 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
104 	register int cnt;
105 	register int *urk = (int *)(&reg - 24);	/* white magic */
106 	caddr_t cp;
107 	int urk2;
108 
109 	for (cnt = 0; cnt < 8; cnt++) {
110 		pdp->p_addr = (struct device *)reg;
111 		pdp->p_arg = (int)tp;
112 		pdp->p_fcn = dzxint;
113 		pdp++, tp++;
114 	}
115 	if ((cp = calloc(12)) == 0)
116 		panic("dz iv nm\n");
117 	uba_hd[uban].uh_vec[*urk] = (int (*)())cp;	/* more white magic */
118 	*cp++ = 0xbb; *cp++ = 0xff; *cp++ = 0xd0;	/* black magic */
119 	*cp++ = ui->ui_unit&0x3f; *cp++ = 0x50;
120 	*cp++ = 0x17; *cp++ = 0x9f;
121 	urk2 = (int)dzdma;
122 	for (cnt = 0; cnt < 4; cnt++)
123 		*cp++ = urk2, urk2 >>= 4;		/* the spell ends */
124 	return (1);
125 }
126 
127 /*ARGSUSED*/
128 dzopen(dev, flag)
129 	dev_t dev;
130 {
131 	register struct tty *tp;
132 	register int unit;
133 	extern dzscan();
134 
135 	unit = minor(dev);
136 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
137 		u.u_error = ENXIO;
138 		return;
139 	}
140 	if (dz_timer == 0) {
141 		dz_timer++;
142 		timeout(dzscan, (caddr_t)0, 60);
143 	}
144 	tp = &dz_tty[unit];
145 	tp->t_addr = (caddr_t)&dzpdma[unit];
146 	tp->t_oproc = dzstart;
147 	tp->t_iproc = NULL;
148 	tp->t_state |= WOPEN;
149 	if ((tp->t_state & ISOPEN) == 0) {
150 		ttychars(tp);
151 		tp->t_ospeed = tp->t_ispeed = SSPEED;
152 		tp->t_flags = ODDP|EVENP|ECHO;
153 		/*tp->t_state |= HUPCLS;*/
154 		dzparam(unit);
155 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
156 		u.u_error = EBUSY;
157 		return;
158 	}
159 	dzmodem(unit, ON);
160 	(void) spl5();
161 	while ((tp->t_state & CARR_ON) == 0) {
162 		tp->t_state |= WOPEN;
163 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
164 	}
165 	(void) spl0();
166 	(*linesw[tp->t_line].l_open)(dev, tp);
167 }
168 
169 /*ARGSUSED*/
170 dzclose(dev, flag)
171 	dev_t dev;
172 {
173 	register struct tty *tp;
174 	register int unit;
175 	int dz;
176 
177 	unit = minor(dev);
178 	dz = unit >> 3;
179 	tp = &dz_tty[unit];
180 	(*linesw[tp->t_line].l_close)(tp);
181 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
182 	    (dz_brk[dz] &= ~(1 << (unit&07)));
183 	if (tp->t_state & HUPCLS)
184 		dzmodem(unit, OFF);
185 	ttyclose(tp);
186 }
187 
188 dzread(dev)
189 	dev_t dev;
190 {
191 	register struct tty *tp;
192 
193 	tp = &dz_tty[minor(dev)];
194 	(*linesw[tp->t_line].l_read)(tp);
195 }
196 
197 dzwrite(dev)
198 	dev_t dev;
199 {
200 	register struct tty *tp;
201 
202 	tp = &dz_tty[minor(dev)];
203 	(*linesw[tp->t_line].l_write)(tp);
204 }
205 
206 /*ARGSUSED*/
207 dzrint(dz)
208 	int dz;
209 {
210 	register struct tty *tp;
211 	register int c;
212 	register struct device *dzaddr;
213 	register struct tty *tp0;
214 	register int unit;
215 	int s;
216 
217 	s = spl6();	/* see comment in clock.c */
218 	/* as long as we are here, service them all */
219 	for (unit = 0; unit < NDZ; unit += 8) {
220 		if ((dzact & (1<<(unit>>3))) == 0)
221 			continue;
222 		dzaddr = dzpdma[unit].p_addr;
223 		tp0 = &dz_tty[unit];
224 		while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
225 			tp = tp0 + ((c>>8)&07);
226 			if (tp >= &dz_tty[dz_cnt])
227 				continue;
228 			if ((tp->t_state & ISOPEN) == 0) {
229 				wakeup((caddr_t)&tp->t_rawq);
230 				continue;
231 			}
232 			if (c&FRERROR)
233 				/* framing error = break */
234 				if (tp->t_flags & RAW)
235 					c = 0;		/* null for getty */
236 				else
237 #ifdef IIASA
238 					continue;
239 #else
240 					c = tun.t_intrc;
241 #endif
242 			if (c&OVERRUN)
243 				printf("o");
244 			if (c&PERROR)
245 				/* parity error */
246 				if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
247 				  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
248 					continue;
249 			if (tp->t_line == NETLDISC) {
250 				c &= 0177;
251 				BKINPUT(c, tp);
252 			} else
253 				(*linesw[tp->t_line].l_rint)(c, tp);
254 		}
255 	}
256 	splx(s);
257 }
258 
259 /*ARGSUSED*/
260 dzioctl(dev, cmd, addr, flag)
261 	dev_t dev;
262 	caddr_t addr;
263 {
264 	register struct tty *tp;
265 	register int unit = minor(dev);
266 	register int dz = unit >> 3;
267 
268 	tp = &dz_tty[unit];
269 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
270 	if (cmd == 0)
271 		return;
272 	if (ttioctl(tp, cmd, addr, flag)) {
273 		if (cmd==TIOCSETP || cmd==TIOCSETN)
274 			dzparam(unit);
275 	} else switch(cmd) {
276 
277 	case TIOCSBRK:
278 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
279 			(dz_brk[dz] |= 1 << (unit&07));
280 		break;
281 	case TIOCCBRK:
282 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
283 			(dz_brk[dz] &= ~(1 << (unit&07)));
284 		break;
285 	case TIOCSDTR:
286 		dzmodem(unit, ON);
287 		break;
288 	case TIOCCDTR:
289 		dzmodem(unit, OFF);
290 		break;
291 	default:
292 		u.u_error = ENOTTY;
293 	}
294 }
295 
296 dzparam(unit)
297 	register int unit;
298 {
299 	register struct tty *tp;
300 	register struct device *dzaddr;
301 	register int lpr;
302 
303 	tp = &dz_tty[unit];
304 	dzaddr = dzpdma[unit].p_addr;
305 	dzaddr->dzcsr = DZ_IEN;
306 	dzact |= (1<<(unit>>3));
307 	if (tp->t_ispeed == 0) {
308 		dzmodem(unit, OFF);		/* hang up line */
309 		return;
310 	}
311 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
312 #ifndef IIASA
313 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
314 		lpr |= BITS8;
315 	else
316 		lpr |= (BITS7|PENABLE);
317 	if ((tp->t_flags & EVENP) == 0)
318 		lpr |= OPAR;
319 #else IIASA
320 	if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP))
321 		lpr |= BITS8;
322 	else if (tp->t_flags & EVENP)
323 		lpr |= (BITS7|PENABLE);
324 	else if (tp->t_flags & ODDP)
325 		lpr |= (BITS7|OPAR|PENABLE);
326 	else
327 		lpr |= BITS7;
328 #endif IIASA
329 	if (tp->t_ispeed == 3)
330 		lpr |= TWOSB; 			/* 110 baud: 2 stop bits */
331 	dzaddr->dzlpr = lpr;
332 }
333 
334 dzxint(tp)
335 	register struct tty *tp;
336 {
337 	register struct pdma *dp;
338 	register s;
339 	s = spl6();	/* block the clock */
340 
341 	dp = (struct pdma *)tp->t_addr;
342 	tp->t_state &= ~BUSY;
343 	if (tp->t_state & FLUSH)
344 		tp->t_state &= ~FLUSH;
345 	else
346 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
347 	if (tp->t_line)
348 		(*linesw[tp->t_line].l_start)(tp);
349 	else
350 		dzstart(tp);
351 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
352 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
353 	splx(s);
354 }
355 
356 dzstart(tp)
357 	register struct tty *tp;
358 {
359 	register struct pdma *dp;
360 	register struct device *dzaddr;
361 	register int cc;
362 	int s;
363 
364 	dp = (struct pdma *)tp->t_addr;
365 	dzaddr = dp->p_addr;
366 	s = spl5();
367 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
368 		goto out;
369 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
370 		tp->t_state &= ~ASLEEP;
371 		if (tp->t_chan)
372 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
373 		else
374 			wakeup((caddr_t)&tp->t_outq);
375 	}
376 	if (tp->t_outq.c_cc == 0)
377 		goto out;
378 	if (tp->t_flags&RAW)
379 		cc = ndqb(&tp->t_outq, 0);
380 	else {
381 		cc = ndqb(&tp->t_outq, 0200);
382 		if (cc == 0) {
383 			cc = getc(&tp->t_outq);
384 			timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
385 			tp->t_state |= TIMEOUT;
386 			goto out;
387 		}
388 	}
389 	tp->t_state |= BUSY;
390 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
391 	dp->p_end += cc;
392 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);
393 out:
394 	splx(s);
395 }
396 
397 /*
398  * Stop output on a line.
399  * Assume call is made at spl6.
400  */
401 /*ARGSUSED*/
402 dzstop(tp, flag)
403 	register struct tty *tp;
404 {
405 	register struct pdma *dp;
406 	register int s;
407 
408 	dp = (struct pdma *)tp->t_addr;
409 	s = spl6();
410 	if (tp->t_state & BUSY) {
411 		dp->p_end = dp->p_mem;
412 		if ((tp->t_state&TTSTOP)==0)
413 			tp->t_state |= FLUSH;
414 	}
415 	splx(s);
416 }
417 
418 dzmodem(unit, flag)
419 	register int unit;
420 {
421 	register struct device *dzaddr;
422 	register char bit;
423 
424 	dzaddr = dzpdma[unit].p_addr;
425 	bit = 1<<(unit&07);
426 	if (flag == OFF)
427 		dzaddr->dzdtr &= ~bit;
428 	else
429 		dzaddr->dzdtr |= bit;
430 }
431 
432 dzscan()
433 {
434 	register i;
435 	register struct device *dzaddr;
436 	register bit;
437 	register struct tty *tp;
438 
439 	for (i = 0; i < dz_cnt ; i++) {
440 		dzaddr = dzpdma[i].p_addr;
441 		tp = &dz_tty[i];
442 		bit = 1<<(i&07);
443 		if (dzaddr->dzmsr & bit || (i == 6 || i == 7)) {
444 			/* carrier present */
445 			if ((tp->t_state & CARR_ON) == 0) {
446 				wakeup((caddr_t)&tp->t_rawq);
447 				tp->t_state |= CARR_ON;
448 			}
449 		} else {
450 			if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) {
451 				/* carrier lost */
452 				if (tp->t_state&ISOPEN) {
453 					gsignal(tp->t_pgrp, SIGHUP);
454 					gsignal(tp->t_pgrp, SIGCONT);
455 					dzaddr->dzdtr &= ~bit;
456 					flushtty(tp, FREAD|FWRITE);
457 				}
458 				tp->t_state &= ~CARR_ON;
459 			}
460 		}
461 	}
462 	timeout(dzscan, (caddr_t)0, 2*HZ);
463 }
464 
465 dztimer()
466 {
467 
468 	dzrint(0);
469 }
470 
471 /*
472  * Reset state of driver if UBA reset was necessary.
473  * Reset parameters and restart transmission on open lines.
474  */
475 dzreset(uban)
476 {
477 	register int unit;
478 	register struct tty *tp;
479 
480 	/*** WE SHOULD LOOK TO SEE IF WE CARE ABOUT UBA BEING RESET ***/
481 
482 	printf(" dz");
483 	for (unit = 0; unit < NDZ; unit++) {
484 		tp = &dz_tty[unit];
485 		if (tp->t_state & (ISOPEN|WOPEN)) {
486 			dzparam(unit);
487 			dzmodem(unit, ON);
488 			tp->t_state &= ~BUSY;
489 			dzstart(tp);
490 		}
491 	}
492 	dztimer();
493 }
494 #endif
495