Annotation of researchv9/sys/sundev/zs.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.