xref: /original-bsd/sys/vax/uba/dz.c (revision 0fc6f013)
1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)dz.c	6.11 (Berkeley) 04/12/86
7  */
8 
9 #include "dz.h"
10 #if NDZ > 0
11 /*
12  *  DZ-11/DZ-32 Driver
13  *
14  * This driver mimics dh.c; see it for explanation of common code.
15  */
16 #include "bk.h"
17 
18 #include "../machine/pte.h"
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "ioctl.h"
23 #include "tty.h"
24 #include "dir.h"
25 #include "user.h"
26 #include "proc.h"
27 #include "map.h"
28 #include "buf.h"
29 #include "vm.h"
30 #include "conf.h"
31 #include "bkmac.h"
32 #include "file.h"
33 #include "uio.h"
34 #include "kernel.h"
35 #include "syslog.h"
36 
37 #include "pdma.h"
38 #include "ubavar.h"
39 #include "dzreg.h"
40 
41 /*
42  * Driver information for auto-configuration stuff.
43  */
44 int	dzprobe(), dzattach(), dzrint();
45 struct	uba_device *dzinfo[NDZ];
46 u_short	dzstd[] = { 0 };
47 struct	uba_driver dzdriver =
48 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
49 
50 #define	NDZLINE 	(NDZ*8)
51 #define	FASTTIMER	(hz/30)		/* rate to drain silos, when in use */
52 
53 int	dzstart(), dzxint(), dzdma();
54 int	ttrstrt();
55 struct	tty dz_tty[NDZLINE];
56 int	dz_cnt = { NDZLINE };
57 int	dzact;
58 int	dzsilos;			/* mask of dz's with silo in use */
59 int	dzchars[NDZ];			/* recent input count */
60 int	dzrate[NDZ];			/* smoothed input count */
61 int	dztimerintvl;			/* time interval for dztimer */
62 int	dzhighrate = 100;		/* silo on if dzchars > dzhighrate */
63 int	dzlowrate = 75;			/* silo off if dzrate < dzlowrate */
64 
65 #define dzwait(x)	while (((x)->dzlcs & DZ_ACK) == 0)
66 
67 /*
68  * Software copy of dzbrk since it isn't readable
69  */
70 char	dz_brk[NDZ];
71 char	dzsoftCAR[NDZ];
72 char	dz_lnen[NDZ];	/* saved line enable bits for DZ32 */
73 
74 /*
75  * The dz11 doesn't interrupt on carrier transitions, so
76  * we have to use a timer to watch it.
77  */
78 char	dz_timer;		/* timer started? */
79 
80 /*
81  * Pdma structures for fast output code
82  */
83 struct	pdma dzpdma[NDZLINE];
84 
85 char	dz_speeds[] =
86 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
87 
88 #ifndef	PORTSELECTOR
89 #define	ISPEED	B9600
90 #define	IFLAGS	(EVENP|ODDP|ECHO)
91 #else
92 #define	ISPEED	B4800
93 #define	IFLAGS	(EVENP|ODDP)
94 #endif
95 
96 dzprobe(reg)
97 	caddr_t reg;
98 {
99 	register int br, cvec;
100 	register struct dzdevice *dzaddr = (struct dzdevice *)reg;
101 
102 #ifdef lint
103 	br = 0; cvec = br; br = cvec;
104 	dzrint(0); dzxint((struct tty *)0);
105 #endif
106 	dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
107 	if (dzaddr->dzcsr & DZ_32)
108 		dzaddr->dzlnen = 1;
109 	else
110 		dzaddr->dztcr = 1;		/* enable any line */
111 	DELAY(100000);
112 	dzaddr->dzcsr = DZ_CLR|DZ_32;		/* reset everything */
113 	if (cvec && cvec != 0x200)
114 		cvec -= 4;
115 	return (sizeof (struct dzdevice));
116 }
117 
118 dzattach(ui)
119 	register struct uba_device *ui;
120 {
121 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
122 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
123 	register int cntr;
124 	extern dzscan();
125 
126 	for (cntr = 0; cntr < 8; cntr++) {
127 		pdp->p_addr = (struct dzdevice *)ui->ui_addr;
128 		pdp->p_arg = (int)tp;
129 		pdp->p_fcn = dzxint;
130 		pdp++, tp++;
131 	}
132 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
133 	if (dz_timer == 0) {
134 		dz_timer++;
135 		timeout(dzscan, (caddr_t)0, hz);
136 		dztimerintvl = FASTTIMER;
137 	}
138 }
139 
140 /*ARGSUSED*/
141 dzopen(dev, flag)
142 	dev_t dev;
143 {
144 	register struct tty *tp;
145 	register int unit;
146 
147 	unit = minor(dev);
148 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
149 		return (ENXIO);
150 	tp = &dz_tty[unit];
151 	tp->t_addr = (caddr_t)&dzpdma[unit];
152 	tp->t_oproc = dzstart;
153 	if ((tp->t_state & TS_ISOPEN) == 0) {
154 		ttychars(tp);
155 #ifndef PORTSELECTOR
156 		if (tp->t_ispeed == 0) {
157 #else
158 			tp->t_state |= TS_HUPCLS;
159 #endif PORTSELECTOR
160 			tp->t_ispeed = ISPEED;
161 			tp->t_ospeed = ISPEED;
162 			tp->t_flags = IFLAGS;
163 #ifndef PORTSELECTOR
164 		}
165 #endif PORTSELECTOR
166 		dzparam(unit);
167 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
168 		return (EBUSY);
169 	(void) dzmctl(dev, DZ_ON, DMSET);
170 	(void) spl5();
171 	while ((tp->t_state & TS_CARR_ON) == 0) {
172 		tp->t_state |= TS_WOPEN;
173 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
174 	}
175 	(void) spl0();
176 	return ((*linesw[tp->t_line].l_open)(dev, tp));
177 }
178 
179 /*ARGSUSED*/
180 dzclose(dev, flag)
181 	dev_t dev;
182 {
183 	register struct tty *tp;
184 	register int unit;
185 	register struct dzdevice *dzaddr;
186 	int dz;
187 
188 	unit = minor(dev);
189 	dz = unit >> 3;
190 	tp = &dz_tty[unit];
191 	(*linesw[tp->t_line].l_close)(tp);
192 	dzaddr = dzpdma[unit].p_addr;
193 	if (dzaddr->dzcsr&DZ_32)
194 		(void) dzmctl(dev, DZ_BRK, DMBIC);
195 	else
196 		dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
197 	if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
198 		(void) dzmctl(dev, DZ_OFF, DMSET);
199 	ttyclose(tp);
200 }
201 
202 dzread(dev, uio)
203 	dev_t dev;
204 	struct uio *uio;
205 {
206 	register struct tty *tp;
207 
208 	tp = &dz_tty[minor(dev)];
209 	return ((*linesw[tp->t_line].l_read)(tp, uio));
210 }
211 
212 dzwrite(dev, uio)
213 	dev_t dev;
214 	struct uio *uio;
215 {
216 	register struct tty *tp;
217 
218 	tp = &dz_tty[minor(dev)];
219 	return ((*linesw[tp->t_line].l_write)(tp, uio));
220 }
221 
222 /*ARGSUSED*/
223 dzrint(dz)
224 	int dz;
225 {
226 	register struct tty *tp;
227 	register int c;
228 	register struct dzdevice *dzaddr;
229 	register struct tty *tp0;
230 	register int unit;
231 	int overrun = 0;
232 
233 	if ((dzact & (1<<dz)) == 0)
234 		return;
235 	unit = dz * 8;
236 	dzaddr = dzpdma[unit].p_addr;
237 	tp0 = &dz_tty[unit];
238 	dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE);	/* the manual says this song */
239 	dzaddr->dzcsr |= DZ_RIE|DZ_MIE;		/*   and dance is necessary */
240 	while (dzaddr->dzcsr & DZ_MSC) {	/* DZ32 modem change interrupt */
241 		c = dzaddr->dzmtsr;
242 		tp = tp0 + (c&7);
243 		if (tp >= &dz_tty[dz_cnt])
244 			break;
245 		dzaddr->dzlcs = c&7;	/* get status of modem lines */
246 		dzwait(dzaddr);		/* wait for them */
247 		if (c & DZ_CD)		/* carrier status change? */
248 		if (dzaddr->dzlcs & DZ_CD) {	/* carrier up? */
249 			/* carrier present */
250 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
251 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
252 			dzaddr->dzlcs = DZ_ACK|(c&7);
253 	}
254 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
255 		dzchars[dz]++;
256 		tp = tp0 + ((c>>8)&07);
257 		if (tp >= &dz_tty[dz_cnt])
258 			continue;
259 		if ((tp->t_state & TS_ISOPEN) == 0) {
260 			wakeup((caddr_t)&tp->t_rawq);
261 #ifdef PORTSELECTOR
262 			if ((tp->t_state&TS_WOPEN) == 0)
263 #endif
264 				continue;
265 		}
266 		if (c&DZ_FE)
267 			if (tp->t_flags & RAW)
268 				c = 0;
269 			else
270 				c = tp->t_intrc;
271 		if (c&DZ_DO && overrun == 0) {
272 			log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
273 			overrun = 1;
274 		}
275 		if (c&DZ_PE)
276 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
277 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
278 				continue;
279 #if NBK > 0
280 		if (tp->t_line == NETLDISC) {
281 			c &= 0177;
282 			BKINPUT(c, tp);
283 		} else
284 #endif
285 			(*linesw[tp->t_line].l_rint)(c, tp);
286 	}
287 }
288 
289 /*ARGSUSED*/
290 dzioctl(dev, cmd, data, flag)
291 	dev_t dev;
292 	caddr_t data;
293 {
294 	register struct tty *tp;
295 	register int unit = minor(dev);
296 	register int dz = unit >> 3;
297 	register struct dzdevice *dzaddr;
298 	int error;
299 
300 	tp = &dz_tty[unit];
301 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
302 	if (error >= 0)
303 		return (error);
304 	error = ttioctl(tp, cmd, data, flag);
305 	if (error >= 0) {
306 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
307 		    cmd == TIOCLBIC || cmd == TIOCLSET)
308 			dzparam(unit);
309 		return (error);
310 	}
311 	switch (cmd) {
312 
313 	case TIOCSBRK:
314 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
315 		if (dzaddr->dzcsr&DZ_32)
316 			(void) dzmctl(dev, DZ_BRK, DMBIS);
317 		else
318 			dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
319 		break;
320 
321 	case TIOCCBRK:
322 		dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
323 		if (dzaddr->dzcsr&DZ_32)
324 			(void) dzmctl(dev, DZ_BRK, DMBIC);
325 		else
326 			dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
327 		break;
328 
329 	case TIOCSDTR:
330 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
331 		break;
332 
333 	case TIOCCDTR:
334 		(void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
335 		break;
336 
337 	case TIOCMSET:
338 		(void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
339 		break;
340 
341 	case TIOCMBIS:
342 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
343 		break;
344 
345 	case TIOCMBIC:
346 		(void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
347 		break;
348 
349 	case TIOCMGET:
350 		*(int *)data = dztodm(dzmctl(dev, 0, DMGET));
351 		break;
352 
353 	default:
354 		return (ENOTTY);
355 	}
356 	return (0);
357 }
358 
359 dmtodz(bits)
360 	register int bits;
361 {
362 	register int b;
363 
364 	b = (bits >>1) & 0370;
365 	if (bits & DML_ST) b |= DZ_ST;
366 	if (bits & DML_RTS) b |= DZ_RTS;
367 	if (bits & DML_DTR) b |= DZ_DTR;
368 	if (bits & DML_LE) b |= DZ_LE;
369 	return(b);
370 }
371 
372 dztodm(bits)
373 	register int bits;
374 {
375 	register int b;
376 
377 	b = (bits << 1) & 0360;
378 	if (bits & DZ_DSR) b |= DML_DSR;
379 	if (bits & DZ_DTR) b |= DML_DTR;
380 	if (bits & DZ_ST) b |= DML_ST;
381 	if (bits & DZ_RTS) b |= DML_RTS;
382 	return(b);
383 }
384 
385 dzparam(unit)
386 	register int unit;
387 {
388 	register struct tty *tp;
389 	register struct dzdevice *dzaddr;
390 	register int lpr;
391 
392 	tp = &dz_tty[unit];
393 	dzaddr = dzpdma[unit].p_addr;
394 	if (dzsilos & (1 << (unit >> 3)))
395 		dzaddr->dzcsr = DZ_IEN | DZ_SAE;
396 	else
397 		dzaddr->dzcsr = DZ_IEN;
398 	dzact |= (1<<(unit>>3));
399 	if (tp->t_ispeed == 0) {
400 		(void) dzmctl(unit, DZ_OFF, DMSET);	/* hang up line */
401 		return;
402 	}
403 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
404 	if (tp->t_flags & (RAW|LITOUT|PASS8))
405 		lpr |= BITS8;
406 	else
407 		lpr |= (BITS7|PENABLE);
408 	if ((tp->t_flags & EVENP) == 0)
409 		lpr |= OPAR;
410 	if (tp->t_ispeed == B110)
411 		lpr |= TWOSB;
412 	dzaddr->dzlpr = lpr;
413 }
414 
415 dzxint(tp)
416 	register struct tty *tp;
417 {
418 	register struct pdma *dp;
419 	register dz, unit;
420 
421 	dp = (struct pdma *)tp->t_addr;
422 	tp->t_state &= ~TS_BUSY;
423 	if (tp->t_state & TS_FLUSH)
424 		tp->t_state &= ~TS_FLUSH;
425 	else {
426 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
427 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
428 	}
429 	if (tp->t_line)
430 		(*linesw[tp->t_line].l_start)(tp);
431 	else
432 		dzstart(tp);
433 	dz = minor(tp->t_dev) >> 3;
434 	unit = minor(tp->t_dev) & 7;
435 	if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
436 		if (dp->p_addr->dzcsr & DZ_32)
437 			dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
438 		else
439 			dp->p_addr->dztcr &= ~(1<<unit);
440 }
441 
442 dzstart(tp)
443 	register struct tty *tp;
444 {
445 	register struct pdma *dp;
446 	register struct dzdevice *dzaddr;
447 	register int cc;
448 	int s, dz, unit;
449 
450 	dp = (struct pdma *)tp->t_addr;
451 	dzaddr = dp->p_addr;
452 	s = spl5();
453 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
454 		goto out;
455 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
456 		if (tp->t_state&TS_ASLEEP) {
457 			tp->t_state &= ~TS_ASLEEP;
458 			wakeup((caddr_t)&tp->t_outq);
459 		}
460 		if (tp->t_wsel) {
461 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
462 			tp->t_wsel = 0;
463 			tp->t_state &= ~TS_WCOLL;
464 		}
465 	}
466 	if (tp->t_outq.c_cc == 0)
467 		goto out;
468 	if (tp->t_flags & (RAW|LITOUT))
469 		cc = ndqb(&tp->t_outq, 0);
470 	else {
471 		cc = ndqb(&tp->t_outq, 0200);
472 		if (cc == 0) {
473 			cc = getc(&tp->t_outq);
474 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
475 			tp->t_state |= TS_TIMEOUT;
476 			goto out;
477 		}
478 	}
479 	tp->t_state |= TS_BUSY;
480 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
481 	dp->p_end += cc;
482 	dz = minor(tp->t_dev) >> 3;
483 	unit = minor(tp->t_dev) & 7;
484 	if (dzaddr->dzcsr & DZ_32)
485 		dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
486 	else
487 		dzaddr->dztcr |= (1<<unit);
488 out:
489 	splx(s);
490 }
491 
492 /*
493  * Stop output on a line.
494  */
495 /*ARGSUSED*/
496 dzstop(tp, flag)
497 	register struct tty *tp;
498 {
499 	register struct pdma *dp;
500 	register int s;
501 
502 	dp = (struct pdma *)tp->t_addr;
503 	s = spl5();
504 	if (tp->t_state & TS_BUSY) {
505 		dp->p_end = dp->p_mem;
506 		if ((tp->t_state&TS_TTSTOP)==0)
507 			tp->t_state |= TS_FLUSH;
508 	}
509 	splx(s);
510 }
511 
512 dzmctl(dev, bits, how)
513 	dev_t dev;
514 	int bits, how;
515 {
516 	register struct dzdevice *dzaddr;
517 	register int unit, mbits;
518 	int b, s;
519 
520 	unit = minor(dev);
521 	b = 1<<(unit&7);
522 	dzaddr = dzpdma[unit].p_addr;
523 	s = spl5();
524 	if (dzaddr->dzcsr & DZ_32) {
525 		dzwait(dzaddr)
526 		DELAY(100);		/* IS 100 TOO MUCH? */
527 		dzaddr->dzlcs = unit&7;
528 		DELAY(100);
529 		dzwait(dzaddr)
530 		DELAY(100);
531 		mbits = dzaddr->dzlcs;
532 		mbits &= 0177770;
533 	} else {
534 		mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
535 		mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
536 		mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
537 	}
538 	switch (how) {
539 	case DMSET:
540 		mbits = bits;
541 		break;
542 
543 	case DMBIS:
544 		mbits |= bits;
545 		break;
546 
547 	case DMBIC:
548 		mbits &= ~bits;
549 		break;
550 
551 	case DMGET:
552 		(void) splx(s);
553 		return(mbits);
554 	}
555 	if (dzaddr->dzcsr & DZ_32) {
556 		mbits |= DZ_ACK|(unit&7);
557 		dzaddr->dzlcs = mbits;
558 	} else {
559 		if (mbits & DZ_DTR)
560 			dzaddr->dzdtr |= b;
561 		else
562 			dzaddr->dzdtr &= ~b;
563 	}
564 	(void) splx(s);
565 	return(mbits);
566 }
567 
568 int dztransitions, dzfasttimers;		/*DEBUG*/
569 dzscan()
570 {
571 	register i;
572 	register struct dzdevice *dzaddr;
573 	register bit;
574 	register struct tty *tp;
575 	register car;
576 	int olddzsilos = dzsilos;
577 	int dztimer();
578 
579 	for (i = 0; i < dz_cnt ; i++) {
580 		dzaddr = dzpdma[i].p_addr;
581 		if (dzaddr == 0)
582 			continue;
583 		tp = &dz_tty[i];
584 		bit = 1<<(i&07);
585 		car = 0;
586 		if (dzsoftCAR[i>>3]&bit)
587 			car = 1;
588 		else if (dzaddr->dzcsr & DZ_32) {
589 			dzaddr->dzlcs = i&07;
590 			dzwait(dzaddr);
591 			car = dzaddr->dzlcs & DZ_CD;
592 		} else
593 			car = dzaddr->dzmsr&bit;
594 		if (car) {
595 			/* carrier present */
596 			if ((tp->t_state & TS_CARR_ON) == 0)
597 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
598 		} else if ((tp->t_state&TS_CARR_ON) &&
599 		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
600 			dzaddr->dzdtr &= ~bit;
601 	}
602 	for (i = 0; i < NDZ; i++) {
603 		ave(dzrate[i], dzchars[i], 8);
604 		if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
605 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
606 			dzsilos |= (1 << i);
607 			dztransitions++;		/*DEBUG*/
608 		} else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
609 			dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
610 			dzsilos &= ~(1 << i);
611 		}
612 		dzchars[i] = 0;
613 	}
614 	if (dzsilos && !olddzsilos)
615 		timeout(dztimer, (caddr_t)0, dztimerintvl);
616 	timeout(dzscan, (caddr_t)0, hz);
617 }
618 
619 dztimer()
620 {
621 	register int dz;
622 	register int s;
623 
624 	if (dzsilos == 0)
625 		return;
626 	s = spl5();
627 	dzfasttimers++;		/*DEBUG*/
628 	for (dz = 0; dz < NDZ; dz++)
629 		if (dzsilos & (1 << dz))
630 		    dzrint(dz);
631 	splx(s);
632 	timeout(dztimer, (caddr_t) 0, dztimerintvl);
633 }
634 
635 /*
636  * Reset state of driver if UBA reset was necessary.
637  * Reset parameters and restart transmission on open lines.
638  */
639 dzreset(uban)
640 	int uban;
641 {
642 	register int unit;
643 	register struct tty *tp;
644 	register struct uba_device *ui;
645 
646 	for (unit = 0; unit < NDZLINE; unit++) {
647 		ui = dzinfo[unit >> 3];
648 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
649 			continue;
650 		if (unit%8 == 0)
651 			printf(" dz%d", unit>>3);
652 		tp = &dz_tty[unit];
653 		if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
654 			dzparam(unit);
655 			(void) dzmctl(unit, DZ_ON, DMSET);
656 			tp->t_state &= ~TS_BUSY;
657 			dzstart(tp);
658 		}
659 	}
660 }
661 #endif
662