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