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