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