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