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