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