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