|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 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: * @(#)dh.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "dh.h" ! 10: #if NDH > 0 ! 11: /* ! 12: * DH-11/DM-11 driver ! 13: */ ! 14: #include "../machine/pte.h" ! 15: ! 16: #include "bk.h" ! 17: #include "uba.h" ! 18: #include "param.h" ! 19: #include "conf.h" ! 20: #include "dir.h" ! 21: #include "user.h" ! 22: #include "proc.h" ! 23: #include "ioctl.h" ! 24: #include "tty.h" ! 25: #include "map.h" ! 26: #include "buf.h" ! 27: #include "vm.h" ! 28: #include "kernel.h" ! 29: #include "syslog.h" ! 30: ! 31: #include "ubareg.h" ! 32: #include "ubavar.h" ! 33: #include "dhreg.h" ! 34: #include "dmreg.h" ! 35: ! 36: #include "bkmac.h" ! 37: #include "clist.h" ! 38: #include "file.h" ! 39: #include "uio.h" ! 40: ! 41: /* ! 42: * Definition of the driver for the auto-configuration program. ! 43: * There is one definition for the dh and one for the dm. ! 44: */ ! 45: int dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer(); ! 46: struct uba_device *dhinfo[NDH]; ! 47: u_short dhstd[] = { 0 }; ! 48: struct uba_driver dhdriver = ! 49: { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo }; ! 50: ! 51: int dmprobe(), dmattach(), dmintr(); ! 52: struct uba_device *dminfo[NDH]; ! 53: u_short dmstd[] = { 0 }; ! 54: struct uba_driver dmdriver = ! 55: { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo }; ! 56: ! 57: #ifndef PORTSELECTOR ! 58: #define ISPEED B9600 ! 59: #define IFLAGS (EVENP|ODDP|ECHO) ! 60: #else ! 61: #define ISPEED B4800 ! 62: #define IFLAGS (EVENP|ODDP) ! 63: #endif ! 64: ! 65: #define FASTTIMER (hz/30) /* scan rate with silos on */ ! 66: ! 67: /* ! 68: * Local variables for the driver ! 69: */ ! 70: short dhsar[NDH]; /* software copy of last bar */ ! 71: short dhsoftCAR[NDH]; ! 72: ! 73: struct tty dh11[NDH*16]; ! 74: int ndh11 = NDH*16; ! 75: int dhact; /* mask of active dh's */ ! 76: int dhsilos; /* mask of dh's with silo in use */ ! 77: int dhchars[NDH]; /* recent input count */ ! 78: int dhrate[NDH]; /* smoothed input count */ ! 79: int dhhighrate = 100; /* silo on if dhchars > dhhighrate */ ! 80: int dhlowrate = 75; /* silo off if dhrate < dhlowrate */ ! 81: static short timerstarted; ! 82: int dhstart(), ttrstrt(); ! 83: ! 84: /* ! 85: * The clist space is mapped by the driver onto each UNIBUS. ! 86: * The UBACVT macro converts a clist space address for unibus uban ! 87: * into an i/o space address for the DMA routine. ! 88: */ ! 89: int dh_ubinfo[NUBA]; /* info about allocated unibus map */ ! 90: int cbase[NUBA]; /* base address in unibus map */ ! 91: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) ! 92: ! 93: /* ! 94: * Routine for configuration to force a dh to interrupt. ! 95: * Set to transmit at 9600 baud, and cause a transmitter interrupt. ! 96: */ ! 97: /*ARGSUSED*/ ! 98: dhprobe(reg) ! 99: caddr_t reg; ! 100: { ! 101: register int br, cvec; /* these are ``value-result'' */ ! 102: register struct dhdevice *dhaddr = (struct dhdevice *)reg; ! 103: ! 104: #ifdef lint ! 105: br = 0; cvec = br; br = cvec; ! 106: if (ndh11 == 0) ndh11 = 1; ! 107: dhrint(0); dhxint(0); ! 108: #endif ! 109: #ifndef notdef ! 110: dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI; ! 111: DELAY(1000); ! 112: dhaddr->un.dhcsr &= ~DH_RI; ! 113: dhaddr->un.dhcsr = 0; ! 114: #else ! 115: dhaddr->un.dhcsr = DH_TIE; ! 116: DELAY(5); ! 117: dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE; ! 118: dhaddr->dhbcr = -1; ! 119: dhaddr->dhcar = 0; ! 120: dhaddr->dhbar = 1; ! 121: DELAY(100000); /* wait 1/10'th of a sec for interrupt */ ! 122: dhaddr->un.dhcsr = 0; ! 123: if (cvec && cvec != 0x200) ! 124: cvec -= 4; /* transmit -> receive */ ! 125: #endif ! 126: return (sizeof (struct dhdevice)); ! 127: } ! 128: ! 129: /* ! 130: * Routine called to attach a dh. ! 131: */ ! 132: dhattach(ui) ! 133: struct uba_device *ui; ! 134: { ! 135: ! 136: dhsoftCAR[ui->ui_unit] = ui->ui_flags; ! 137: cbase[ui->ui_ubanum] = -1; ! 138: } ! 139: ! 140: /* ! 141: * Configuration routine to cause a dm to interrupt. ! 142: */ ! 143: dmprobe(reg) ! 144: caddr_t reg; ! 145: { ! 146: register int br, vec; /* value-result */ ! 147: register struct dmdevice *dmaddr = (struct dmdevice *)reg; ! 148: ! 149: #ifdef lint ! 150: br = 0; vec = br; br = vec; ! 151: dmintr(0); ! 152: #endif ! 153: dmaddr->dmcsr = DM_DONE|DM_IE; ! 154: DELAY(20); ! 155: dmaddr->dmcsr = 0; ! 156: return (1); ! 157: } ! 158: ! 159: /*ARGSUSED*/ ! 160: dmattach(ui) ! 161: struct uba_device *ui; ! 162: { ! 163: ! 164: /* no local state to set up */ ! 165: } ! 166: ! 167: /* ! 168: * Open a DH11 line, mapping the clist onto the uba if this ! 169: * is the first dh on this uba. Turn on this dh if this is ! 170: * the first use of it. Also do a dmopen to wait for carrier. ! 171: */ ! 172: /*ARGSUSED*/ ! 173: dhopen(dev, flag) ! 174: dev_t dev; ! 175: { ! 176: register struct tty *tp; ! 177: register int unit, dh; ! 178: register struct dhdevice *addr; ! 179: register struct uba_device *ui; ! 180: int s; ! 181: ! 182: unit = minor(dev); ! 183: dh = unit >> 4; ! 184: if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0) ! 185: return (ENXIO); ! 186: tp = &dh11[unit]; ! 187: if (tp->t_state&TS_XCLUDE && u.u_uid!=0) ! 188: return (EBUSY); ! 189: addr = (struct dhdevice *)ui->ui_addr; ! 190: tp->t_addr = (caddr_t)addr; ! 191: tp->t_oproc = dhstart; ! 192: tp->t_state |= TS_WOPEN; ! 193: /* ! 194: * While setting up state for this uba and this dh, ! 195: * block uba resets which can clear the state. ! 196: */ ! 197: s = spl5(); ! 198: if (cbase[ui->ui_ubanum] == -1) { ! 199: dh_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(dh_ubinfo[ui->ui_ubanum]); ! 203: } ! 204: if (timerstarted == 0) { ! 205: timerstarted++; ! 206: timeout(dhtimer, (caddr_t) 0, hz); ! 207: } ! 208: if ((dhact&(1<<dh)) == 0) { ! 209: addr->un.dhcsr |= DH_IE; ! 210: dhact |= (1<<dh); ! 211: addr->dhsilo = 0; ! 212: } ! 213: splx(s); ! 214: /* ! 215: * If this is first open, initialize tty state to default. ! 216: */ ! 217: if ((tp->t_state&TS_ISOPEN) == 0) { ! 218: ttychars(tp); ! 219: #ifndef PORTSELECTOR ! 220: if (tp->t_ispeed == 0) { ! 221: #else ! 222: tp->t_state |= TS_HUPCLS; ! 223: #endif PORTSELECTOR ! 224: tp->t_ispeed = ISPEED; ! 225: tp->t_ospeed = ISPEED; ! 226: tp->t_flags = IFLAGS; ! 227: #ifndef PORTSELECTOR ! 228: } ! 229: #endif PORTSELECTOR ! 230: dhparam(unit); ! 231: } ! 232: /* ! 233: * Wait for carrier, then process line discipline specific open. ! 234: */ ! 235: dmopen(dev); ! 236: return ((*linesw[tp->t_line].l_open)(dev, tp)); ! 237: } ! 238: ! 239: /* ! 240: * Close a DH11 line, turning off the DM11. ! 241: */ ! 242: /*ARGSUSED*/ ! 243: dhclose(dev, flag) ! 244: dev_t dev; ! 245: int flag; ! 246: { ! 247: register struct tty *tp; ! 248: register unit; ! 249: ! 250: unit = minor(dev); ! 251: tp = &dh11[unit]; ! 252: (*linesw[tp->t_line].l_close)(tp); ! 253: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); ! 254: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) ! 255: dmctl(unit, DML_OFF, DMSET); ! 256: ttyclose(tp); ! 257: } ! 258: ! 259: dhread(dev, uio) ! 260: dev_t dev; ! 261: struct uio *uio; ! 262: { ! 263: register struct tty *tp = &dh11[minor(dev)]; ! 264: ! 265: return ((*linesw[tp->t_line].l_read)(tp, uio)); ! 266: } ! 267: ! 268: dhwrite(dev, uio) ! 269: dev_t dev; ! 270: struct uio *uio; ! 271: { ! 272: register struct tty *tp = &dh11[minor(dev)]; ! 273: ! 274: return ((*linesw[tp->t_line].l_write)(tp, uio)); ! 275: } ! 276: ! 277: /* ! 278: * DH11 receiver interrupt. ! 279: */ ! 280: dhrint(dh) ! 281: int dh; ! 282: { ! 283: register struct tty *tp; ! 284: register c; ! 285: register struct dhdevice *addr; ! 286: register struct tty *tp0; ! 287: register struct uba_device *ui; ! 288: int overrun = 0; ! 289: ! 290: ui = dhinfo[dh]; ! 291: if (ui == 0 || ui->ui_alive == 0) ! 292: return; ! 293: addr = (struct dhdevice *)ui->ui_addr; ! 294: tp0 = &dh11[dh<<4]; ! 295: /* ! 296: * Loop fetching characters from the silo for this ! 297: * dh until there are no more in the silo. ! 298: */ ! 299: while ((c = addr->dhrcr) < 0) { ! 300: tp = tp0 + ((c>>8)&0xf); ! 301: dhchars[dh]++; ! 302: if ((tp->t_state&TS_ISOPEN)==0) { ! 303: wakeup((caddr_t)&tp->t_rawq); ! 304: #ifdef PORTSELECTOR ! 305: if ((tp->t_state&TS_WOPEN) == 0) ! 306: #endif ! 307: continue; ! 308: } ! 309: if (c & DH_PE) ! 310: if ((tp->t_flags&(EVENP|ODDP))==EVENP ! 311: || (tp->t_flags&(EVENP|ODDP))==ODDP ) ! 312: continue; ! 313: if ((c & DH_DO) && overrun == 0) { ! 314: log(LOG_WARNING, "dh%d: silo overflow\n", dh); ! 315: overrun = 1; ! 316: } ! 317: if (c & DH_FE) ! 318: /* ! 319: * At framing error (break) generate ! 320: * a null (in raw mode, for getty), or a ! 321: * interrupt (in cooked/cbreak mode). ! 322: */ ! 323: if (tp->t_flags&RAW) ! 324: c = 0; ! 325: else ! 326: c = tp->t_intrc; ! 327: #if NBK > 0 ! 328: if (tp->t_line == NETLDISC) { ! 329: c &= 0177; ! 330: BKINPUT(c, tp); ! 331: } else ! 332: #endif ! 333: (*linesw[tp->t_line].l_rint)(c, tp); ! 334: } ! 335: } ! 336: ! 337: /* ! 338: * Ioctl for DH11. ! 339: */ ! 340: /*ARGSUSED*/ ! 341: dhioctl(dev, cmd, data, flag) ! 342: caddr_t data; ! 343: { ! 344: register struct tty *tp; ! 345: register int unit = minor(dev); ! 346: int error; ! 347: ! 348: tp = &dh11[unit]; ! 349: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 350: if (error >= 0) ! 351: return (error); ! 352: error = ttioctl(tp, cmd, data, flag); ! 353: if (error >= 0) { ! 354: if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || ! 355: cmd == TIOCLBIC || cmd == TIOCLSET) ! 356: dhparam(unit); ! 357: return (error); ! 358: } ! 359: switch (cmd) { ! 360: ! 361: case TIOCSBRK: ! 362: ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); ! 363: break; ! 364: ! 365: case TIOCCBRK: ! 366: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); ! 367: break; ! 368: ! 369: case TIOCSDTR: ! 370: dmctl(unit, DML_DTR|DML_RTS, DMBIS); ! 371: break; ! 372: ! 373: case TIOCCDTR: ! 374: dmctl(unit, DML_DTR|DML_RTS, DMBIC); ! 375: break; ! 376: ! 377: default: ! 378: return (ENOTTY); ! 379: } ! 380: return (0); ! 381: } ! 382: ! 383: /* ! 384: * Set parameters from open or stty into the DH hardware ! 385: * registers. ! 386: */ ! 387: dhparam(unit) ! 388: register int unit; ! 389: { ! 390: register struct tty *tp; ! 391: register struct dhdevice *addr; ! 392: register int lpar; ! 393: int s; ! 394: ! 395: tp = &dh11[unit]; ! 396: addr = (struct dhdevice *)tp->t_addr; ! 397: /* ! 398: * Block interrupts so parameters will be set ! 399: * before the line interrupts. ! 400: */ ! 401: s = spl5(); ! 402: addr->un.dhcsrl = (unit&0xf) | DH_IE; ! 403: if ((tp->t_ispeed)==0) { ! 404: tp->t_state |= TS_HUPCLS; ! 405: dmctl(unit, DML_OFF, DMSET); ! 406: splx(s); ! 407: return; ! 408: } ! 409: lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); ! 410: if ((tp->t_ispeed) == B134) ! 411: lpar |= BITS6|PENABLE|HDUPLX; ! 412: else if (tp->t_flags & (RAW|LITOUT|PASS8)) ! 413: lpar |= BITS8; ! 414: else ! 415: lpar |= BITS7|PENABLE; ! 416: if ((tp->t_flags&EVENP) == 0) ! 417: lpar |= OPAR; ! 418: if ((tp->t_ospeed) == B110) ! 419: lpar |= TWOSB; ! 420: addr->dhlpr = lpar; ! 421: splx(s); ! 422: } ! 423: ! 424: /* ! 425: * DH11 transmitter interrupt. ! 426: * Restart each line which used to be active but has ! 427: * terminated transmission since the last interrupt. ! 428: */ ! 429: dhxint(dh) ! 430: int dh; ! 431: { ! 432: register struct tty *tp; ! 433: register struct dhdevice *addr; ! 434: short ttybit, bar, *sbar; ! 435: register struct uba_device *ui; ! 436: register int unit; ! 437: u_short cntr; ! 438: ! 439: ui = dhinfo[dh]; ! 440: addr = (struct dhdevice *)ui->ui_addr; ! 441: if (addr->un.dhcsr & DH_NXM) { ! 442: addr->un.dhcsr |= DH_CNI; ! 443: printf("dh%d: NXM\n", dh); ! 444: } ! 445: sbar = &dhsar[dh]; ! 446: bar = *sbar & ~addr->dhbar; ! 447: unit = dh * 16; ttybit = 1; ! 448: addr->un.dhcsr &= (short)~DH_TI; ! 449: for (; bar; unit++, ttybit <<= 1) { ! 450: if (bar & ttybit) { ! 451: *sbar &= ~ttybit; ! 452: bar &= ~ttybit; ! 453: tp = &dh11[unit]; ! 454: tp->t_state &= ~TS_BUSY; ! 455: if (tp->t_state&TS_FLUSH) ! 456: tp->t_state &= ~TS_FLUSH; ! 457: else { ! 458: addr->un.dhcsrl = (unit&017)|DH_IE; ! 459: /* ! 460: * Do arithmetic in a short to make up ! 461: * for lost 16&17 bits. ! 462: */ ! 463: cntr = addr->dhcar - ! 464: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); ! 465: ndflush(&tp->t_outq, (int)cntr); ! 466: } ! 467: if (tp->t_line) ! 468: (*linesw[tp->t_line].l_start)(tp); ! 469: else ! 470: dhstart(tp); ! 471: } ! 472: } ! 473: } ! 474: ! 475: /* ! 476: * Start (restart) transmission on the given DH11 line. ! 477: */ ! 478: dhstart(tp) ! 479: register struct tty *tp; ! 480: { ! 481: register struct dhdevice *addr; ! 482: register int car, dh, unit, nch; ! 483: int s; ! 484: ! 485: unit = minor(tp->t_dev); ! 486: dh = unit >> 4; ! 487: unit &= 0xf; ! 488: addr = (struct dhdevice *)tp->t_addr; ! 489: ! 490: /* ! 491: * Must hold interrupts in following code to prevent ! 492: * state of the tp from changing. ! 493: */ ! 494: s = spl5(); ! 495: /* ! 496: * If it's currently active, or delaying, no need to do anything. ! 497: */ ! 498: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 499: goto out; ! 500: /* ! 501: * If there are sleepers, and output has drained below low ! 502: * water mark, wake up the sleepers. ! 503: */ ! 504: if (tp->t_outq.c_cc<=TTLOWAT(tp)) { ! 505: if (tp->t_state&TS_ASLEEP) { ! 506: tp->t_state &= ~TS_ASLEEP; ! 507: wakeup((caddr_t)&tp->t_outq); ! 508: } ! 509: if (tp->t_wsel) { ! 510: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 511: tp->t_wsel = 0; ! 512: tp->t_state &= ~TS_WCOLL; ! 513: } ! 514: } ! 515: /* ! 516: * Now restart transmission unless the output queue is ! 517: * empty. ! 518: */ ! 519: if (tp->t_outq.c_cc == 0) ! 520: goto out; ! 521: if (tp->t_flags & (RAW|LITOUT)) ! 522: nch = ndqb(&tp->t_outq, 0); ! 523: else { ! 524: nch = ndqb(&tp->t_outq, 0200); ! 525: /* ! 526: * If first thing on queue is a delay process it. ! 527: */ ! 528: if (nch == 0) { ! 529: nch = getc(&tp->t_outq); ! 530: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); ! 531: tp->t_state |= TS_TIMEOUT; ! 532: goto out; ! 533: } ! 534: } ! 535: /* ! 536: * If characters to transmit, restart transmission. ! 537: */ ! 538: if (nch) { ! 539: car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum); ! 540: addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE; ! 541: /* ! 542: * The following nonsense with short word ! 543: * is to make sure the dhbar |= word below ! 544: * is done with an interlocking bisw2 instruction. ! 545: */ ! 546: { short word = 1 << unit; ! 547: dhsar[dh] |= word; ! 548: addr->dhcar = car; ! 549: addr->dhbcr = -nch; ! 550: addr->dhbar |= word; ! 551: } ! 552: tp->t_state |= TS_BUSY; ! 553: } ! 554: out: ! 555: splx(s); ! 556: } ! 557: ! 558: /* ! 559: * Stop output on a line, e.g. for ^S/^Q or output flush. ! 560: */ ! 561: /*ARGSUSED*/ ! 562: dhstop(tp, flag) ! 563: register struct tty *tp; ! 564: { ! 565: register struct dhdevice *addr; ! 566: register int unit, s; ! 567: ! 568: addr = (struct dhdevice *)tp->t_addr; ! 569: /* ! 570: * Block input/output interrupts while messing with state. ! 571: */ ! 572: s = spl5(); ! 573: if (tp->t_state & TS_BUSY) { ! 574: /* ! 575: * Device is transmitting; stop output ! 576: * by selecting the line and setting the byte ! 577: * count to -1. We will clean up later ! 578: * by examining the address where the dh stopped. ! 579: */ ! 580: unit = minor(tp->t_dev); ! 581: addr->un.dhcsrl = (unit&017) | DH_IE; ! 582: if ((tp->t_state&TS_TTSTOP)==0) ! 583: tp->t_state |= TS_FLUSH; ! 584: addr->dhbcr = -1; ! 585: } ! 586: splx(s); ! 587: } ! 588: ! 589: /* ! 590: * Reset state of driver if UBA reset was necessary. ! 591: * Reset the csrl and lpr registers on open lines, and ! 592: * restart transmitters. ! 593: */ ! 594: dhreset(uban) ! 595: int uban; ! 596: { ! 597: register int dh, unit; ! 598: register struct tty *tp; ! 599: register struct uba_device *ui; ! 600: int i; ! 601: ! 602: dh = 0; ! 603: for (dh = 0; dh < NDH; dh++) { ! 604: ui = dhinfo[dh]; ! 605: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) ! 606: continue; ! 607: printf(" dh%d", dh); ! 608: if (dh_ubinfo[uban]) { ! 609: dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, ! 610: nclist*sizeof (struct cblock), 0); ! 611: cbase[uban] = UBAI_ADDR(dh_ubinfo[uban]); ! 612: } ! 613: ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE; ! 614: ((struct dhdevice *)ui->ui_addr)->dhsilo = 0; ! 615: unit = dh * 16; ! 616: for (i = 0; i < 16; i++) { ! 617: tp = &dh11[unit]; ! 618: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { ! 619: dhparam(unit); ! 620: dmctl(unit, DML_ON, DMSET); ! 621: tp->t_state &= ~TS_BUSY; ! 622: dhstart(tp); ! 623: } ! 624: unit++; ! 625: } ! 626: } ! 627: dhsilos = 0; ! 628: } ! 629: ! 630: int dhtransitions, dhslowtimers, dhfasttimers; /*DEBUG*/ ! 631: /* ! 632: * At software clock interrupt time, check status. ! 633: * Empty all the dh silos that are in use, and decide whether ! 634: * to turn any silos off or on. ! 635: */ ! 636: dhtimer() ! 637: { ! 638: register int dh, s; ! 639: static int timercalls; ! 640: ! 641: if (dhsilos) { ! 642: dhfasttimers++; /*DEBUG*/ ! 643: timercalls++; ! 644: s = spl5(); ! 645: for (dh = 0; dh < NDH; dh++) ! 646: if (dhsilos & (1 << dh)) ! 647: dhrint(dh); ! 648: splx(s); ! 649: } ! 650: if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) { ! 651: dhslowtimers++; /*DEBUG*/ ! 652: timercalls = 0; ! 653: for (dh = 0; dh < NDH; dh++) { ! 654: ave(dhrate[dh], dhchars[dh], 8); ! 655: if ((dhchars[dh] > dhhighrate) && ! 656: ((dhsilos & (1 << dh)) == 0)) { ! 657: ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = ! 658: (dhchars[dh] > 500? 32 : 16); ! 659: dhsilos |= (1 << dh); ! 660: dhtransitions++; /*DEBUG*/ ! 661: } else if ((dhsilos & (1 << dh)) && ! 662: (dhrate[dh] < dhlowrate)) { ! 663: ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0; ! 664: dhsilos &= ~(1 << dh); ! 665: } ! 666: dhchars[dh] = 0; ! 667: } ! 668: } ! 669: timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz); ! 670: } ! 671: ! 672: /* ! 673: * Turn on the line associated with dh dev. ! 674: */ ! 675: dmopen(dev) ! 676: dev_t dev; ! 677: { ! 678: register struct tty *tp; ! 679: register struct dmdevice *addr; ! 680: register struct uba_device *ui; ! 681: register int unit; ! 682: register int dm; ! 683: int s; ! 684: ! 685: unit = minor(dev); ! 686: dm = unit >> 4; ! 687: tp = &dh11[unit]; ! 688: unit &= 0xf; ! 689: if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) { ! 690: tp->t_state |= TS_CARR_ON; ! 691: return; ! 692: } ! 693: addr = (struct dmdevice *)ui->ui_addr; ! 694: s = spl5(); ! 695: addr->dmcsr &= ~DM_SE; ! 696: while (addr->dmcsr & DM_BUSY) ! 697: ; ! 698: addr->dmcsr = unit; ! 699: addr->dmlstat = DML_ON; ! 700: if ((addr->dmlstat&DML_CAR) || (dhsoftCAR[dm]&(1<<unit))) ! 701: tp->t_state |= TS_CARR_ON; ! 702: addr->dmcsr = DM_IE|DM_SE; ! 703: while ((tp->t_state&TS_CARR_ON)==0) ! 704: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 705: splx(s); ! 706: } ! 707: ! 708: /* ! 709: * Dump control bits into the DM registers. ! 710: */ ! 711: dmctl(dev, bits, how) ! 712: dev_t dev; ! 713: int bits, how; ! 714: { ! 715: register struct uba_device *ui; ! 716: register struct dmdevice *addr; ! 717: register int unit, s; ! 718: int dm; ! 719: ! 720: unit = minor(dev); ! 721: dm = unit >> 4; ! 722: if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0) ! 723: return; ! 724: addr = (struct dmdevice *)ui->ui_addr; ! 725: s = spl5(); ! 726: addr->dmcsr &= ~DM_SE; ! 727: while (addr->dmcsr & DM_BUSY) ! 728: ; ! 729: addr->dmcsr = unit & 0xf; ! 730: switch(how) { ! 731: case DMSET: ! 732: addr->dmlstat = bits; ! 733: break; ! 734: case DMBIS: ! 735: addr->dmlstat |= bits; ! 736: break; ! 737: case DMBIC: ! 738: addr->dmlstat &= ~bits; ! 739: break; ! 740: } ! 741: addr->dmcsr = DM_IE|DM_SE; ! 742: splx(s); ! 743: } ! 744: ! 745: /* ! 746: * DM11 interrupt; deal with carrier transitions. ! 747: */ ! 748: dmintr(dm) ! 749: register int dm; ! 750: { ! 751: register struct uba_device *ui; ! 752: register struct tty *tp; ! 753: register struct dmdevice *addr; ! 754: int unit; ! 755: ! 756: ui = dminfo[dm]; ! 757: if (ui == 0) ! 758: return; ! 759: addr = (struct dmdevice *)ui->ui_addr; ! 760: if (addr->dmcsr&DM_DONE) { ! 761: if (addr->dmcsr&DM_CF) { ! 762: unit = addr->dmcsr & 0xf; ! 763: tp = &dh11[(dm << 4) + unit]; ! 764: if (addr->dmlstat & DML_CAR) ! 765: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 766: else if ((dhsoftCAR[dm] & (1<<unit)) == 0 && ! 767: (*linesw[tp->t_line].l_modem)(tp, 0) == 0) ! 768: addr->dmlstat = 0; ! 769: } ! 770: addr->dmcsr = DM_IE|DM_SE; ! 771: } ! 772: } ! 773: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.