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