xref: /original-bsd/sys/vax/uba/dz.c (revision 1f3a482a)
1 /*	dz.c	4.26	81/05/29	*/
2 
3 #include "dz.h"
4 #if NDZ > 0
5 /*
6  *  DZ-11 Driver
7  *
8  * This driver mimics dh.c; see it for explanation of common code.
9  */
10 #include "bk.h"
11 #include "../h/param.h"
12 #include "../h/systm.h"
13 #include "../h/tty.h"
14 #include "../h/dir.h"
15 #include "../h/user.h"
16 #include "../h/map.h"
17 #include "../h/pte.h"
18 #include "../h/buf.h"
19 #include "../h/vm.h"
20 #include "../h/ubavar.h"
21 #include "../h/conf.h"
22 #include "../h/pdma.h"
23 #include "../h/bk.h"
24 #include "../h/file.h"
25 #include "../h/mx.h"
26 
27 /*
28  * Driver information for auto-configuration stuff.
29  */
30 int	dzprobe(), dzattach(), dzrint();
31 struct	uba_device *dzinfo[NDZ];
32 u_short	dzstd[] = { 0 };
33 struct	uba_driver dzdriver =
34 	{ dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
35 
36 #define	NDZLINE 	(NDZ*8)
37 
38 /*
39  * Registers and bits
40  */
41 
42 /* Bits in dzlpr */
43 #define	BITS7	020
44 #define	BITS8	030
45 #define	TWOSB	040
46 #define	PENABLE	0100
47 #define	OPAR	0200
48 
49 /* Bits in dzrbuf */
50 #define	DZ_PE	010000
51 #define	DZ_FE	020000
52 #define	DZ_DO	040000
53 
54 /* Bits in dzcsr */
55 #define	DZ_CLR	020		/* Reset dz */
56 #define	DZ_MSE	040		/* Master Scan Enable */
57 #define	DZ_RIE	0100		/* Receiver Interrupt Enable */
58 #define	DZ_SAE	010000		/* Silo Alarm Enable */
59 #define	DZ_TIE	040000		/* Transmit Interrupt Enable */
60 #if NBK == 0
61 #define	DZ_IEN	(DZ_MSE|DZ_RIE|DZ_TIE)
62 #else
63 #define	DZ_IEN	(DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
64 #endif
65 
66 /* Flags for modem-control */
67 #define	DZ_ON	1
68 #define	DZ_OFF	0
69 
70 int	dzstart(), dzxint(), dzdma();
71 int	ttrstrt();
72 struct	tty dz_tty[NDZLINE];
73 int	dz_cnt = { NDZLINE };
74 int	dzact;
75 
76 struct device {
77 	short	dzcsr;		/* control-status register */
78 	short	dzrbuf;		/* receiver buffer */
79 #define	dzlpr	dzrbuf		/* line parameter reg is write of dzrbuf */
80 	char	dztcr;		/* transmit control register */
81 	char	dzdtr;		/* data terminal ready */
82 	char	dztbuf;		/* transmit buffer */
83 	char	dzbrk;		/* break control */
84 #define	dzmsr	dzbrk		/* modem status register */
85 };
86 /*
87  * Software copy of dzbrk since it isn't readable
88  */
89 char	dz_brk[NDZ];
90 char	dzsoftCAR[NDZ];
91 
92 /*
93  * The dz doesn't interrupt on carrier transitions, so
94  * we have to use a timer to watch it.
95  */
96 char	dz_timer;		/* timer started? */
97 
98 /*
99  * Pdma structures for fast output code
100  */
101 struct	pdma dzpdma[NDZLINE];
102 
103 char	dz_speeds[] =
104 	{ 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
105 
106 dzprobe(reg)
107 	caddr_t reg;
108 {
109 	register int br, cvec;
110 	register struct device *dzaddr = (struct device *)reg;
111 
112 #ifdef lint
113 	br = 0; cvec = br; br = cvec;
114 #endif
115 	dzaddr->dzcsr = DZ_TIE|DZ_MSE;
116 	dzaddr->dztcr = 1;		/* enable any line */
117 	DELAY(100000);
118 	dzaddr->dzcsr = DZ_CLR;		/* reset everything */
119 	if (cvec && cvec != 0x200)
120 		cvec -= 4;
121 	return (1);
122 }
123 
124 dzattach(ui)
125 	register struct uba_device *ui;
126 {
127 	register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
128 	register struct tty *tp = &dz_tty[ui->ui_unit*8];
129 	register int cntr;
130 	extern dzscan();
131 
132 	for (cntr = 0; cntr < 8; cntr++) {
133 		pdp->p_addr = (struct device *)ui->ui_addr;
134 		pdp->p_arg = (int)tp;
135 		pdp->p_fcn = dzxint;
136 		pdp++, tp++;
137 	}
138 	dzsoftCAR[ui->ui_unit] = ui->ui_flags;
139 	if (dz_timer == 0) {
140 		dz_timer++;
141 		timeout(dzscan, (caddr_t)0, hz);
142 	}
143 	return (1);
144 }
145 
146 /*ARGSUSED*/
147 dzopen(dev, flag)
148 	dev_t dev;
149 {
150 	register struct tty *tp;
151 	register int unit;
152 
153 	unit = minor(dev);
154 	if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
155 		u.u_error = ENXIO;
156 		return;
157 	}
158 	tp = &dz_tty[unit];
159 	tp->t_addr = (caddr_t)&dzpdma[unit];
160 	tp->t_oproc = dzstart;
161 	tp->t_iproc = NULL;
162 	tp->t_state |= WOPEN;
163 	if ((tp->t_state & ISOPEN) == 0) {
164 		ttychars(tp);
165 		tp->t_ospeed = tp->t_ispeed = B300;
166 		tp->t_flags = ODDP|EVENP|ECHO;
167 		/* tp->t_state |= HUPCLS; */
168 		dzparam(unit);
169 	} else if (tp->t_state&XCLUDE && u.u_uid != 0) {
170 		u.u_error = EBUSY;
171 		return;
172 	}
173 	dzmodem(unit, DZ_ON);
174 	(void) spl5();
175 	while ((tp->t_state & CARR_ON) == 0) {
176 		tp->t_state |= WOPEN;
177 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
178 	}
179 	(void) spl0();
180 	(*linesw[tp->t_line].l_open)(dev, tp);
181 }
182 
183 /*ARGSUSED*/
184 dzclose(dev, flag)
185 	dev_t dev;
186 {
187 	register struct tty *tp;
188 	register int unit;
189 	int dz;
190 
191 	unit = minor(dev);
192 	dz = unit >> 3;
193 	tp = &dz_tty[unit];
194 	(*linesw[tp->t_line].l_close)(tp);
195 	((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
196 	    (dz_brk[dz] &= ~(1 << (unit&07)));
197 	if (tp->t_state & HUPCLS)
198 		dzmodem(unit, DZ_OFF);
199 	ttyclose(tp);
200 }
201 
202 dzread(dev)
203 	dev_t dev;
204 {
205 	register struct tty *tp;
206 
207 	tp = &dz_tty[minor(dev)];
208 	(*linesw[tp->t_line].l_read)(tp);
209 }
210 
211 dzwrite(dev)
212 	dev_t dev;
213 {
214 	register struct tty *tp;
215 
216 	tp = &dz_tty[minor(dev)];
217 	(*linesw[tp->t_line].l_write)(tp);
218 }
219 
220 /*ARGSUSED*/
221 dzrint(dz)
222 	int dz;
223 {
224 	register struct tty *tp;
225 	register int c;
226 	register struct device *dzaddr;
227 	register struct tty *tp0;
228 	register int unit;
229 	int overrun = 0;
230 
231 	if ((dzact & (1<<dz)) == 0)
232 		return;
233 	unit = dz * 8;
234 	dzaddr = dzpdma[unit].p_addr;
235 	tp0 = &dz_tty[unit];
236 	while ((c = dzaddr->dzrbuf) < 0) {	/* char present */
237 		tp = tp0 + ((c>>8)&07);
238 		if (tp >= &dz_tty[dz_cnt])
239 			continue;
240 		if ((tp->t_state & ISOPEN) == 0) {
241 			wakeup((caddr_t)&tp->t_rawq);
242 			continue;
243 		}
244 		if (c&DZ_FE)
245 			if (tp->t_flags & RAW)
246 				c = 0;
247 			else
248 				c = tun.t_intrc;
249 		if (c&DZ_DO && overrun == 0) {
250 			printf("dz%d: silo overflow\n", dz);
251 			overrun = 1;
252 		}
253 		if (c&DZ_PE)
254 			if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
255 			  || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
256 				continue;
257 #if NBK > 0
258 		if (tp->t_line == NETLDISC) {
259 			c &= 0177;
260 			BKINPUT(c, tp);
261 		} else
262 #endif
263 			(*linesw[tp->t_line].l_rint)(c, tp);
264 	}
265 }
266 
267 /*ARGSUSED*/
268 dzioctl(dev, cmd, addr, flag)
269 	dev_t dev;
270 	caddr_t addr;
271 {
272 	register struct tty *tp;
273 	register int unit = minor(dev);
274 	register int dz = unit >> 3;
275 
276 	tp = &dz_tty[unit];
277 	cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
278 	if (cmd == 0)
279 		return;
280 	if (ttioctl(tp, cmd, addr, flag)) {
281 		if (cmd==TIOCSETP || cmd==TIOCSETN)
282 			dzparam(unit);
283 	} else switch(cmd) {
284 
285 	case TIOCSBRK:
286 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
287 			(dz_brk[dz] |= 1 << (unit&07));
288 		break;
289 	case TIOCCBRK:
290 		((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
291 			(dz_brk[dz] &= ~(1 << (unit&07)));
292 		break;
293 	case TIOCSDTR:
294 		dzmodem(unit, DZ_ON);
295 		break;
296 	case TIOCCDTR:
297 		dzmodem(unit, DZ_OFF);
298 		break;
299 	default:
300 		u.u_error = ENOTTY;
301 	}
302 }
303 
304 dzparam(unit)
305 	register int unit;
306 {
307 	register struct tty *tp;
308 	register struct device *dzaddr;
309 	register int lpr;
310 
311 	tp = &dz_tty[unit];
312 	dzaddr = dzpdma[unit].p_addr;
313 	dzaddr->dzcsr = DZ_IEN;
314 	dzact |= (1<<(unit>>3));
315 	if (tp->t_ispeed == 0) {
316 		dzmodem(unit, DZ_OFF);		/* hang up line */
317 		return;
318 	}
319 	lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
320 	if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
321 		lpr |= BITS8;
322 	else
323 		lpr |= (BITS7|PENABLE);
324 	if ((tp->t_flags & EVENP) == 0)
325 		lpr |= OPAR;
326 	if (tp->t_ispeed == B110)
327 		lpr |= TWOSB;
328 	dzaddr->dzlpr = lpr;
329 }
330 
331 dzxint(tp)
332 	register struct tty *tp;
333 {
334 	register struct pdma *dp;
335 	register s;
336 
337 	s = spl5();		/* block pdma interrupts */
338 	dp = (struct pdma *)tp->t_addr;
339 	tp->t_state &= ~BUSY;
340 	if (tp->t_state & FLUSH)
341 		tp->t_state &= ~FLUSH;
342 	else
343 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
344 	if (tp->t_line)
345 		(*linesw[tp->t_line].l_start)(tp);
346 	else
347 		dzstart(tp);
348 	if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
349 		dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
350 	splx(s);
351 }
352 
353 dzstart(tp)
354 	register struct tty *tp;
355 {
356 	register struct pdma *dp;
357 	register struct device *dzaddr;
358 	register int cc;
359 	int s;
360 
361 	dp = (struct pdma *)tp->t_addr;
362 	dzaddr = dp->p_addr;
363 	s = spl5();
364 	if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
365 		goto out;
366 	if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
367 		tp->t_state &= ~ASLEEP;
368 		if (tp->t_chan)
369 			mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
370 		else
371 			wakeup((caddr_t)&tp->t_outq);
372 	}
373 	if (tp->t_outq.c_cc == 0)
374 		goto out;
375 	if (tp->t_flags&RAW || tp->t_local&LLITOUT)
376 		cc = ndqb(&tp->t_outq, 0);
377 	else {
378 		cc = ndqb(&tp->t_outq, 0200);
379 		if (cc == 0) {
380 			cc = getc(&tp->t_outq);
381 			timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
382 			tp->t_state |= TIMEOUT;
383 			goto out;
384 		}
385 	}
386 	tp->t_state |= BUSY;
387 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
388 	dp->p_end += cc;
389 	dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);	/* force intr */
390 out:
391 	splx(s);
392 }
393 
394 /*
395  * Stop output on a line.
396  */
397 /*ARGSUSED*/
398 dzstop(tp, flag)
399 	register struct tty *tp;
400 {
401 	register struct pdma *dp;
402 	register int s;
403 
404 	dp = (struct pdma *)tp->t_addr;
405 	s = spl5();
406 	if (tp->t_state & BUSY) {
407 		dp->p_end = dp->p_mem;
408 		if ((tp->t_state&TTSTOP)==0)
409 			tp->t_state |= FLUSH;
410 	}
411 	splx(s);
412 }
413 
414 dzmodem(unit, flag)
415 	register int unit;
416 {
417 	register struct device *dzaddr;
418 	register char bit;
419 
420 	dzaddr = dzpdma[unit].p_addr;
421 	bit = 1<<(unit&07);
422 	if (flag == DZ_OFF)
423 		dzaddr->dzdtr &= ~bit;
424 	else
425 		dzaddr->dzdtr |= bit;
426 }
427 
428 dzscan()
429 {
430 	register i;
431 	register struct device *dzaddr;
432 	register bit;
433 	register struct tty *tp;
434 
435 	for (i = 0; i < dz_cnt ; i++) {
436 		dzaddr = dzpdma[i].p_addr;
437 		if (dzaddr == 0)
438 			continue;
439 		tp = &dz_tty[i];
440 		bit = 1<<(i&07);
441 		if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
442 			/* carrier present */
443 			if ((tp->t_state & CARR_ON) == 0) {
444 				wakeup((caddr_t)&tp->t_rawq);
445 				tp->t_state |= CARR_ON;
446 			}
447 		} else {
448 			if ((tp->t_state&CARR_ON) &&
449 			    (tp->t_local&LNOHANG)==0) {
450 				/* carrier lost */
451 				if (tp->t_state&ISOPEN) {
452 					gsignal(tp->t_pgrp, SIGHUP);
453 					gsignal(tp->t_pgrp, SIGCONT);
454 					dzaddr->dzdtr &= ~bit;
455 					flushtty(tp, FREAD|FWRITE);
456 				}
457 				tp->t_state &= ~CARR_ON;
458 			}
459 		}
460 	}
461 	timeout(dzscan, (caddr_t)0, 2*hz);
462 }
463 
464 dztimer()
465 {
466 	int dz;
467 
468 	for (dz = 0; dz < NDZ; dz++)
469 		dzrint(dz);
470 }
471 
472 /*
473  * Reset state of driver if UBA reset was necessary.
474  * Reset parameters and restart transmission on open lines.
475  */
476 dzreset(uban)
477 	int uban;
478 {
479 	register int unit;
480 	register struct tty *tp;
481 	register struct uba_device *ui;
482 
483 	for (unit = 0; unit < NDZLINE; unit++) {
484 		ui = dzinfo[unit >> 3];
485 		if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
486 			continue;
487 		if (unit%8 == 0)
488 			printf(" dz%d", unit>>3);
489 		tp = &dz_tty[unit];
490 		if (tp->t_state & (ISOPEN|WOPEN)) {
491 			dzparam(unit);
492 			dzmodem(unit, DZ_ON);
493 			tp->t_state &= ~BUSY;
494 			dzstart(tp);
495 		}
496 	}
497 	dztimer();
498 }
499 #endif
500