|
|
1.1 ! root 1: /* ! 2: * ZS driver ! 3: */ ! 4: #include "zs.h" ! 5: #define TRC(c) ! 6: ! 7: #include "../h/param.h" ! 8: #include "../h/stream.h" ! 9: #include "../h/ttyio.h" ! 10: #include "../h/ttyld.h" ! 11: #include "../machine/pte.h" ! 12: #include "../h/map.h" ! 13: #include "../h/buf.h" ! 14: #include "../h/systm.h" ! 15: #include "../h/conf.h" ! 16: ! 17: #include "../sundev/mbvar.h" ! 18: #include "../sundev/zsreg.h" ! 19: #include "../sundev/zscom.h" ! 20: #include "../sundev/zsvar.h" ! 21: ! 22: #define ZSWR1_INIT (ZSWR1_SIE|ZSWR1_TIE|ZSWR1_RIE) ! 23: #define ZS_ON (ZSWR5_DTR|ZSWR5_RTS) ! 24: #define ZS_OFF 0 ! 25: ! 26: #define NZSLINE (NZS*2) ! 27: #define SSPEED B9600 /* std speed = 9600 baud */ ! 28: ! 29: #define EXISTS 01 ! 30: #define ISOPEN 02 ! 31: #define WOPEN 04 ! 32: #define TIMEOUT 010 ! 33: #define CARR_ON 020 ! 34: #define ZSSTOP 040 ! 35: #define HPCL 0100 ! 36: #define BRKING 0200 ! 37: #define DIALOUT 0400 /* set when used as dialout with smart modems */ ! 38: ! 39: #define ZSPRI 30 ! 40: ! 41: /* ! 42: * Modem control commands. ! 43: */ ! 44: #define DMSET 0 ! 45: #define DMBIS 1 ! 46: #define DMBIC 2 ! 47: #define DMGET 3 ! 48: ! 49: /* ! 50: * One structure per line. ! 51: * Includes communication between H/W level 6 interrupts ! 52: * and software interrupts ! 53: */ ! 54: #define ZSIBUFSZ 256 ! 55: struct zsaline { ! 56: /* from v9 dz.c */ ! 57: short state; ! 58: short flags; ! 59: struct block *oblock; ! 60: struct queue *rdq; ! 61: char speed; ! 62: /* from SUN zsasync.c */ ! 63: short za_needsoft; /* need for software interrupt */ ! 64: short za_break; /* break occurred */ ! 65: short za_overrun; /* overrun (either hw or sw) */ ! 66: short za_ext; /* modem status change */ ! 67: short za_work; /* work to do */ ! 68: u_char za_rr0; /* for break detection */ ! 69: u_char za_ibuf[ZSIBUFSZ]; /* circular input buffer */ ! 70: short za_iptr; /* producing ptr for input */ ! 71: short za_sptr; /* consuming ptr for input */ ! 72: /* additions */ ! 73: dev_t za_dev; ! 74: struct zscom *za_addr; ! 75: } zsaline[NZSLINE]; ! 76: ! 77: extern int zssoftflags[NZSLINE]; ! 78: ! 79: int zsopen(), zsclose(), zsoput(), nodev(); ! 80: ! 81: static struct qinit zsrinit = { nodev, NULL, zsopen, zsclose, 0, 0 }; ! 82: struct qinit zswinit = { zsoput, NULL, zsopen, zsclose, 200, 100 }; ! 83: struct streamtab zsinfo = { &zsrinit, &zswinit }; ! 84: ! 85: ! 86: #define PCLK (19660800/4) /* basic clock rate for UARTs */ ! 87: #define ZSPEED(n) ZSTimeConst(PCLK, n) ! 88: #define NSPEED 16 /* max # of speeds */ ! 89: u_short zs_speeds[NSPEED] = { ! 90: 0, ! 91: ZSPEED(50), ! 92: ZSPEED(75), ! 93: ZSPEED(110), ! 94: #ifdef lint ! 95: ZSPEED(134), ! 96: #else ! 97: ZSPEED(134.5), ! 98: #endif ! 99: ZSPEED(150), ! 100: ZSPEED(200), ! 101: ZSPEED(300), ! 102: ZSPEED(600), ! 103: ZSPEED(1200), ! 104: ZSPEED(1800), ! 105: ZSPEED(2400), ! 106: ZSPEED(4800), ! 107: ZSPEED(9600), ! 108: ZSPEED(19200), ! 109: ZSPEED(38400), ! 110: }; ! 111: ! 112: int zsticks = 3; /* polling frequency */ ! 113: ! 114: /* ! 115: * The async zs protocol ! 116: */ ! 117: int zsa_attach(), zsa_txint(), zsa_xsint(), zsa_rxint(), zsa_srint(), ! 118: zsa_softint(); ! 119: ! 120: struct zsops zsops_async = { ! 121: zsa_attach, ! 122: zsa_txint, ! 123: zsa_xsint, ! 124: zsa_rxint, ! 125: zsa_srint, ! 126: zsa_softint, ! 127: }; ! 128: ! 129: zsa_attach(zs) ! 130: register struct zscom *zs; ! 131: { ! 132: register struct zsaline *za = &zsaline[zs->zs_unit]; ! 133: ! 134: za->za_addr = zs; ! 135: za->za_dev = zs->zs_unit; ! 136: za->state = EXISTS; ! 137: } ! 138: ! 139: /* ! 140: * Get the current speed of the console and turn it into something ! 141: * UNIX knows about - used to preserve console speed when UNIX comes up ! 142: */ ! 143: zsgetspeed(dev) ! 144: dev_t dev; ! 145: { ! 146: struct zscom *zs; ! 147: register struct zsaline *za; ! 148: int uspeed, zspeed; ! 149: ! 150: dev = minor(dev); ! 151: if (dev >= NZSLINE) ! 152: return(SSPEED); ! 153: za = &zsaline[dev]; ! 154: zs = za->za_addr; ! 155: zspeed = ZREAD(12); ! 156: zspeed |= ZREAD(13) << 8; ! 157: for (uspeed = 0; uspeed < NSPEED; uspeed++) ! 158: if (zs_speeds[uspeed] == zspeed) ! 159: return (uspeed); ! 160: return (SSPEED); ! 161: } ! 162: ! 163: /*ARGSUSED*/ ! 164: zsopen(q, d, flag) ! 165: register struct queue *q; ! 166: { ! 167: register dev; ! 168: register struct zsaline *za; ! 169: struct zscom *zs; ! 170: int s; ! 171: static int first = 1; ! 172: int zspoll(); ! 173: ! 174: if (q->ptr) /* already attached */ ! 175: return(1); ! 176: dev = minor(d); ! 177: za = &zsaline[dev]; ! 178: if (dev >= NZSLINE || (za->state&EXISTS)==0) ! 179: return(0); ! 180: zs = za->za_addr; ! 181: q->ptr = (caddr_t)za; ! 182: WR(q)->ptr = (caddr_t)za; ! 183: s = splzs(); ! 184: zs->zs_priv = (caddr_t)za; ! 185: zsopinit(zs, &zsops_async); ! 186: (void) splx(s); ! 187: if (first) { ! 188: first = 0; ! 189: timeout(zspoll, (caddr_t)0, zsticks); ! 190: } ! 191: if ((za->state&ISOPEN)==0 || (za->state&CARR_ON)==0) { ! 192: register s = spl5(); ! 193: /* clear any stale input */ ! 194: za->za_iptr = 0; ! 195: za->za_sptr = 0; ! 196: za->za_overrun = 0; ! 197: zsmctl(zs, ZS_ON, DMSET); ! 198: for (;;) { ! 199: za->flags = F8BIT|ODDP|EVENP; ! 200: if (zssoftflags[dev] & ZS_KBDMS) ! 201: za->speed = zsgetspeed(dev); ! 202: else ! 203: za->speed = SSPEED; ! 204: zsparam(za); ! 205: if (za->state & CARR_ON) ! 206: break; ! 207: /* ignore carrier? */ ! 208: if (zssoftflags[dev] & 1) { ! 209: za->state |= (DIALOUT | CARR_ON); ! 210: break; ! 211: } ! 212: if (tsleep((caddr_t)za, ZSPRI, 0) != TS_OK) { ! 213: wakeup((caddr_t)za); ! 214: za->speed = 0; ! 215: zsparam(za); ! 216: splx(s); ! 217: return(0); ! 218: } ! 219: } ! 220: za->rdq = q; ! 221: za->state |= ISOPEN; ! 222: /* ! 223: * The 0 channel of the keyboard UART controls ! 224: * the keyboard, so push the keyboard line ! 225: * discipline on it automatically. ! 226: */ ! 227: if ((zssoftflags[dev] & ZS_KBDMS) && !(dev & 1)) ! 228: pushkeyld(WR(q->next), d); ! 229: splx(s); ! 230: } ! 231: TRC('o'); ! 232: return(1); ! 233: } ! 234: ! 235: zsclose(q, d) ! 236: register struct queue *q; ! 237: { ! 238: register struct zsaline *za; ! 239: register s; ! 240: int s1; ! 241: ! 242: za = (struct zsaline *)q->ptr; ! 243: s = spl5(); ! 244: s1 = splzs(); ! 245: if (za->oblock) { ! 246: register struct block *bp = za->oblock; ! 247: za->oblock = NULL; ! 248: splx(s1); ! 249: freeb(bp); ! 250: } ! 251: flushq(WR(q), 1); ! 252: za->rdq = NULL; ! 253: if (za->state&HPCL || (za->state&CARR_ON)==0) { ! 254: za->speed = 0; ! 255: zsparam(za); ! 256: } ! 257: za->state &= EXISTS; ! 258: splx(s); ! 259: TRC('c'); ! 260: } ! 261: ! 262: /* ! 263: * ZS write put routine ! 264: */ ! 265: zsoput(q, bp) ! 266: register struct queue *q; ! 267: register struct block *bp; ! 268: { ! 269: register struct zsaline *za = (struct zsaline *)q->ptr; ! 270: register union stmsg *sp; ! 271: register s; ! 272: int s1; ! 273: int delaytime; ! 274: ! 275: TRC('p'); ! 276: switch(bp->type) { ! 277: ! 278: case M_IOCTL: ! 279: TRC('i'); ! 280: sp = (union stmsg *)bp->rptr; ! 281: switch (sp->ioc0.com) { ! 282: ! 283: case TIOCSDEV: ! 284: delaytime = 0; ! 285: if (za->speed != sp->ioc3.sb.ispeed) ! 286: delaytime = 20; ! 287: za->speed = sp->ioc3.sb.ispeed; ! 288: za->flags = sp->ioc3.sb.flags; ! 289: bp->type = M_IOCACK; ! 290: bp->wptr = bp->rptr; ! 291: qreply(q, bp); ! 292: qpctl1(q, M_DELAY, delaytime); /* wait a bit */ ! 293: qpctl(q, M_CTL); /* means do zsparam */ ! 294: zsstart(za); ! 295: return; ! 296: ! 297: case TIOCGDEV: ! 298: sp->ioc3.sb.ispeed = ! 299: sp->ioc3.sb.ospeed = za->speed; ! 300: sp->ioc3.sb.flags = za->flags; ! 301: bp->type = M_IOCACK; ! 302: qreply(q, bp); ! 303: return; ! 304: ! 305: case TIOCHPCL: ! 306: za->state |= HPCL; ! 307: bp->type = M_IOCACK; ! 308: bp->wptr = bp->rptr; ! 309: qreply(q, bp); ! 310: return; ! 311: ! 312: default: ! 313: bp->wptr = bp->rptr; ! 314: bp->type = M_IOCNAK; ! 315: qreply(q, bp); ! 316: return; ! 317: } ! 318: ! 319: case M_STOP: ! 320: s = spl5(); ! 321: za->state |= ZSSTOP; ! 322: freeb(bp); ! 323: s1 = splzs(); ! 324: if (bp = za->oblock) { ! 325: za->oblock = NULL; ! 326: splx(s1); ! 327: putbq(q, bp); ! 328: } ! 329: splx(s); ! 330: return; ! 331: ! 332: case M_START: ! 333: za->state &= ~ZSSTOP; ! 334: zsstart(za); ! 335: break; ! 336: ! 337: case M_FLUSH: ! 338: flushq(q, 1); ! 339: freeb(bp); ! 340: s = spl5(); ! 341: s1 = splzs(); ! 342: if (bp = za->oblock) { ! 343: za->oblock = NULL; ! 344: splx(s1); ! 345: freeb(bp); ! 346: } ! 347: splx(s); ! 348: return; ! 349: ! 350: case M_BREAK: ! 351: qpctl1(q, M_DELAY, 10); ! 352: putq(q, bp); ! 353: qpctl1(q, M_DELAY, 10); ! 354: zsstart(za); ! 355: return; ! 356: ! 357: case M_HANGUP: ! 358: za->state &= ~ZSSTOP; ! 359: case M_DELAY: ! 360: case M_DATA: ! 361: putq(q, bp); ! 362: TRC('d'); ! 363: zsstart(za); ! 364: return; ! 365: ! 366: default: /* not handled; just toss */ ! 367: break; ! 368: } ! 369: freeb(bp); ! 370: } ! 371: ! 372: /* ! 373: * set device parameters ! 374: */ ! 375: zsparam(za) ! 376: register struct zsaline *za; ! 377: { ! 378: register struct zscom *zs = za->za_addr; ! 379: register int wr1, wr3, wr4, wr5, speed; ! 380: int loops; ! 381: int s; ! 382: char c; ! 383: ! 384: if (za->speed == 0) { ! 385: (void) zsmctl(zs, ZS_OFF, DMSET); /* hang up line */ ! 386: return; ! 387: } ! 388: wr1 = ZSWR1_INIT; ! 389: wr3 = ZSWR3_RX_ENABLE; ! 390: wr4 = ZSWR4_X16_CLK; ! 391: wr5 = (zs->zs_wreg[5] & (ZSWR5_RTS|ZSWR5_DTR)) | ZSWR5_TX_ENABLE; ! 392: if (za->speed == B134) { /* what a joke! */ ! 393: wr1 |= ZSWR1_PARITY_SPECIAL; ! 394: wr3 |= ZSWR3_RX_6; ! 395: wr4 |= ZSWR4_PARITY_ENABLE | ZSWR4_PARITY_EVEN; ! 396: wr5 |= ZSWR5_TX_6; ! 397: } else if (za->flags&(F8BIT)) { ! 398: wr3 |= ZSWR3_RX_8; ! 399: wr5 |= ZSWR5_TX_8; ! 400: } else switch (za->flags & (EVENP|ODDP)) { ! 401: case 0: ! 402: wr3 |= ZSWR3_RX_8; ! 403: wr5 |= ZSWR5_TX_8; ! 404: break; ! 405: ! 406: case EVENP: ! 407: wr1 |= ZSWR1_PARITY_SPECIAL; ! 408: wr3 |= ZSWR3_RX_7; ! 409: wr4 |= ZSWR4_PARITY_ENABLE + ZSWR4_PARITY_EVEN; ! 410: wr5 |= ZSWR5_TX_7; ! 411: break; ! 412: ! 413: case ODDP: ! 414: wr1 |= ZSWR1_PARITY_SPECIAL; ! 415: wr3 |= ZSWR3_RX_7; ! 416: wr4 |= ZSWR4_PARITY_ENABLE; ! 417: wr5 |= ZSWR5_TX_7; ! 418: break; ! 419: ! 420: case EVENP|ODDP: ! 421: wr3 |= ZSWR3_RX_7; ! 422: wr4 |= ZSWR4_PARITY_ENABLE + ZSWR4_PARITY_EVEN; ! 423: wr5 |= ZSWR5_TX_7; ! 424: break; ! 425: } ! 426: if (za->speed == B110) ! 427: wr4 |= ZSWR4_2_STOP; ! 428: else if (za->speed == B134) ! 429: wr4 |= ZSWR4_1_5_STOP; ! 430: else ! 431: wr4 |= ZSWR4_1_STOP; ! 432: speed = zs->zs_wreg[12] + (zs->zs_wreg[13] << 8); ! 433: if (wr1 != zs->zs_wreg[1] || wr3 != zs->zs_wreg[3] || ! 434: wr4 != zs->zs_wreg[4] || wr5 != zs->zs_wreg[5] || ! 435: speed != zs_speeds[za->speed&017]) { ! 436: /* ! 437: * Wait for that last damn character to get out the ! 438: * door. At most 1000 loops of 100 usec each is worst ! 439: * case of 110 baud. If something appears on the output ! 440: * queue then somebody higher up isn't synchronized ! 441: * and we give up. ! 442: */ ! 443: s = splzs(); ! 444: loops = 1000; ! 445: while ((ZREAD(1) & ZSRR1_ALL_SENT) == 0 && --loops > 0) { ! 446: (void) splx(s); ! 447: DELAY(100); ! 448: s = splzs(); ! 449: } ! 450: ZWRITE(3, 0); /* disable receiver while setting parameters */ ! 451: zs->zs_addr->zscc_control = ZSWR0_RESET_STATUS; ! 452: zs->zs_addr->zscc_control = ZSWR0_RESET_ERRORS; ! 453: c = zs->zs_addr->zscc_data; /* swallow junk */ ! 454: c = zs->zs_addr->zscc_data; /* swallow junk */ ! 455: c = zs->zs_addr->zscc_data; /* swallow junk */ ! 456: ZWRITE(1, wr1); ! 457: ZWRITE(4, wr4); ! 458: ZWRITE(3, wr3); ! 459: ZWRITE(5, wr5); ! 460: speed = zs_speeds[za->speed&017]; ! 461: ZWRITE(11, ZSWR11_TXCLK_BAUD + ZSWR11_RXCLK_BAUD); ! 462: ZWRITE(14, ZSWR14_BAUD_FROM_PCLK); ! 463: ZWRITE(12, speed); ! 464: ZWRITE(13, speed >> 8); ! 465: ZWRITE(14, ZSWR14_BAUD_ENA + ZSWR14_BAUD_FROM_PCLK); ! 466: (void) splx(s); ! 467: } ! 468: } ! 469: ! 470: zstimo(za) ! 471: register struct zsaline *za; ! 472: { ! 473: register struct zscom *zs = za->za_addr; ! 474: int s; ! 475: ! 476: if (za->state&BRKING) { ! 477: s = splzs(); ! 478: ZBIC(5, ZSWR5_BREAK); ! 479: splx(s); ! 480: } ! 481: za->state &= ~(TIMEOUT|BRKING); ! 482: zsstart(za); ! 483: } ! 484: ! 485: zsstart(za) ! 486: register struct zsaline *za; ! 487: { ! 488: register struct zscom *zs = za->za_addr; ! 489: register s = spl5(); ! 490: register struct block *bp; ! 491: int s1; ! 492: ! 493: TRC('s'); ! 494: again: ! 495: if (za->state & (TIMEOUT|ZSSTOP|BRKING) || za->oblock) { ! 496: TRC('t'); ! 497: goto out; ! 498: } ! 499: if (za->rdq == NULL) ! 500: goto out; ! 501: if ((bp = getq(WR(za->rdq))) == NULL) { ! 502: TRC('n'); ! 503: goto out; ! 504: } ! 505: switch (bp->type) { ! 506: ! 507: case M_DATA: ! 508: za->oblock = bp; ! 509: if (zs->zs_addr->zscc_control & ZSRR0_TX_READY) ! 510: zs->zs_addr->zscc_data = *bp->rptr++; ! 511: break; ! 512: ! 513: case M_BREAK: ! 514: s1 = splzs(); ! 515: ZBIS(5, ZSWR5_BREAK); ! 516: splx(s1); ! 517: za->state |= BRKING|TIMEOUT; ! 518: timeout(zstimo, (caddr_t)za, 15); /* about 250 ms */ ! 519: freeb(bp); ! 520: break; ! 521: ! 522: case M_DELAY: ! 523: za->state |= TIMEOUT; ! 524: timeout(zstimo, (caddr_t)za, (int)*bp->rptr + 6); ! 525: freeb(bp); ! 526: break; ! 527: ! 528: case M_HANGUP: ! 529: za->speed = 0; ! 530: case M_CTL: ! 531: freeb(bp); ! 532: zsparam(za); ! 533: goto again; ! 534: ! 535: } ! 536: out: ! 537: splx(s); ! 538: } ! 539: ! 540: zsmctl(zs, bits, how) ! 541: register struct zscom *zs; ! 542: int bits, how; ! 543: { ! 544: register int mbits, s; ! 545: ! 546: s = splzs(); ! 547: mbits = zs->zs_wreg[5] & (ZSWR5_RTS|ZSWR5_DTR); ! 548: zs->zs_addr->zscc_control = ZSWR0_RESET_STATUS; ! 549: DELAY(2); ! 550: mbits |= zs->zs_addr->zscc_control & (ZSRR0_CD|ZSRR0_CTS); ! 551: switch (how) { ! 552: case DMSET: ! 553: mbits = bits; ! 554: break; ! 555: ! 556: case DMBIS: ! 557: mbits |= bits; ! 558: break; ! 559: ! 560: case DMBIC: ! 561: mbits &= ~bits; ! 562: break; ! 563: ! 564: case DMGET: ! 565: (void) splx(s); ! 566: return (mbits); ! 567: } ! 568: zs->zs_wreg[5] &= ~(ZSWR5_RTS|ZSWR5_DTR); ! 569: ZBIS(5, mbits & (ZSWR5_RTS|ZSWR5_DTR)); ! 570: (void) splx(s); ! 571: return (mbits); ! 572: } ! 573: ! 574: zsa_txint(zs) ! 575: register struct zscom *zs; ! 576: { ! 577: register struct zsaline *za = (struct zsaline *)zs->zs_priv; ! 578: register struct zscc_device *zsaddr = zs->zs_addr; ! 579: register struct block *bp; ! 580: ! 581: if ((bp = za->oblock) && bp->rptr < bp->wptr && ! 582: (zsaddr->zscc_control & ZSRR0_TX_READY)) { ! 583: zsaddr->zscc_data = *bp->rptr++; ! 584: } else { ! 585: za->za_work++; ! 586: zsaddr->zscc_control = ZSWR0_RESET_TXINT; ! 587: ZSSETSOFT(zs); ! 588: } ! 589: } ! 590: ! 591: zsa_xsint(zs) ! 592: register struct zscom *zs; ! 593: { ! 594: register struct zsaline *za = (struct zsaline *)zs->zs_priv; ! 595: register struct zscc_device *zsaddr = zs->zs_addr; ! 596: register u_char s0, x0, c; ! 597: ! 598: s0 = zsaddr->zscc_control; ! 599: x0 = s0 ^ za->za_rr0; ! 600: za->za_rr0 = s0; ! 601: zsaddr->zscc_control = ZSWR0_RESET_STATUS; ! 602: if ((x0 & ZSRR0_BREAK) && (s0 & ZSRR0_BREAK) == 0) { ! 603: za->za_break++; ! 604: c = zsaddr->zscc_data; /* swallow null */ ! 605: #ifdef lint ! 606: c = c; ! 607: #endif ! 608: zsaddr->zscc_control = ZSWR0_RESET_ERRORS; ! 609: /* ! 610: if (za->za_dev == kbddev) ! 611: montrap(*romp->v_abortent); ! 612: */ ! 613: } ! 614: za->za_work++; ! 615: za->za_ext++; ! 616: ZSSETSOFT(zs); ! 617: } ! 618: ! 619: zsa_rxint(zs) ! 620: register struct zscom *zs; ! 621: { ! 622: register struct zsaline *za = (struct zsaline *)zs->zs_priv; ! 623: register struct zscc_device *zsaddr = zs->zs_addr; ! 624: register u_char c; ! 625: ! 626: c = zsaddr->zscc_data; ! 627: if (c == 0 && (za->za_rr0 & ZSRR0_BREAK)) ! 628: return; ! 629: za->za_ibuf[za->za_iptr++] = c; ! 630: if (za->za_iptr >= ZSIBUFSZ) ! 631: za->za_iptr = 0; ! 632: if (za->za_iptr == za->za_sptr) ! 633: za->za_overrun++; ! 634: za->za_work++; ! 635: if (++za->za_needsoft > 20) { ! 636: za->za_needsoft = 0; ! 637: ZSSETSOFT(zs); ! 638: } ! 639: } ! 640: ! 641: zsa_srint(zs) ! 642: register struct zscom *zs; ! 643: { ! 644: register struct zsaline *za = (struct zsaline *)zs->zs_priv; ! 645: register struct zscc_device *zsaddr = zs->zs_addr; ! 646: register short s1; ! 647: register u_char c; ! 648: ! 649: s1 = ZREAD(1); ! 650: c = zsaddr->zscc_data; /* swallow bad char */ ! 651: #ifdef lint ! 652: c = c; ! 653: #endif ! 654: zsaddr->zscc_control = ZSWR0_RESET_ERRORS; ! 655: if (s1 & ZSRR1_DO) { ! 656: za->za_overrun++; ! 657: za->za_work++; ! 658: ZSSETSOFT(zs); ! 659: } ! 660: } ! 661: /* ! 662: * Handle a software interrupt ! 663: */ ! 664: zsa_softint(zs) ! 665: register struct zscom *zs; ! 666: { ! 667: register struct zsaline *za = (struct zsaline *)zs->zs_priv; ! 668: ! 669: if (zsa_process(za)) /* true if too much work at once */ ! 670: zspoll(1); ! 671: return (0); ! 672: } ! 673: ! 674: /* ! 675: * Poll for events in the zscom structures ! 676: * This routine is called at level 1, we jack up to 3 to lock ! 677: * out zsa_softint. ! 678: */ ! 679: zspoll(direct) ! 680: { ! 681: register struct zsaline *za; ! 682: register short more; ! 683: register int s; ! 684: ! 685: do { ! 686: more = 0; ! 687: for (za = &zsaline[0]; za < &zsaline[NZSLINE]; za++) ! 688: if (za->za_work) { ! 689: za->za_work = 0; ! 690: s = spl3(); ! 691: if (zsa_process(za)) { ! 692: za->za_work++; ! 693: more++; ! 694: } ! 695: (void) splx(s); ! 696: } ! 697: } while (more); ! 698: if (!direct) ! 699: timeout(zspoll, (caddr_t)0, zsticks); ! 700: } ! 701: ! 702: /* ! 703: * Process software interrupts (or poll) ! 704: * Crucial points: ! 705: * 1. Inner loop gives equal priority to input and output so that ! 706: * in TANDEM mode the stop character has a chance of being sent ! 707: * before enough input arrives to exceed TTYHOG. This has happened ! 708: * in very busy systems. ! 709: * 2. The inner loop is executed at most 20 times before the next line ! 710: * is serviced -- this "schedules" more fairly among lines. ! 711: * 3. BUG - breaks are handled "out-of-band" - their relative position ! 712: * among input events is lost, as well as multiple breaks together. ! 713: * This is probably not a problem in practice. ! 714: */ ! 715: zsa_process(za) ! 716: register struct zsaline *za; ! 717: { ! 718: register struct zscc_device *zsaddr = za->za_addr->zs_addr; ! 719: register struct block *bp; ! 720: register short i; ! 721: register u_char c; ! 722: ! 723: if (za->za_ext) { ! 724: za->za_ext = 0; ! 725: /* carrier up? */ ! 726: if (zsaddr->zscc_control & ZSRR0_CD) { ! 727: /* carrier present */ ! 728: if ((za->state & CARR_ON)==0) ! 729: wakeup((caddr_t)za); ! 730: za->state |= CARR_ON; ! 731: } else if ((za->state & CARR_ON) && !(za->state & DIALOUT)) { ! 732: /* carrier lost */ ! 733: if (za->state & ISOPEN) { ! 734: (void) zsmctl(za->za_addr, ZSWR5_DTR, DMBIC); ! 735: if (za->rdq) ! 736: putctl(za->rdq->next,M_HANGUP); ! 737: } ! 738: za->state &= ~CARR_ON; ! 739: } ! 740: } ! 741: if (za->za_overrun) { ! 742: za->za_overrun = 0; ! 743: za->za_iptr = 0; ! 744: za->za_sptr = 0; ! 745: if (za->state & ISOPEN) ! 746: printf("zs%d: silo overflow\n", minor(za->za_dev)); ! 747: } ! 748: if (za->za_break && (zsaddr->zscc_control & ZSRR0_BREAK) == 0) { ! 749: za->za_break = 0; ! 750: if (za->rdq != NULL && !(za->rdq->next->flag&QFULL) && ! 751: (bp = allocb(16)) != NULL) { ! 752: bp->type = M_BREAK; ! 753: (*za->rdq->next->qinfo->putp)(za->rdq->next, bp); ! 754: } ! 755: } ! 756: /* need to handle I & O in same loop to make TANDEM mode work */ ! 757: i = 0; ! 758: do { ! 759: if (za->za_sptr != za->za_iptr) { ! 760: c = za->za_ibuf[za->za_sptr++]; ! 761: if (za->za_sptr >= ZSIBUFSZ) ! 762: za->za_sptr = 0; ! 763: if (za->rdq != NULL && !(za->rdq->next->flag&QFULL) && ! 764: (bp = allocb(16)) != NULL) { ! 765: *bp->wptr++ = c; ! 766: (*za->rdq->next->qinfo->putp)(za->rdq->next, bp); ! 767: } ! 768: } ! 769: if ((bp = za->oblock) && bp->rptr >= bp->wptr) { ! 770: freeb(bp); ! 771: za->oblock = NULL; ! 772: zsstart(za); ! 773: } ! 774: } while (za->za_sptr != za->za_iptr && ++i < 20); ! 775: return (i >= 20); ! 776: } ! 777: ! 778: /* ! 779: * push the keyboard line discipline on the line ! 780: * function equivalent of FIOPUSHLD, but occurs automatically on open ! 781: */ ! 782: #include "kbd.h" ! 783: #if NKBD > 0 ! 784: extern struct streamtab kbdinfo; ! 785: #else ! 786: # define kbdinfo *(struct streamtab *)NULL ! 787: #endif ! 788: ! 789: pushkeyld(q, d) ! 790: register struct queue *q; ! 791: { ! 792: if (&kbdinfo == (struct streamtab *)NULL) ! 793: return; ! 794: if (qattach(&kbdinfo, RD(q), d)) { ! 795: long nip = ! 796: (*q->next->qinfo->qopen)(RD(q->next), d); ! 797: if (nip ==0) ! 798: qdetach(RD(q->next), 0); ! 799: } ! 800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.