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