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