|
|
1.1 root 1: /*
2: * Copyright (c) 1985, 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: * @(#)dhu.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: /*
10: * based on dh.c 6.3 84/03/15
11: * and on dmf.c 6.2 84/02/16
12: *
13: * Dave Johnson, Brown University Computer Science
14: * ddj%brown@csnet-relay
15: */
16:
17: #include "dhu.h"
18: #if NDHU > 0
19: /*
20: * DHU-11 driver
21: */
22: #include "../machine/pte.h"
23:
24: #include "bk.h"
25: #include "param.h"
26: #include "conf.h"
27: #include "dir.h"
28: #include "user.h"
29: #include "proc.h"
30: #include "ioctl.h"
31: #include "tty.h"
32: #include "map.h"
33: #include "buf.h"
34: #include "vm.h"
35: #include "kernel.h"
36: #include "syslog.h"
37:
38: #include "uba.h"
39: #include "ubareg.h"
40: #include "ubavar.h"
41: #include "dhureg.h"
42:
43: #include "bkmac.h"
44: #include "clist.h"
45: #include "file.h"
46: #include "uio.h"
47:
48: /*
49: * Definition of the driver for the auto-configuration program.
50: */
51: int dhuprobe(), dhuattach(), dhurint(), dhuxint();
52: struct uba_device *dhuinfo[NDHU];
53: u_short dhustd[] = { 160440, 160500, 0 }; /* some common addresses */
54: struct uba_driver dhudriver =
55: { dhuprobe, 0, dhuattach, 0, dhustd, "dhu", dhuinfo };
56:
57: #define NDHULINE (NDHU*16)
58:
59: #define UNIT(x) (minor(x))
60:
61: #ifndef PORTSELECTOR
62: #define ISPEED B9600
63: #define IFLAGS (EVENP|ODDP|ECHO)
64: #else
65: #define ISPEED B4800
66: #define IFLAGS (EVENP|ODDP)
67: #endif
68:
69: /*
70: * default receive silo timeout value -- valid values are 2..255
71: * number of ms. to delay between first char received and receive interrupt
72: *
73: * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0
74: */
75: #define DHU_DEF_TIMO 20
76:
77: /*
78: * Other values for silo timeout register defined here but not used:
79: * receive interrupt only on modem control or silo alarm (3/4 full)
80: */
81: #define DHU_POLL_TIMO 0
82: /*
83: * receive interrupt immediately on receive character
84: */
85: #define DHU_NO_TIMO 1
86:
87: /*
88: * Local variables for the driver
89: */
90: /*
91: * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B".
92: * EXTA => 19200 baud
93: * EXTB => 2000 baud
94: */
95: char dhu_speeds[] =
96: { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 };
97:
98: short dhusoftCAR[NDHU];
99:
100: struct tty dhu_tty[NDHULINE];
101: int ndhu = NDHULINE;
102: int dhuact; /* mask of active dhu's */
103: int dhustart(), ttrstrt();
104:
105: /*
106: * The clist space is mapped by the driver onto each UNIBUS.
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 dhu_ubinfo[NUBA]; /* info about allocated unibus map */
111: int cbase[NUBA]; /* base address in unibus map */
112: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
113:
114: /*
115: * Routine for configuration to force a dhu to interrupt.
116: */
117: /*ARGSUSED*/
118: dhuprobe(reg)
119: caddr_t reg;
120: {
121: register int br, cvec; /* these are ``value-result'' */
122: register struct dhudevice *dhuaddr = (struct dhudevice *)reg;
123: int i;
124:
125: #ifdef lint
126: br = 0; cvec = br; br = cvec;
127: if (ndhu == 0) ndhu = 1;
128: dhurint(0); dhuxint(0);
129: #endif
130: /*
131: * The basic idea here is:
132: * do a self-test by setting the Master-Reset bit
133: * if this fails, then return
134: * if successful, there will be 8 diagnostic codes in RX FIFO
135: * therefore ask for a Received-Data-Available interrupt
136: * wait for it...
137: * reset the interrupt-enable bit and flush out the diag. codes
138: */
139: dhuaddr->dhucsr = DHU_CS_MCLR;
140: for (i = 0; i < 1000; i++) {
141: DELAY(10000);
142: if ((dhuaddr->dhucsr&DHU_CS_MCLR) == 0)
143: break;
144: }
145: if (dhuaddr->dhucsr&DHU_CS_MCLR)
146: return(0);
147: if (dhuaddr->dhucsr&DHU_CS_DFAIL)
148: return(0);
149: dhuaddr->dhucsr = DHU_CS_RIE;
150: DELAY(1000);
151: dhuaddr->dhucsr = 0;
152: while (dhuaddr->dhurbuf < 0)
153: /* void */;
154: return (sizeof(struct dhudevice));
155: }
156:
157: /*
158: * Routine called to attach a dhu.
159: */
160: dhuattach(ui)
161: struct uba_device *ui;
162: {
163:
164: dhusoftCAR[ui->ui_unit] = ui->ui_flags;
165: cbase[ui->ui_ubanum] = -1;
166: }
167:
168: /*
169: * Open a DHU11 line, mapping the clist onto the uba if this
170: * is the first dhu on this uba. Turn on this dhu if this is
171: * the first use of it.
172: */
173: /*ARGSUSED*/
174: dhuopen(dev, flag)
175: dev_t dev;
176: {
177: register struct tty *tp;
178: register int unit, dhu;
179: register struct dhudevice *addr;
180: register struct uba_device *ui;
181: int s;
182:
183: unit = UNIT(dev);
184: dhu = unit >> 4;
185: if (unit >= NDHULINE || (ui = dhuinfo[dhu])== 0 || ui->ui_alive == 0)
186: return (ENXIO);
187: tp = &dhu_tty[unit];
188: if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
189: return (EBUSY);
190: addr = (struct dhudevice *)ui->ui_addr;
191: tp->t_addr = (caddr_t)addr;
192: tp->t_oproc = dhustart;
193: /*
194: * While setting up state for this uba and this dhu,
195: * block uba resets which can clear the state.
196: */
197: s = spl5();
198: if (cbase[ui->ui_ubanum] == -1) {
199: dhu_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(dhu_ubinfo[ui->ui_ubanum]);
203: }
204: if ((dhuact&(1<<dhu)) == 0) {
205: addr->dhucsr = DHU_SELECT(0) | DHU_IE;
206: addr->dhutimo = DHU_DEF_TIMO;
207: dhuact |= (1<<dhu);
208: /* anything else to configure whole board */
209: }
210: (void) splx(s);
211: /*
212: * If this is first open, initialize tty state to default.
213: */
214: if ((tp->t_state&TS_ISOPEN) == 0) {
215: ttychars(tp);
216: #ifndef PORTSELECTOR
217: if (tp->t_ispeed == 0) {
218: #else
219: tp->t_state |= TS_HUPCLS;
220: #endif PORTSELECTOR
221: tp->t_ispeed = ISPEED;
222: tp->t_ospeed = ISPEED;
223: tp->t_flags = IFLAGS;
224: #ifndef PORTSELECTOR
225: }
226: #endif PORTSELECTOR
227: tp->t_dev = dev;
228: dhuparam(unit);
229: }
230: /*
231: * Wait for carrier, then process line discipline specific open.
232: */
233: s = spl5();
234: if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) ||
235: (dhusoftCAR[dhu] & (1<<(unit&0xf))))
236: tp->t_state |= TS_CARR_ON;
237: while ((tp->t_state & TS_CARR_ON) == 0) {
238: tp->t_state |= TS_WOPEN;
239: sleep((caddr_t)&tp->t_rawq, TTIPRI);
240: }
241: (void) splx(s);
242: return ((*linesw[tp->t_line].l_open)(dev, tp));
243: }
244:
245: /*
246: * Close a DHU11 line, turning off the modem control.
247: */
248: /*ARGSUSED*/
249: dhuclose(dev, flag)
250: dev_t dev;
251: int flag;
252: {
253: register struct tty *tp;
254: register unit;
255:
256: unit = UNIT(dev);
257: tp = &dhu_tty[unit];
258: (*linesw[tp->t_line].l_close)(tp);
259: (void) dhumctl(unit, DHU_BRK, DMBIC);
260: if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0)
261: #ifdef PORTSELECTOR
262: {
263: extern int wakeup();
264:
265: (void) dhumctl(unit, DHU_OFF, DMSET);
266: /* Hold DTR low for 0.5 seconds */
267: timeout(wakeup, (caddr_t) &tp->t_dev, hz/2);
268: sleep((caddr_t) &tp->t_dev, PZERO);
269: }
270: #else
271: (void) dhumctl(unit, DHU_OFF, DMSET);
272: #endif PORTSELECTOR
273: ttyclose(tp);
274: }
275:
276: dhuread(dev, uio)
277: dev_t dev;
278: struct uio *uio;
279: {
280: register struct tty *tp = &dhu_tty[UNIT(dev)];
281:
282: return ((*linesw[tp->t_line].l_read)(tp, uio));
283: }
284:
285: dhuwrite(dev, uio)
286: dev_t dev;
287: struct uio *uio;
288: {
289: register struct tty *tp = &dhu_tty[UNIT(dev)];
290:
291: return ((*linesw[tp->t_line].l_write)(tp, uio));
292: }
293:
294: /*
295: * DHU11 receiver interrupt.
296: */
297: dhurint(dhu)
298: int dhu;
299: {
300: register struct tty *tp;
301: register c;
302: register struct dhudevice *addr;
303: register struct tty *tp0;
304: register struct uba_device *ui;
305: register line;
306: int overrun = 0;
307:
308: #ifdef VAX630
309: (void) spl5();
310: #endif
311: ui = dhuinfo[dhu];
312: if (ui == 0 || ui->ui_alive == 0)
313: return;
314: addr = (struct dhudevice *)ui->ui_addr;
315: tp0 = &dhu_tty[dhu<<4];
316: /*
317: * Loop fetching characters from the silo for this
318: * dhu until there are no more in the silo.
319: */
320: while ((c = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */
321: line = DHU_RX_LINE(c);
322: tp = tp0 + line;
323: if ((c & DHU_RB_STAT) == DHU_RB_STAT) {
324: /*
325: * modem changed or diag info
326: */
327: if (c & DHU_RB_DIAG) {
328: /* decode diagnostic messages */
329: continue;
330: }
331: if (c & DHU_ST_DCD)
332: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
333: else if ((dhusoftCAR[dhu] & (1<<line)) == 0 &&
334: (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
335: (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET);
336: continue;
337: }
338: if ((tp->t_state&TS_ISOPEN) == 0) {
339: wakeup((caddr_t)&tp->t_rawq);
340: #ifdef PORTSELECTOR
341: if ((tp->t_state&TS_WOPEN) == 0)
342: #endif
343: continue;
344: }
345: if (c & DHU_RB_PE)
346: if ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
347: (tp->t_flags&(EVENP|ODDP)) == ODDP)
348: continue;
349: if ((c & DHU_RB_DO) && overrun == 0) {
350: log(LOG_WARNING, "dhu%d: silo overflow\n", dhu);
351: overrun = 1;
352: }
353: if (c & DHU_RB_FE)
354: /*
355: * At framing error (break) generate
356: * a null (in raw mode, for getty), or a
357: * interrupt (in cooked/cbreak mode).
358: */
359: if (tp->t_flags&RAW)
360: c = 0;
361: else
362: c = tp->t_intrc;
363: #if NBK > 0
364: if (tp->t_line == NETLDISC) {
365: c &= 0x7f;
366: BKINPUT(c, tp);
367: } else
368: #endif
369: (*linesw[tp->t_line].l_rint)(c, tp);
370: }
371: }
372:
373: /*
374: * Ioctl for DHU11.
375: */
376: /*ARGSUSED*/
377: dhuioctl(dev, cmd, data, flag)
378: caddr_t data;
379: {
380: register struct tty *tp;
381: register int unit = UNIT(dev);
382: int error;
383:
384: tp = &dhu_tty[unit];
385: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
386: if (error >= 0)
387: return (error);
388: error = ttioctl(tp, cmd, data, flag);
389: if (error >= 0) {
390: if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET ||
391: cmd == TIOCLBIC || cmd == TIOCLBIS)
392: dhuparam(unit);
393: return (error);
394: }
395:
396: switch (cmd) {
397: case TIOCSBRK:
398: (void) dhumctl(unit, DHU_BRK, DMBIS);
399: break;
400:
401: case TIOCCBRK:
402: (void) dhumctl(unit, DHU_BRK, DMBIC);
403: break;
404:
405: case TIOCSDTR:
406: (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS);
407: break;
408:
409: case TIOCCDTR:
410: (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC);
411: break;
412:
413: case TIOCMSET:
414: (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET);
415: break;
416:
417: case TIOCMBIS:
418: (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS);
419: break;
420:
421: case TIOCMBIC:
422: (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC);
423: break;
424:
425: case TIOCMGET:
426: *(int *)data = dhutodm(dhumctl(dev, 0, DMGET));
427: break;
428: default:
429: return (ENOTTY);
430: }
431: return (0);
432: }
433:
434: dmtodhu(bits)
435: register int bits;
436: {
437: register int b = 0;
438:
439: if (bits & DML_RTS) b |= DHU_RTS;
440: if (bits & DML_DTR) b |= DHU_DTR;
441: if (bits & DML_LE) b |= DHU_LE;
442: return(b);
443: }
444:
445: dhutodm(bits)
446: register int bits;
447: {
448: register int b = 0;
449:
450: if (bits & DHU_DSR) b |= DML_DSR;
451: if (bits & DHU_RNG) b |= DML_RNG;
452: if (bits & DHU_CAR) b |= DML_CAR;
453: if (bits & DHU_CTS) b |= DML_CTS;
454: if (bits & DHU_RTS) b |= DML_RTS;
455: if (bits & DHU_DTR) b |= DML_DTR;
456: if (bits & DHU_LE) b |= DML_LE;
457: return(b);
458: }
459:
460:
461: /*
462: * Set parameters from open or stty into the DHU hardware
463: * registers.
464: */
465: dhuparam(unit)
466: register int unit;
467: {
468: register struct tty *tp;
469: register struct dhudevice *addr;
470: register int lpar;
471: int s;
472:
473: tp = &dhu_tty[unit];
474: addr = (struct dhudevice *)tp->t_addr;
475: /*
476: * Block interrupts so parameters will be set
477: * before the line interrupts.
478: */
479: s = spl5();
480: if ((tp->t_ispeed) == 0) {
481: tp->t_state |= TS_HUPCLS;
482: (void)dhumctl(unit, DHU_OFF, DMSET);
483: splx(s);
484: return;
485: }
486: lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8);
487: if ((tp->t_ispeed) == B134)
488: lpar |= DHU_LP_BITS6|DHU_LP_PENABLE;
489: else if (tp->t_flags & (RAW|LITOUT|PASS8))
490: lpar |= DHU_LP_BITS8;
491: else
492: lpar |= DHU_LP_BITS7|DHU_LP_PENABLE;
493: if (tp->t_flags&EVENP)
494: lpar |= DHU_LP_EPAR;
495: if ((tp->t_ospeed) == B110)
496: lpar |= DHU_LP_TWOSB;
497: addr->dhucsr = DHU_SELECT(unit) | DHU_IE;
498: addr->dhulpr = lpar;
499: splx(s);
500: }
501:
502: /*
503: * DHU11 transmitter interrupt.
504: * Restart each line which used to be active but has
505: * terminated transmission since the last interrupt.
506: */
507: dhuxint(dhu)
508: int dhu;
509: {
510: register struct tty *tp;
511: register struct dhudevice *addr;
512: register struct tty *tp0;
513: register struct uba_device *ui;
514: register int line, t;
515: u_short cntr;
516:
517: #ifdef VAX630
518: (void) spl5();
519: #endif
520: ui = dhuinfo[dhu];
521: tp0 = &dhu_tty[dhu<<4];
522: addr = (struct dhudevice *)ui->ui_addr;
523: while ((t = addr->dhucsrh) & DHU_CSH_TI) {
524: line = DHU_TX_LINE(t);
525: tp = tp0 + line;
526: tp->t_state &= ~TS_BUSY;
527: if (t & DHU_CSH_NXM) {
528: printf("dhu(%d,%d): NXM fault\n", dhu, line);
529: /* SHOULD RESTART OR SOMETHING... */
530: }
531: if (tp->t_state&TS_FLUSH)
532: tp->t_state &= ~TS_FLUSH;
533: else {
534: addr->dhucsrl = DHU_SELECT(line) | DHU_IE;
535: /*
536: * Do arithmetic in a short to make up
537: * for lost 16&17 bits.
538: */
539: cntr = addr->dhubar1 -
540: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
541: ndflush(&tp->t_outq, (int)cntr);
542: }
543: if (tp->t_line)
544: (*linesw[tp->t_line].l_start)(tp);
545: else
546: dhustart(tp);
547: }
548: }
549:
550: /*
551: * Start (restart) transmission on the given DHU11 line.
552: */
553: dhustart(tp)
554: register struct tty *tp;
555: {
556: register struct dhudevice *addr;
557: register int car, dhu, unit, nch;
558: int s;
559:
560: unit = minor(tp->t_dev);
561: dhu = unit >> 4;
562: unit &= 0xf;
563: addr = (struct dhudevice *)tp->t_addr;
564:
565: /*
566: * Must hold interrupts in following code to prevent
567: * state of the tp from changing.
568: */
569: s = spl5();
570: /*
571: * If it's currently active, or delaying, no need to do anything.
572: */
573: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
574: goto out;
575: /*
576: * If there are sleepers, and output has drained below low
577: * water mark, wake up the sleepers..
578: */
579: if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
580: if (tp->t_state&TS_ASLEEP) {
581: tp->t_state &= ~TS_ASLEEP;
582: wakeup((caddr_t)&tp->t_outq);
583: }
584: if (tp->t_wsel) {
585: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
586: tp->t_wsel = 0;
587: tp->t_state &= ~TS_WCOLL;
588: }
589: }
590: /*
591: * Now restart transmission unless the output queue is
592: * empty.
593: */
594: if (tp->t_outq.c_cc == 0)
595: goto out;
596: if (tp->t_flags & (RAW|LITOUT))
597: nch = ndqb(&tp->t_outq, 0);
598: else {
599: nch = ndqb(&tp->t_outq, 0200);
600: /*
601: * If first thing on queue is a delay process it.
602: */
603: if (nch == 0) {
604: nch = getc(&tp->t_outq);
605: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
606: tp->t_state |= TS_TIMEOUT;
607: goto out;
608: }
609: }
610: /*
611: * If characters to transmit, restart transmission.
612: */
613: if (nch) {
614: car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);
615: addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
616: addr->dhulcr &= ~DHU_LC_TXABORT;
617: addr->dhubcr = nch;
618: addr->dhubar1 = car;
619: addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) |
620: DHU_BA2_DMAGO;
621: tp->t_state |= TS_BUSY;
622: }
623: out:
624: splx(s);
625: }
626:
627: /*
628: * Stop output on a line, e.g. for ^S/^Q or output flush.
629: */
630: /*ARGSUSED*/
631: dhustop(tp, flag)
632: register struct tty *tp;
633: {
634: register struct dhudevice *addr;
635: register int unit, s;
636:
637: addr = (struct dhudevice *)tp->t_addr;
638: /*
639: * Block input/output interrupts while messing with state.
640: */
641: s = spl5();
642: if (tp->t_state & TS_BUSY) {
643: /*
644: * Device is transmitting; stop output
645: * by selecting the line and setting the
646: * abort xmit bit. We will get an xmit interrupt,
647: * where we will figure out where to continue the
648: * next time the transmitter is enabled. If
649: * TS_FLUSH is set, the outq will be flushed.
650: * In either case, dhustart will clear the TXABORT bit.
651: */
652: unit = minor(tp->t_dev);
653: addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
654: addr->dhulcr |= DHU_LC_TXABORT;
655: if ((tp->t_state&TS_TTSTOP)==0)
656: tp->t_state |= TS_FLUSH;
657: }
658: (void) splx(s);
659: }
660:
661: /*
662: * DHU11 modem control
663: */
664: dhumctl(dev, bits, how)
665: dev_t dev;
666: int bits, how;
667: {
668: register struct dhudevice *dhuaddr;
669: register int unit, mbits;
670: int s;
671:
672: unit = UNIT(dev);
673: dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr);
674: unit &= 0xf;
675: s = spl5();
676: dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE;
677: /*
678: * combine byte from stat register (read only, bits 16..23)
679: * with lcr register (read write, bits 0..15).
680: */
681: mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16);
682: switch (how) {
683: case DMSET:
684: mbits = (mbits & 0xff0000) | bits;
685: break;
686:
687: case DMBIS:
688: mbits |= bits;
689: break;
690:
691: case DMBIC:
692: mbits &= ~bits;
693: break;
694:
695: case DMGET:
696: (void) splx(s);
697: return(mbits);
698: }
699: dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN;
700: dhuaddr->dhulcr2 = DHU_LC2_TXEN;
701: (void) splx(s);
702: return(mbits);
703: }
704:
705: /*
706: * Reset state of driver if UBA reset was necessary.
707: * Reset the line and modem control registers.
708: * restart transmitters.
709: */
710: dhureset(uban)
711: int uban;
712: {
713: register int dhu, unit;
714: register struct tty *tp;
715: register struct uba_device *ui;
716: register struct dhudevice *addr;
717: int i;
718:
719: for (dhu = 0; dhu < NDHU; dhu++) {
720: ui = dhuinfo[dhu];
721: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
722: continue;
723: printf(" dhu%d", dhu);
724: if (dhu_ubinfo[uban]) {
725: dhu_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
726: nclist*sizeof (struct cblock), 0);
727: cbase[uban] = UBAI_ADDR(dhu_ubinfo[uban]);
728: }
729: addr = (struct dhudevice *)ui->ui_addr;
730: addr->dhucsr = DHU_SELECT(0) | DHU_IE;
731: addr->dhutimo = DHU_DEF_TIMO;
732: unit = dhu * 16;
733: for (i = 0; i < 16; i++) {
734: tp = &dhu_tty[unit];
735: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
736: dhuparam(unit);
737: (void)dhumctl(unit, DHU_ON, DMSET);
738: tp->t_state &= ~TS_BUSY;
739: dhustart(tp);
740: }
741: unit++;
742: }
743: }
744: }
745: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.