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