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