|
|
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.