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