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