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