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