xref: /original-bsd/sys/vax/uba/dh.c (revision f0fd5f8a)
1 /*	dh.c	4.56	82/12/17	*/
2 
3 #include "dh.h"
4 #if NDH > 0
5 /*
6  * DH-11/DM-11 driver
7  */
8 #include "../machine/pte.h"
9 
10 #include "bk.h"
11 #include "../h/param.h"
12 #include "../h/conf.h"
13 #include "../h/dir.h"
14 #include "../h/user.h"
15 #include "../h/proc.h"
16 #include "../h/ioctl.h"
17 #include "../h/tty.h"
18 #include "../h/map.h"
19 #include "../h/buf.h"
20 #include "../h/vm.h"
21 
22 #include "../vaxuba/ubareg.h"
23 #include "../vaxuba/ubavar.h"
24 
25 #include "../h/bk.h"
26 #include "../h/clist.h"
27 #include "../h/file.h"
28 #include "../h/uio.h"
29 
30 /*
31  * Definition of the driver for the auto-configuration program.
32  * There is one definition for the dh and one for the dm.
33  */
34 int	dhprobe(), dhattach(), dhrint(), dhxint();
35 struct	uba_device *dhinfo[NDH];
36 u_short	dhstd[] = { 0 };
37 struct	uba_driver dhdriver =
38 	{ dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
39 
40 int	dmprobe(), dmattach(), dmintr();
41 struct	uba_device *dminfo[NDH];
42 u_short	dmstd[] = { 0 };
43 struct	uba_driver dmdriver =
44 	{ dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
45 
46 struct dhdevice
47 {
48 	union {
49 		short	dhcsr;		/* control-status register */
50 		char	dhcsrl;		/* low byte for line select */
51 	} un;
52 	short	dhrcr;			/* receive character register */
53 	short	dhlpr;			/* line parameter register */
54 	u_short dhcar;			/* current address register */
55 	short	dhbcr;			/* byte count register */
56 	u_short	dhbar;			/* buffer active register */
57 	short	dhbreak;		/* break control register */
58 	short	dhsilo;			/* silo status register */
59 };
60 
61 #ifndef	PORTSELECTOR
62 #define	ISPEED	B300
63 #define	IFLAGS	(EVENP|ODDP|ECHO)
64 #else
65 #define	ISPEED	B4800
66 #define	IFLAGS	(EVENP|ODDP)
67 #endif
68 
69 /* Bits in dhcsr */
70 #define	DH_TI	0100000		/* transmit interrupt */
71 #define	DH_SI	0040000		/* storage interrupt */
72 #define	DH_TIE	0020000		/* transmit interrupt enable */
73 #define	DH_SIE	0010000		/* storage interrupt enable */
74 #define	DH_MC	0004000		/* master clear */
75 #define	DH_NXM	0002000		/* non-existant memory */
76 #define	DH_MM	0001000		/* maintenance mode */
77 #define	DH_CNI	0000400		/* clear non-existant memory interrupt */
78 #define	DH_RI	0000200		/* receiver interrupt */
79 #define	DH_RIE	0000100		/* receiver interrupt enable */
80 
81 /* Bits in dhlpr */
82 #define	BITS6	01
83 #define	BITS7	02
84 #define	BITS8	03
85 #define	TWOSB	04
86 #define	PENABLE	020
87 /* DEC manuals incorrectly say this bit causes generation of even parity. */
88 #define	OPAR	040
89 #define	HDUPLX	040000
90 
91 #define	DH_IE	(DH_TIE|DH_SIE|DH_RIE)
92 
93 /* Bits in dhrcr */
94 #define	DH_PE		0010000		/* parity error */
95 #define	DH_FE		0020000		/* framing error */
96 #define	DH_DO		0040000		/* data overrun */
97 
98 struct dmdevice
99 {
100 	short	dmcsr;		/* control status register */
101 	short	dmlstat;	/* line status register */
102 	short	dmpad1[2];
103 };
104 
105 /* bits in dm csr */
106 #define	DM_RF		0100000		/* ring flag */
107 #define	DM_CF		0040000		/* carrier flag */
108 #define	DM_CTS		0020000		/* clear to send */
109 #define	DM_SRF		0010000		/* secondary receive flag */
110 #define	DM_CS		0004000		/* clear scan */
111 #define	DM_CM		0002000		/* clear multiplexor */
112 #define	DM_MM		0001000		/* maintenance mode */
113 #define	DM_STP		0000400		/* step */
114 #define	DM_DONE		0000200		/* scanner is done */
115 #define	DM_IE		0000100		/* interrupt enable */
116 #define	DM_SE		0000040		/* scan enable */
117 #define	DM_BUSY		0000020		/* scan busy */
118 
119 /* bits in dm lsr */
120 #define	DML_RNG		0000200		/* ring */
121 #define	DML_CAR		0000100		/* carrier detect */
122 #define	DML_CTS		0000040		/* clear to send */
123 #define	DML_SR		0000020		/* secondary receive */
124 #define	DML_ST		0000010		/* secondary transmit */
125 #define	DML_RTS		0000004		/* request to send */
126 #define	DML_DTR		0000002		/* data terminal ready */
127 #define	DML_LE		0000001		/* line enable */
128 
129 #define	DML_ON		(DML_DTR|DML_RTS|DML_LE)
130 #define	DML_OFF		(DML_LE)
131 
132 /*
133  * Local variables for the driver
134  */
135 short	dhsar[NDH];			/* software copy of last bar */
136 short	dhsoftCAR[NDH];
137 
138 struct	tty dh11[NDH*16];
139 int	ndh11	= NDH*16;
140 int	dhact;				/* mask of active dh's */
141 int	dhstart(), ttrstrt();
142 
143 /*
144  * The clist space is mapped by the driver onto each UNIBUS.
145  * The UBACVT macro converts a clist space address for unibus uban
146  * into an i/o space address for the DMA routine.
147  */
148 int	dh_ubinfo[MAXNUBA];		/* info about allocated unibus map */
149 int	cbase[MAXNUBA];			/* base address in unibus map */
150 #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
151 
152 /*
153  * Routine for configuration to force a dh to interrupt.
154  * Set to transmit at 9600 baud, and cause a transmitter interrupt.
155  */
156 /*ARGSUSED*/
157 dhprobe(reg)
158 	caddr_t reg;
159 {
160 	register int br, cvec;		/* these are ``value-result'' */
161 	register struct dhdevice *dhaddr = (struct dhdevice *)reg;
162 
163 #ifdef lint
164 	br = 0; cvec = br; br = cvec;
165 	if (ndh11 == 0) ndh11 = 1;
166 	dhrint(0); dhxint(0);
167 #endif
168 #ifndef notdef
169 	dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
170 	DELAY(1000);
171 	dhaddr->un.dhcsr &= ~DH_RI;
172 	dhaddr->un.dhcsr = 0;
173 #else
174 	dhaddr->un.dhcsr = DH_TIE;
175 	DELAY(5);
176 	dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
177 	dhaddr->dhbcr = -1;
178 	dhaddr->dhcar = 0;
179 	dhaddr->dhbar = 1;
180 	DELAY(100000);		/* wait 1/10'th of a sec for interrupt */
181 	dhaddr->un.dhcsr = 0;
182 	if (cvec && cvec != 0x200)
183 		cvec -= 4;		/* transmit -> receive */
184 #endif
185 	return (sizeof (struct dhdevice));
186 }
187 
188 /*
189  * Routine called to attach a dh.
190  */
191 dhattach(ui)
192 	struct uba_device *ui;
193 {
194 
195 	dhsoftCAR[ui->ui_unit] = ui->ui_flags;
196 }
197 
198 /*
199  * Configuration routine to cause a dm to interrupt.
200  */
201 dmprobe(reg)
202 	caddr_t reg;
203 {
204 	register int br, vec;			/* value-result */
205 	register struct dmdevice *dmaddr = (struct dmdevice *)reg;
206 
207 #ifdef lint
208 	br = 0; vec = br; br = vec;
209 	dmintr(0);
210 #endif
211 	dmaddr->dmcsr = DM_DONE|DM_IE;
212 	DELAY(20);
213 	dmaddr->dmcsr = 0;
214 	return (1);
215 }
216 
217 /*ARGSUSED*/
218 dmattach(ui)
219 	struct uba_device *ui;
220 {
221 
222 	/* no local state to set up */
223 }
224 
225 /*
226  * Open a DH11 line, mapping the clist onto the uba if this
227  * is the first dh on this uba.  Turn on this dh if this is
228  * the first use of it.  Also do a dmopen to wait for carrier.
229  */
230 /*ARGSUSED*/
231 dhopen(dev, flag)
232 	dev_t dev;
233 {
234 	register struct tty *tp;
235 	register int unit, dh;
236 	register struct dhdevice *addr;
237 	register struct uba_device *ui;
238 	int s;
239 
240 	unit = minor(dev);
241 	dh = unit >> 4;
242 	if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
243 		return (ENXIO);
244 	tp = &dh11[unit];
245 	if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
246 		return (EBUSY);
247 	addr = (struct dhdevice *)ui->ui_addr;
248 	tp->t_addr = (caddr_t)addr;
249 	tp->t_oproc = dhstart;
250 	tp->t_state |= TS_WOPEN;
251 	/*
252 	 * While setting up state for this uba and this dh,
253 	 * block uba resets which can clear the state.
254 	 */
255 	s = spl5();
256 	if (dh_ubinfo[ui->ui_ubanum] == 0) {
257 		/* 512+ is a kludge to try to get around a hardware problem */
258 		dh_ubinfo[ui->ui_ubanum] =
259 		    uballoc(ui->ui_ubanum, (caddr_t)cfree,
260 			512+nclist*sizeof(struct cblock), 0);
261 		cbase[ui->ui_ubanum] = dh_ubinfo[ui->ui_ubanum]&0x3ffff;
262 	}
263 	if ((dhact&(1<<dh)) == 0) {
264 		addr->un.dhcsr |= DH_IE;
265 		dhact |= (1<<dh);
266 		addr->dhsilo = 16;
267 	}
268 	splx(s);
269 	/*
270 	 * If this is first open, initialze tty state to default.
271 	 */
272 	if ((tp->t_state&TS_ISOPEN) == 0) {
273 		ttychars(tp);
274 #ifndef PORTSELECTOR
275 		if (tp->t_ispeed == 0) {
276 #endif
277 			tp->t_ispeed = ISPEED;
278 			tp->t_ospeed = ISPEED;
279 			tp->t_flags = IFLAGS;
280 #ifndef PORTSELECTOR
281 		}
282 #endif
283 		dhparam(unit);
284 	}
285 	/*
286 	 * Wait for carrier, then process line discipline specific open.
287 	 */
288 	dmopen(dev);
289 	return ((*linesw[tp->t_line].l_open)(dev, tp));
290 }
291 
292 /*
293  * Close a DH11 line, turning off the DM11.
294  */
295 /*ARGSUSED*/
296 dhclose(dev, flag)
297 	dev_t dev;
298 	int flag;
299 {
300 	register struct tty *tp;
301 	register unit;
302 
303 	unit = minor(dev);
304 	tp = &dh11[unit];
305 	(*linesw[tp->t_line].l_close)(tp);
306 	((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
307 	if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
308 		dmctl(unit, DML_OFF, DMSET);
309 	ttyclose(tp);
310 }
311 
312 dhread(dev, uio)
313 	dev_t dev;
314 	struct uio *uio;
315 {
316 	register struct tty *tp = &dh11[minor(dev)];
317 
318 	return ((*linesw[tp->t_line].l_read)(tp, uio));
319 }
320 
321 dhwrite(dev, uio)
322 	dev_t dev;
323 	struct uio *uio;
324 {
325 	register struct tty *tp = &dh11[minor(dev)];
326 
327 	return ((*linesw[tp->t_line].l_write)(tp, uio));
328 }
329 
330 /*
331  * DH11 receiver interrupt.
332  */
333 dhrint(dh)
334 	int dh;
335 {
336 	register struct tty *tp;
337 	register c;
338 	register struct dhdevice *addr;
339 	register struct tty *tp0;
340 	register struct uba_device *ui;
341 	int overrun = 0;
342 
343 	ui = dhinfo[dh];
344 	if (ui == 0 || ui->ui_alive == 0)
345 		return;
346 	addr = (struct dhdevice *)ui->ui_addr;
347 	tp0 = &dh11[dh<<4];
348 	/*
349 	 * Loop fetching characters from the silo for this
350 	 * dh until there are no more in the silo.
351 	 */
352 	while ((c = addr->dhrcr) < 0) {
353 		tp = tp0 + ((c>>8)&0xf);
354 #ifndef PORTSELECTOR
355 		if ((tp->t_state&TS_ISOPEN)==0) {
356 #else
357 		if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0) {
358 #endif
359 			wakeup((caddr_t)tp);
360 			continue;
361 		}
362 		if (c & DH_PE)
363 			if ((tp->t_flags&(EVENP|ODDP))==EVENP
364 			 || (tp->t_flags&(EVENP|ODDP))==ODDP )
365 				continue;
366 		if ((c & DH_DO) && overrun == 0) {
367 			printf("dh%d: silo overflow\n", dh);
368 			overrun = 1;
369 		}
370 		if (c & DH_FE)
371 			/*
372 			 * At framing error (break) generate
373 			 * a null (in raw mode, for getty), or a
374 			 * interrupt (in cooked/cbreak mode).
375 			 */
376 			if (tp->t_flags&RAW)
377 				c = 0;
378 			else
379 				c = tp->t_intrc;
380 #if NBK > 0
381 		if (tp->t_line == NETLDISC) {
382 			c &= 0177;
383 			BKINPUT(c, tp);
384 		} else
385 #endif
386 			(*linesw[tp->t_line].l_rint)(c, tp);
387 	}
388 }
389 
390 /*
391  * Ioctl for DH11.
392  */
393 /*ARGSUSED*/
394 dhioctl(dev, cmd, data, flag)
395 	caddr_t data;
396 {
397 	register struct tty *tp;
398 	register int unit = minor(dev);
399 	int error;
400 
401 	tp = &dh11[unit];
402 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
403 	if (error >= 0)
404 		return (error);
405 	error = ttioctl(tp, cmd, data, flag);
406 	if (error >= 0) {
407 		if (cmd == TIOCSETP || cmd == TIOCSETN)
408 			dhparam(unit);
409 		return (error);
410 	}
411 	switch (cmd) {
412 
413 	case TIOCSBRK:
414 		((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
415 		break;
416 
417 	case TIOCCBRK:
418 		((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
419 		break;
420 
421 	case TIOCSDTR:
422 		dmctl(unit, DML_DTR|DML_RTS, DMBIS);
423 		break;
424 
425 	case TIOCCDTR:
426 		dmctl(unit, DML_DTR|DML_RTS, DMBIC);
427 		break;
428 
429 	default:
430 		return (ENOTTY);
431 	}
432 	return (0);
433 }
434 
435 /*
436  * Set parameters from open or stty into the DH hardware
437  * registers.
438  */
439 dhparam(unit)
440 	register int unit;
441 {
442 	register struct tty *tp;
443 	register struct dhdevice *addr;
444 	register int lpar;
445 	int s;
446 
447 	tp = &dh11[unit];
448 	addr = (struct dhdevice *)tp->t_addr;
449 	/*
450 	 * Block interrupts so parameters will be set
451 	 * before the line interrupts.
452 	 */
453 	s = spl5();
454 	addr->un.dhcsrl = (unit&0xf) | DH_IE;
455 	if ((tp->t_ispeed)==0) {
456 		tp->t_state |= TS_HUPCLS;
457 		dmctl(unit, DML_OFF, DMSET);
458 		return;
459 	}
460 	lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
461 	if ((tp->t_ispeed) == B134)
462 		lpar |= BITS6|PENABLE|HDUPLX;
463 	else if (tp->t_flags & (RAW|LITOUT))
464 		lpar |= BITS8;
465 	else
466 		lpar |= BITS7|PENABLE;
467 	if ((tp->t_flags&EVENP) == 0)
468 		lpar |= OPAR;
469 	if ((tp->t_ospeed) == B110)
470 		lpar |= TWOSB;
471 	addr->dhlpr = lpar;
472 	splx(s);
473 }
474 
475 /*
476  * DH11 transmitter interrupt.
477  * Restart each line which used to be active but has
478  * terminated transmission since the last interrupt.
479  */
480 dhxint(dh)
481 	int dh;
482 {
483 	register struct tty *tp;
484 	register struct dhdevice *addr;
485 	short ttybit, bar, *sbar;
486 	register struct uba_device *ui;
487 	register int unit;
488 	u_short cntr;
489 
490 	ui = dhinfo[dh];
491 	addr = (struct dhdevice *)ui->ui_addr;
492 	if (addr->un.dhcsr & DH_NXM) {
493 		addr->un.dhcsr |= DH_CNI;
494 		printf("dh%d: NXM\n", dh);
495 	}
496 	sbar = &dhsar[dh];
497 	bar = *sbar & ~addr->dhbar;
498 	unit = dh * 16; ttybit = 1;
499 	addr->un.dhcsr &= (short)~DH_TI;
500 	for (; bar; unit++, ttybit <<= 1) {
501 		if (bar & ttybit) {
502 			*sbar &= ~ttybit;
503 			bar &= ~ttybit;
504 			tp = &dh11[unit];
505 			tp->t_state &= ~TS_BUSY;
506 			if (tp->t_state&TS_FLUSH)
507 				tp->t_state &= ~TS_FLUSH;
508 			else {
509 				addr->un.dhcsrl = (unit&017)|DH_IE;
510 				/*
511 				 * Do arithmetic in a short to make up
512 				 * for lost 16&17 bits.
513 				 */
514 				cntr = addr->dhcar -
515 				    UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
516 				ndflush(&tp->t_outq, (int)cntr);
517 			}
518 			if (tp->t_line)
519 				(*linesw[tp->t_line].l_start)(tp);
520 			else
521 				dhstart(tp);
522 		}
523 	}
524 }
525 
526 /*
527  * Start (restart) transmission on the given DH11 line.
528  */
529 dhstart(tp)
530 	register struct tty *tp;
531 {
532 	register struct dhdevice *addr;
533 	register int car, dh, unit, nch;
534 	int s;
535 
536 	unit = minor(tp->t_dev);
537 	dh = unit >> 4;
538 	unit &= 0xf;
539 	addr = (struct dhdevice *)tp->t_addr;
540 
541 	/*
542 	 * Must hold interrupts in following code to prevent
543 	 * state of the tp from changing.
544 	 */
545 	s = spl5();
546 	/*
547 	 * If it's currently active, or delaying, no need to do anything.
548 	 */
549 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
550 		goto out;
551 	/*
552 	 * If there are sleepers, and output has drained below low
553 	 * water mark, wake up the sleepers.
554 	 */
555 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
556 		if (tp->t_state&TS_ASLEEP) {
557 			tp->t_state &= ~TS_ASLEEP;
558 			wakeup((caddr_t)&tp->t_outq);
559 		}
560 		if (tp->t_wsel) {
561 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
562 			tp->t_wsel = 0;
563 			tp->t_state &= ~TS_WCOLL;
564 		}
565 	}
566 	/*
567 	 * Now restart transmission unless the output queue is
568 	 * empty.
569 	 */
570 	if (tp->t_outq.c_cc == 0)
571 		goto out;
572 	if (tp->t_flags & (RAW|LITOUT))
573 		nch = ndqb(&tp->t_outq, 0);
574 	else {
575 		nch = ndqb(&tp->t_outq, 0200);
576 		/*
577 		 * If first thing on queue is a delay process it.
578 		 */
579 		if (nch == 0) {
580 			nch = getc(&tp->t_outq);
581 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
582 			tp->t_state |= TS_TIMEOUT;
583 			goto out;
584 		}
585 	}
586 	/*
587 	 * If characters to transmit, restart transmission.
588 	 */
589 	if (nch) {
590 		car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
591 		addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
592 		/*
593 		 * The following nonsense with short word
594 		 * is to make sure the dhbar |= word below
595 		 * is done with an interlocking bisw2 instruction.
596 		 */
597 		{ short word = 1 << unit;
598 		dhsar[dh] |= word;
599 		addr->dhcar = car;
600 		addr->dhbcr = -nch;
601 		addr->dhbar |= word;
602 		}
603 		tp->t_state |= TS_BUSY;
604 	}
605 out:
606 	splx(s);
607 }
608 
609 /*
610  * Stop output on a line, e.g. for ^S/^Q or output flush.
611  */
612 /*ARGSUSED*/
613 dhstop(tp, flag)
614 	register struct tty *tp;
615 {
616 	register struct dhdevice *addr;
617 	register int unit, s;
618 
619 	addr = (struct dhdevice *)tp->t_addr;
620 	/*
621 	 * Block input/output interrupts while messing with state.
622 	 */
623 	s = spl5();
624 	if (tp->t_state & TS_BUSY) {
625 		/*
626 		 * Device is transmitting; stop output
627 		 * by selecting the line and setting the byte
628 		 * count to -1.  We will clean up later
629 		 * by examining the address where the dh stopped.
630 		 */
631 		unit = minor(tp->t_dev);
632 		addr->un.dhcsrl = (unit&017) | DH_IE;
633 		if ((tp->t_state&TS_TTSTOP)==0)
634 			tp->t_state |= TS_FLUSH;
635 		addr->dhbcr = -1;
636 	}
637 	splx(s);
638 }
639 
640 /*
641  * Reset state of driver if UBA reset was necessary.
642  * Reset the csrl and lpr registers on open lines, and
643  * restart transmitters.
644  */
645 dhreset(uban)
646 	int uban;
647 {
648 	register int dh, unit;
649 	register struct tty *tp;
650 	register struct uba_device *ui;
651 	int i;
652 
653 	if (dh_ubinfo[uban] == 0)
654 		return;
655 	dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
656 	    512+nclist*sizeof (struct cblock), 0);
657 	cbase[uban] = dh_ubinfo[uban]&0x3ffff;
658 	dh = 0;
659 	for (dh = 0; dh < NDH; dh++) {
660 		ui = dhinfo[dh];
661 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
662 			continue;
663 		printf(" dh%d", dh);
664 		((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
665 		((struct dhdevice *)ui->ui_addr)->dhsilo = 16;
666 		unit = dh * 16;
667 		for (i = 0; i < 16; i++) {
668 			tp = &dh11[unit];
669 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
670 				dhparam(unit);
671 				dmctl(unit, DML_ON, DMSET);
672 				tp->t_state &= ~TS_BUSY;
673 				dhstart(tp);
674 			}
675 			unit++;
676 		}
677 	}
678 	dhtimer();
679 }
680 
681 /*
682  * At software clock interrupt time or after a UNIBUS reset
683  * empty all the dh silos.
684  */
685 dhtimer()
686 {
687 	register int dh;
688 	register int s = spl5();
689 
690 	for (dh = 0; dh < NDH; dh++)
691 		dhrint(dh);
692 	splx(s);
693 }
694 
695 /*
696  * Turn on the line associated with dh dev.
697  */
698 dmopen(dev)
699 	dev_t dev;
700 {
701 	register struct tty *tp;
702 	register struct dmdevice *addr;
703 	register struct uba_device *ui;
704 	register int unit;
705 	register int dm;
706 	int s;
707 
708 	unit = minor(dev);
709 	dm = unit >> 4;
710 	tp = &dh11[unit];
711 	unit &= 0xf;
712 	if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 ||
713 	    (dhsoftCAR[dm]&(1<<unit))) {
714 		tp->t_state |= TS_CARR_ON;
715 		return;
716 	}
717 	addr = (struct dmdevice *)ui->ui_addr;
718 	s = spl5();
719 	addr->dmcsr &= ~DM_SE;
720 	while (addr->dmcsr & DM_BUSY)
721 		;
722 	addr->dmcsr = unit;
723 	addr->dmlstat = DML_ON;
724 	if (addr->dmlstat&DML_CAR)
725 		tp->t_state |= TS_CARR_ON;
726 	addr->dmcsr = DM_IE|DM_SE;
727 	while ((tp->t_state&TS_CARR_ON)==0)
728 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
729 	splx(s);
730 }
731 
732 /*
733  * Dump control bits into the DM registers.
734  */
735 dmctl(dev, bits, how)
736 	dev_t dev;
737 	int bits, how;
738 {
739 	register struct uba_device *ui;
740 	register struct dmdevice *addr;
741 	register int unit, s;
742 	int dm;
743 
744 	unit = minor(dev);
745 	dm = unit >> 4;
746 	if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
747 		return;
748 	addr = (struct dmdevice *)ui->ui_addr;
749 	s = spl5();
750 	addr->dmcsr &= ~DM_SE;
751 	while (addr->dmcsr & DM_BUSY)
752 		;
753 	addr->dmcsr = unit & 0xf;
754 	switch(how) {
755 	case DMSET:
756 		addr->dmlstat = bits;
757 		break;
758 	case DMBIS:
759 		addr->dmlstat |= bits;
760 		break;
761 	case DMBIC:
762 		addr->dmlstat &= ~bits;
763 		break;
764 	}
765 	addr->dmcsr = DM_IE|DM_SE;
766 	splx(s);
767 }
768 
769 /*
770  * DM11 interrupt; deal with carrier transitions.
771  */
772 dmintr(dm)
773 	register int dm;
774 {
775 	register struct uba_device *ui;
776 	register struct tty *tp;
777 	register struct dmdevice *addr;
778 
779 	ui = dminfo[dm];
780 	if (ui == 0)
781 		return;
782 	addr = (struct dmdevice *)ui->ui_addr;
783 	if (addr->dmcsr&DM_DONE) {
784 		if (addr->dmcsr&DM_CF) {
785 			tp = &dh11[(dm<<4)+(addr->dmcsr&0xf)];
786 			wakeup((caddr_t)&tp->t_rawq);
787 			if ((tp->t_state&TS_WOPEN) == 0 &&
788 			    (tp->t_flags & MDMBUF)) {
789 				if (addr->dmlstat & DML_CAR) {
790 					tp->t_state &= ~TS_TTSTOP;
791 					ttstart(tp);
792 				} else if ((tp->t_state&TS_TTSTOP) == 0) {
793 					tp->t_state |= TS_TTSTOP;
794 					dhstop(tp, 0);
795 				}
796 			} else if ((addr->dmlstat&DML_CAR)==0) {
797 				if ((tp->t_state&TS_WOPEN)==0 &&
798 				    (tp->t_flags & NOHANG) == 0) {
799 					gsignal(tp->t_pgrp, SIGHUP);
800 					gsignal(tp->t_pgrp, SIGCONT);
801 					addr->dmlstat = 0;
802 					flushtty(tp, FREAD|FWRITE);
803 				}
804 				tp->t_state &= ~TS_CARR_ON;
805 			} else
806 				tp->t_state |= TS_CARR_ON;
807 		}
808 		addr->dmcsr = DM_IE|DM_SE;
809 	}
810 }
811 #endif
812