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