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