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