|
|
1.1 ! root 1: /* dmf.c 6.1 83/07/29 */ ! 2: ! 3: #include "dmf.h" ! 4: #if NDMF > 0 ! 5: /* ! 6: * DMF32 driver ! 7: * ! 8: * TODO: ! 9: * test with modem ! 10: * load as much as possible into silo ! 11: * get correct numbers for receive silo parameter timeout ! 12: * use auto XON/XOFF ! 13: * test reset code ! 14: * test with more than one unit ! 15: * optimize for efficient DMA and dynamically ! 16: * decide between silo and DMA mode ! 17: */ ! 18: #include "../machine/pte.h" ! 19: ! 20: #include "bk.h" ! 21: #include "../h/param.h" ! 22: #include "../h/conf.h" ! 23: #include "../h/dir.h" ! 24: #include "../h/user.h" ! 25: #include "../h/ioctl.h" ! 26: #include "../h/tty.h" ! 27: #include "../h/map.h" ! 28: #include "../h/buf.h" ! 29: #include "../h/vm.h" ! 30: #include "../h/bk.h" ! 31: #include "../h/clist.h" ! 32: #include "../h/file.h" ! 33: #include "../h/uio.h" ! 34: ! 35: #include "../vaxuba/ubareg.h" ! 36: #include "../vaxuba/ubavar.h" ! 37: #include "../vaxuba/dmfreg.h" ! 38: ! 39: /* ! 40: * Definition of the driver for the auto-configuration program. ! 41: */ ! 42: int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); ! 43: struct uba_device *dmfinfo[NDMF]; ! 44: u_short dmfstd[] = { 0 }; ! 45: struct uba_driver dmfdriver = ! 46: { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; ! 47: ! 48: /* ! 49: * Local variables for the driver ! 50: */ ! 51: char dmf_speeds[] = ! 52: { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; ! 53: ! 54: struct tty dmf_tty[NDMF*8]; ! 55: char dmfsoftCAR[NDMF]; ! 56: #ifndef lint ! 57: int ndmf = NDMF*8; /* used by iostat */ ! 58: #endif ! 59: int dmfact; /* mask of active dmf's */ ! 60: int dmfstart(), ttrstrt(); ! 61: ! 62: #ifdef DMFDMA ! 63: /* ! 64: * The clist space is mapped by the driver onto each UNIBUS. ! 65: * The UBACVT macro converts a clist space address for unibus uban ! 66: * into an i/o space address for the DMA routine. ! 67: */ ! 68: int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */ ! 69: static int cbase[MAXNUBA]; /* base address in unibus map */ ! 70: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) ! 71: #endif ! 72: ! 73: /* ! 74: * Routine for configuration to set dmf interrupt. ! 75: */ ! 76: /*ARGSUSED*/ ! 77: dmfprobe(reg, ctlr) ! 78: caddr_t reg; ! 79: int ctlr; ! 80: { ! 81: register int br, cvec; /* these are ``value-result'' */ ! 82: register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; ! 83: ! 84: #ifdef lint ! 85: br = 0; cvec = br; br = cvec; ! 86: dmfxint(0); dmfrint(0); ! 87: dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(); ! 88: #endif ! 89: br = 0x15; ! 90: cvec = (uba_hd[numuba].uh_lastiv -= 4*8); ! 91: dmfaddr->dmfccsr0 = cvec >> 2; ! 92: /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ ! 93: return (sizeof (struct dmfdevice)); ! 94: } ! 95: ! 96: /* ! 97: * Routine called to attach a dmf. ! 98: */ ! 99: dmfattach(ui) ! 100: struct uba_device *ui; ! 101: { ! 102: ! 103: dmfsoftCAR[ui->ui_unit] = ui->ui_flags; ! 104: } ! 105: ! 106: ! 107: /* ! 108: * Open a DMF32 line, mapping the clist onto the uba if this ! 109: * is the first dmf on this uba. Turn on this dmf if this is ! 110: * the first use of it. ! 111: */ ! 112: /*ARGSUSED*/ ! 113: dmfopen(dev, flag) ! 114: dev_t dev; ! 115: { ! 116: register struct tty *tp; ! 117: register int unit, dmf; ! 118: register struct dmfdevice *addr; ! 119: register struct uba_device *ui; ! 120: int s; ! 121: ! 122: unit = minor(dev); ! 123: dmf = unit >> 3; ! 124: if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) ! 125: return (ENXIO); ! 126: tp = &dmf_tty[unit]; ! 127: if (tp->t_state&TS_XCLUDE && u.u_uid!=0) ! 128: return (EBUSY); ! 129: addr = (struct dmfdevice *)ui->ui_addr; ! 130: tp->t_addr = (caddr_t)addr; ! 131: tp->t_oproc = dmfstart; ! 132: tp->t_state |= TS_WOPEN; ! 133: /* ! 134: * While setting up state for this uba and this dmf, ! 135: * block uba resets which can clear the state. ! 136: */ ! 137: s = spl5(); ! 138: #ifdef DMFDMA ! 139: if (dmf_ubinfo[ui->ui_ubanum] == 0) { ! 140: dmf_ubinfo[ui->ui_ubanum] = ! 141: uballoc(ui->ui_ubanum, (caddr_t)cfree, ! 142: nclist*sizeof(struct cblock), 0); ! 143: cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff; ! 144: } ! 145: #endif ! 146: if ((dmfact&(1<<dmf)) == 0) { ! 147: addr->dmfcsr |= DMF_IE; ! 148: dmfact |= (1<<dmf); ! 149: addr->dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */ ! 150: } ! 151: splx(s); ! 152: /* ! 153: * If this is first open, initialze tty state to default. ! 154: */ ! 155: if ((tp->t_state&TS_ISOPEN) == 0) { ! 156: ttychars(tp); ! 157: if (tp->t_ispeed == 0) { ! 158: tp->t_ispeed = B300; ! 159: tp->t_ospeed = B300; ! 160: tp->t_flags = ODDP|EVENP|ECHO; ! 161: } ! 162: dmfparam(unit); ! 163: } ! 164: /* ! 165: * Wait for carrier, then process line discipline specific open. ! 166: */ ! 167: if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || ! 168: (dmfsoftCAR[dmf] & (1<<(unit&07)))) ! 169: tp->t_state |= TS_CARR_ON; ! 170: s = spl5(); ! 171: while ((tp->t_state & TS_CARR_ON) == 0) { ! 172: tp->t_state |= TS_WOPEN; ! 173: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 174: } ! 175: splx(s); ! 176: return ((*linesw[tp->t_line].l_open)(dev, tp)); ! 177: } ! 178: ! 179: /* ! 180: * Close a DMF32 line. ! 181: */ ! 182: /*ARGSUSED*/ ! 183: dmfclose(dev, flag) ! 184: dev_t dev; ! 185: int flag; ! 186: { ! 187: register struct tty *tp; ! 188: register unit; ! 189: ! 190: unit = minor(dev); ! 191: tp = &dmf_tty[unit]; ! 192: (*linesw[tp->t_line].l_close)(tp); ! 193: (void) dmfmctl(unit, DMF_BRK, DMBIC); ! 194: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) ! 195: (void) dmfmctl(unit, DMF_OFF, DMSET); ! 196: ttyclose(tp); ! 197: } ! 198: ! 199: dmfread(dev, uio) ! 200: dev_t dev; ! 201: struct uio *uio; ! 202: { ! 203: register struct tty *tp; ! 204: ! 205: tp = &dmf_tty[minor(dev)]; ! 206: return ((*linesw[tp->t_line].l_read)(tp, uio)); ! 207: } ! 208: ! 209: dmfwrite(dev, uio) ! 210: dev_t dev; ! 211: struct uio *uio; ! 212: { ! 213: register struct tty *tp; ! 214: ! 215: tp = &dmf_tty[minor(dev)]; ! 216: return ((*linesw[tp->t_line].l_write)(tp, uio)); ! 217: } ! 218: ! 219: /* ! 220: * DMF32 receiver interrupt. ! 221: */ ! 222: dmfrint(dmf) ! 223: int dmf; ! 224: { ! 225: register struct tty *tp; ! 226: register c; ! 227: register struct dmfdevice *addr; ! 228: register struct tty *tp0; ! 229: register struct uba_device *ui; ! 230: int overrun = 0, s; ! 231: ! 232: ui = dmfinfo[dmf]; ! 233: if (ui == 0 || ui->ui_alive == 0) ! 234: return; ! 235: addr = (struct dmfdevice *)ui->ui_addr; ! 236: tp0 = &dmf_tty[dmf<<3]; ! 237: /* ! 238: * Loop fetching characters from the silo for this ! 239: * dmf until there are no more in the silo. ! 240: */ ! 241: while ((c = addr->dmfrbuf) < 0) { ! 242: tp = tp0 + ((c>>8)&07); ! 243: if (c & DMF_DSC) { ! 244: s = spl5(); ! 245: addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07); ! 246: if (addr->dmfrms & DMF_CAR) { ! 247: if ((tp->t_state & TS_CARR_ON) == 0) { ! 248: wakeup((caddr_t)&tp->t_rawq); ! 249: tp->t_state |= TS_CARR_ON; ! 250: } ! 251: } else { ! 252: if (tp->t_state & TS_CARR_ON) { ! 253: gsignal(tp->t_pgrp, SIGHUP); ! 254: gsignal(tp->t_pgrp, SIGCONT); ! 255: addr->dmfcsr = DMF_IE | DMFIR_LCR | ! 256: ((c>>8)&07); ! 257: addr->dmftms = 0; ! 258: ttyflush(tp, FREAD|FWRITE); ! 259: } ! 260: tp->t_state &= ~TS_CARR_ON; ! 261: } ! 262: splx(s); ! 263: continue; ! 264: } ! 265: if ((tp->t_state&TS_ISOPEN)==0) { ! 266: wakeup((caddr_t)tp); ! 267: continue; ! 268: } ! 269: if (c & DMF_PE) ! 270: if ((tp->t_flags&(EVENP|ODDP))==EVENP ! 271: || (tp->t_flags&(EVENP|ODDP))==ODDP ) ! 272: continue; ! 273: if ((c & DMF_DO) && overrun == 0) { ! 274: printf("dmf%d: silo overflow\n", dmf); ! 275: overrun = 1; ! 276: } ! 277: if (c & DMF_FE) ! 278: /* ! 279: * At framing error (break) generate ! 280: * a null (in raw mode, for getty), or a ! 281: * interrupt (in cooked/cbreak mode). ! 282: */ ! 283: if (tp->t_flags&RAW) ! 284: c = 0; ! 285: else ! 286: c = tp->t_intrc; ! 287: #if NBK > 0 ! 288: if (tp->t_line == NETLDISC) { ! 289: c &= 0177; ! 290: BKINPUT(c, tp); ! 291: } else ! 292: #endif ! 293: (*linesw[tp->t_line].l_rint)(c, tp); ! 294: } ! 295: } ! 296: ! 297: /* ! 298: * Ioctl for DMF32. ! 299: */ ! 300: /*ARGSUSED*/ ! 301: dmfioctl(dev, cmd, data, flag) ! 302: dev_t dev; ! 303: caddr_t data; ! 304: { ! 305: register struct tty *tp; ! 306: register int unit = minor(dev); ! 307: int error; ! 308: ! 309: tp = &dmf_tty[unit]; ! 310: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 311: if (error >= 0) ! 312: return (error); ! 313: error = ttioctl(tp, cmd, data, flag); ! 314: if (error >= 0) { ! 315: if (cmd == TIOCSETP || cmd == TIOCSETN) ! 316: dmfparam(unit); ! 317: return (error); ! 318: } ! 319: switch (cmd) { ! 320: ! 321: case TIOCSBRK: ! 322: (void) dmfmctl(dev, DMF_BRK, DMBIS); ! 323: break; ! 324: ! 325: case TIOCCBRK: ! 326: (void) dmfmctl(dev, DMF_BRK, DMBIC); ! 327: break; ! 328: ! 329: case TIOCSDTR: ! 330: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); ! 331: break; ! 332: ! 333: case TIOCCDTR: ! 334: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); ! 335: break; ! 336: ! 337: case TIOCMSET: ! 338: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); ! 339: break; ! 340: ! 341: case TIOCMBIS: ! 342: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); ! 343: break; ! 344: ! 345: case TIOCMBIC: ! 346: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); ! 347: break; ! 348: ! 349: case TIOCMGET: ! 350: *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); ! 351: break; ! 352: ! 353: default: ! 354: return (ENOTTY); ! 355: } ! 356: return (0); ! 357: } ! 358: ! 359: dmtodmf(bits) ! 360: register int bits; ! 361: { ! 362: register int b; ! 363: ! 364: b = bits & 012; ! 365: if (bits & DML_ST) b |= DMF_RATE; ! 366: if (bits & DML_RTS) b |= DMF_RTS; ! 367: if (bits & DML_USR) b |= DMF_USRW; ! 368: return(b); ! 369: } ! 370: ! 371: dmftodm(bits) ! 372: register int bits; ! 373: { ! 374: register int b; ! 375: ! 376: b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; ! 377: if (bits & DMF_USRR) b |= DML_USR; ! 378: if (bits & DMF_RTS) b |= DML_RTS; ! 379: return(b); ! 380: } ! 381: ! 382: ! 383: /* ! 384: * Set parameters from open or stty into the DMF hardware ! 385: * registers. ! 386: */ ! 387: dmfparam(unit) ! 388: register int unit; ! 389: { ! 390: register struct tty *tp; ! 391: register struct dmfdevice *addr; ! 392: register int lpar, lcr; ! 393: int s; ! 394: ! 395: tp = &dmf_tty[unit]; ! 396: addr = (struct dmfdevice *)tp->t_addr; ! 397: /* ! 398: * Block interrupts so parameters will be set ! 399: * before the line interrupts. ! 400: */ ! 401: s = spl5(); ! 402: addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; ! 403: if ((tp->t_ispeed)==0) { ! 404: tp->t_state |= TS_HUPCLS; ! 405: (void) dmfmctl(unit, DMF_OFF, DMSET); ! 406: return; ! 407: } ! 408: lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); ! 409: lcr = DMFLCR_ENA; ! 410: if ((tp->t_ispeed) == B134) ! 411: lpar |= BITS6|PENABLE; ! 412: else if (tp->t_flags & (RAW|LITOUT)) ! 413: lpar |= BITS8; ! 414: else { ! 415: lpar |= BITS7|PENABLE; ! 416: /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ ! 417: } ! 418: if (tp->t_flags&EVENP) ! 419: lpar |= EPAR; ! 420: if ((tp->t_ospeed) == B110) ! 421: lpar |= TWOSB; ! 422: lpar |= (unit&07); ! 423: addr->dmflpr = lpar; ! 424: SETLCR(addr, lcr); ! 425: splx(s); ! 426: } ! 427: ! 428: /* ! 429: * DMF32 transmitter interrupt. ! 430: * Restart the idle line. ! 431: */ ! 432: dmfxint(dmf) ! 433: int dmf; ! 434: { ! 435: register struct tty *tp; ! 436: register struct dmfdevice *addr; ! 437: register struct uba_device *ui; ! 438: register int unit, t; ! 439: #ifdef DMFDMA ! 440: short cntr; ! 441: int s; ! 442: #endif ! 443: ! 444: ui = dmfinfo[dmf]; ! 445: addr = (struct dmfdevice *)ui->ui_addr; ! 446: while ((t = addr->dmfcsr) & DMF_TI) { ! 447: unit = dmf*8 + ((t>>8)&07); ! 448: tp = &dmf_tty[unit]; ! 449: tp->t_state &= ~TS_BUSY; ! 450: if (t & DMF_NXM) { ! 451: printf("dmf%d: NXM line %d\n", dmf, unit&7); ! 452: /* SHOULD RESTART OR SOMETHING... */ ! 453: } ! 454: if (tp->t_state&TS_FLUSH) ! 455: tp->t_state &= ~TS_FLUSH; ! 456: #ifdef DMFDMA ! 457: else { ! 458: s = spl5(); ! 459: addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07); ! 460: if (addr->dmftsc == 0) { ! 461: /* ! 462: * Do arithmetic in a short to make up ! 463: * for lost 16&17 bits. ! 464: */ ! 465: addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07); ! 466: cntr = addr->dmftba - ! 467: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); ! 468: ndflush(&tp->t_outq, (int)cntr); ! 469: } ! 470: splx(s); ! 471: } ! 472: #endif ! 473: if (tp->t_line) ! 474: (*linesw[tp->t_line].l_start)(tp); ! 475: else ! 476: dmfstart(tp); ! 477: } ! 478: } ! 479: ! 480: /* ! 481: * Start (restart) transmission on the given DMF32 line. ! 482: */ ! 483: dmfstart(tp) ! 484: register struct tty *tp; ! 485: { ! 486: register struct dmfdevice *addr; ! 487: register int unit, nch; ! 488: int s; ! 489: ! 490: unit = minor(tp->t_dev); ! 491: unit &= 07; ! 492: addr = (struct dmfdevice *)tp->t_addr; ! 493: ! 494: /* ! 495: * Must hold interrupts in following code to prevent ! 496: * state of the tp from changing. ! 497: */ ! 498: s = spl5(); ! 499: /* ! 500: * If it's currently active, or delaying, no need to do anything. ! 501: */ ! 502: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 503: goto out; ! 504: /* ! 505: * If there are still characters in the silo, ! 506: * just reenable the transmitter. ! 507: */ ! 508: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; ! 509: if (addr->dmftsc) { ! 510: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; ! 511: SETLCR(addr, addr->dmflcr|DMF_TE); ! 512: tp->t_state |= TS_BUSY; ! 513: goto out; ! 514: } ! 515: /* ! 516: * If there are sleepers, and output has drained below low ! 517: * water mark, wake up the sleepers. ! 518: */ ! 519: if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { ! 520: tp->t_state &= ~TS_ASLEEP; ! 521: wakeup((caddr_t)&tp->t_outq); ! 522: } ! 523: /* ! 524: * Now restart transmission unless the output queue is ! 525: * empty. ! 526: */ ! 527: if (tp->t_outq.c_cc == 0) ! 528: goto out; ! 529: if (tp->t_flags & (RAW|LITOUT)) ! 530: nch = ndqb(&tp->t_outq, 0); ! 531: else { ! 532: nch = ndqb(&tp->t_outq, 0200); ! 533: /* ! 534: * If first thing on queue is a delay process it. ! 535: */ ! 536: if (nch == 0) { ! 537: nch = getc(&tp->t_outq); ! 538: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); ! 539: tp->t_state |= TS_TIMEOUT; ! 540: goto out; ! 541: } ! 542: } ! 543: /* ! 544: * If characters to transmit, restart transmission. ! 545: */ ! 546: if (nch) { ! 547: #ifdef DMFDMA ! 548: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; ! 549: SETLCR(addr, addr->dmflcr|DMF_TE); ! 550: car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); ! 551: addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; ! 552: addr->dmftba = car; ! 553: addr->dmftcc = ((car>>2)&0xc000) | nch; ! 554: #else ! 555: register char *cp = tp->t_outq.c_cf; ! 556: register int i; ! 557: ! 558: nch = MIN(nch, DMF_SILOCNT); ! 559: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; ! 560: SETLCR(addr, addr->dmflcr|DMF_TE); ! 561: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; ! 562: for (i = 0; i < nch; i++) ! 563: addr->dmftbuf = *cp++; ! 564: ndflush(&tp->t_outq, nch); ! 565: #endif ! 566: tp->t_state |= TS_BUSY; ! 567: } ! 568: out: ! 569: splx(s); ! 570: } ! 571: ! 572: /* ! 573: * Stop output on a line, e.g. for ^S/^Q or output flush. ! 574: */ ! 575: /*ARGSUSED*/ ! 576: dmfstop(tp, flag) ! 577: register struct tty *tp; ! 578: { ! 579: register struct dmfdevice *addr; ! 580: register int unit, s; ! 581: ! 582: addr = (struct dmfdevice *)tp->t_addr; ! 583: /* ! 584: * Block input/output interrupts while messing with state. ! 585: */ ! 586: s = spl5(); ! 587: if (tp->t_state & TS_BUSY) { ! 588: /* ! 589: * Device is transmitting; stop output ! 590: * by selecting the line and disabling ! 591: * the transmitter. If this is a flush ! 592: * request then flush the output silo, ! 593: * otherwise we will pick up where we ! 594: * left off by enabling the transmitter. ! 595: */ ! 596: unit = minor(tp->t_dev); ! 597: addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE; ! 598: SETLCR(addr, addr->dmflcr &~ DMF_TE); ! 599: if ((tp->t_state&TS_TTSTOP)==0) { ! 600: tp->t_state |= TS_FLUSH; ! 601: SETLCR(addr, addr->dmflcr|DMF_FLUSH); ! 602: } else ! 603: tp->t_state &= ~TS_BUSY; ! 604: } ! 605: splx(s); ! 606: } ! 607: ! 608: /* ! 609: * DMF32 modem control ! 610: */ ! 611: dmfmctl(dev, bits, how) ! 612: dev_t dev; ! 613: int bits, how; ! 614: { ! 615: register struct dmfdevice *dmfaddr; ! 616: register int unit, mbits, lcr; ! 617: int s; ! 618: ! 619: unit = minor(dev); ! 620: dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); ! 621: unit &= 07; ! 622: s = spl5(); ! 623: dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; ! 624: mbits = dmfaddr->dmfrms << 8; ! 625: dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; ! 626: mbits |= dmfaddr->dmftms; ! 627: lcr = dmfaddr->dmflcr; ! 628: switch (how) { ! 629: case DMSET: ! 630: mbits = (mbits &0xff00) | bits; ! 631: break; ! 632: ! 633: case DMBIS: ! 634: mbits |= bits; ! 635: break; ! 636: ! 637: case DMBIC: ! 638: mbits &= ~bits; ! 639: break; ! 640: ! 641: case DMGET: ! 642: (void) splx(s); ! 643: return(mbits); ! 644: } ! 645: if (mbits & DMF_BRK) ! 646: lcr |= DMF_RBRK; ! 647: else ! 648: lcr &= ~DMF_RBRK; ! 649: lcr = ((mbits & 037) << 8) | (lcr & 0xff); ! 650: dmfaddr->dmfun.dmfirw = lcr; ! 651: (void) splx(s); ! 652: return(mbits); ! 653: } ! 654: ! 655: /* ! 656: * Reset state of driver if UBA reset was necessary. ! 657: * Reset the csr, lpr, and lcr registers on open lines, and ! 658: * restart transmitters. ! 659: */ ! 660: dmfreset(uban) ! 661: int uban; ! 662: { ! 663: register int dmf, unit; ! 664: register struct tty *tp; ! 665: register struct uba_device *ui; ! 666: register struct dmfdevice *addr; ! 667: int i; ! 668: ! 669: #ifdef DMFDMA ! 670: if (dmf_ubinfo[uban] == 0) ! 671: return; ! 672: dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, ! 673: nclist*sizeof (struct cblock), 0); ! 674: cbase[uban] = dmf_ubinfo[uban]&0x3ffff; ! 675: #endif ! 676: for (dmf = 0; dmf < NDMF; dmf++) { ! 677: ui = dmfinfo[dmf]; ! 678: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) ! 679: continue; ! 680: printf(" dmf%d", dmf); ! 681: addr = (struct dmfdevice *)ui->ui_addr; ! 682: addr->dmfcsr = DMF_IE; ! 683: addr->dmfrsp = 1; ! 684: unit = dmf * 8; ! 685: for (i = 0; i < 8; i++) { ! 686: tp = &dmf_tty[unit]; ! 687: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { ! 688: dmfparam(unit); ! 689: (void) dmfmctl(unit, DMF_ON, DMSET); ! 690: tp->t_state &= ~TS_BUSY; ! 691: dmfstart(tp); ! 692: } ! 693: unit++; ! 694: } ! 695: } ! 696: } ! 697: ! 698: /* stubs for interrupt routines for devices not yet supported */ ! 699: ! 700: dmfsrint() { printf("dmfsrint\n"); } ! 701: ! 702: dmfsxint() { printf("dmfsxint\n"); } ! 703: ! 704: dmfdaint() { printf("dmfdaint\n"); } ! 705: ! 706: dmfdbint() { printf("dmfdbint\n"); } ! 707: ! 708: dmflint() { printf("dmflint\n"); } ! 709: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.