|
|
1.1 root 1: /* dh.c 4.39 81/12/07 */
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(1000);
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.