Annotation of researchv10dc/sys/io/debna.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * first cut at NI port in DEBNA
                      3:  * slower than it need be, because of all the copying;
                      4:  * disallows use of the storage port
                      5:  */
                      6: #include "sys/param.h"
                      7: #include "sys/biaddr.h"
                      8: #include "sys/conf.h"
                      9: #include "sys/user.h"
                     10: #include "sys/buf.h"
                     11: #include "sys/stream.h"
                     12: #include "sys/biic.h"
                     13: #include "sys/ethernet.h"
                     14: #include "sys/enio.h"
                     15: #include "sys/pte.h"
                     16: #include "sys/bvp.h"
                     17: #include "sys/debna.h"
                     18: 
                     19: caddr_t remqhi();
                     20: 
                     21: 
                     22: #define        PCMDQ   0       /* just one command queue */
                     23: #define        PFREQ   0       /* just one free queue for now */
                     24: 
                     25: /*
                     26:  * internal ideas about packets
                     27:  */
                     28: 
                     29: /*
                     30:  * bounds of an Ethernet packet
                     31:  * min is probably uninteresting
                     32:  * max is constrained by the port, which will fuss and shut down
                     33:  * if handed a buffer bigger than ETHERMAXTU+ETHERCKSUM
                     34:  */
                     35: #define        ETHERMINTU      60
                     36: #define        ETHERMAXTU      1514
                     37: #define        ETHERCKSUM      4
                     38: 
                     39: #define        NIRCVBUF        (ETHERMAXTU+ETHERCKSUM)
                     40: 
                     41: struct dgi {
                     42:        struct bvpdg h;         /* header */
                     43:        char d[NIRCVBUF];
                     44: };
                     45: 
                     46: struct mst {
                     47:        struct bvpmsg h;
                     48:        struct stptdb p;
                     49: };
                     50: 
                     51: /*
                     52:  * config stuff
                     53:  */
                     54: extern struct bnactl bna[];
                     55: extern struct bnabuf bnabuf[];
                     56: extern struct biaddr bnaaddr[];
                     57: extern int bnacnt;
                     58: 
                     59: long bnaopen();
                     60: int bnaclose(), bnaput();
                     61: 
                     62: static struct qinit bnarinit = { noput, NULL, bnaopen, bnaclose, 0, 0 };
                     63: static struct qinit bnawinit = { bnaput, NULL, bnaopen, bnaclose, 4*ETHERMAXTU, 64 };
                     64: static struct streamtab bnasinfo = { &bnarinit, &bnawinit };
                     65: struct cdevsw bnacdev = cstrinit(&bnasinfo);
                     66: 
                     67: long
                     68: bnaopen(q, dev)
                     69: register struct queue *q;
                     70: dev_t dev;
                     71: {
                     72:        register int unit, chan;
                     73:        register struct bnachan *bc;
                     74: 
                     75:        unit = minor(dev);
                     76:        chan = unit % BNACHAN;
                     77:        unit /= BNACHAN;
                     78:        if (unit >= bnacnt)
                     79:                return (0);
                     80:        if (bnainit(unit) == 0)
                     81:                return (0);
                     82:        bc = &bna[unit].chan[chan];
                     83:        if (bc->rq)
                     84:                return (0);
                     85:        bc->unit = unit;
                     86:        bc->proto = 0;
                     87:        q->ptr = (caddr_t)bc;
                     88:        q->flag |= QDELIM;
                     89:        WR(q)->ptr = (caddr_t)bc;
                     90:        WR(q)->flag |= QDELIM|QBIGB;
                     91:        bc->rq = q;
                     92:        return (1);
                     93: }
                     94: 
                     95: /*
                     96:  * init the bvp port registers and pqb
                     97:  * set up our list of free transmit buffers,
                     98:  * and the free queue for the port
                     99:  * -- only one free queue for now
                    100:  */
                    101: bnainit(unit)
                    102: register int unit;
                    103: {
                    104:        register char *cp;
                    105:        register struct bnactl *bn;
                    106:        register int i;
                    107: 
                    108:        bn = &bna[unit];
                    109:        if (bvpinit(&bn->bvp, &bnaaddr[unit], NIREGS) == 0) {
                    110:                printf("debna %d: can't init\n", unit);
                    111:                return (0);
                    112:        }
                    113:        if (bn->bvp.d->f[PFREQ].f_size == 0) {  /* somewhat sleazy init flag */
                    114:                bn->bvp.d->f[PFREQ].f_size = BNABSIZE-BVPHSIZE;
                    115:                cp = bnabuf[unit].rbuf;
                    116:                cp = (char *)(((int)cp + 7) & ~07);     /* quad-align */
                    117:                for (i = 0; i < BNARBUF; i++, cp += BNABSIZE) {
                    118:                        if (((int)cp&PGOFSET) > (((int)cp+sizeof(struct bvpdg))&PGOFSET))
                    119:                                cp = (char *)(((int)cp+PGOFSET)&~PGOFSET);
                    120:                        bnarbuf(bn, (struct dgi *)cp);
                    121:                }
                    122:                cp = bnabuf[unit].xbuf;
                    123:                cp = (char *)(((int)cp + 7) & ~07);     /* quad-align */
                    124:                for (i = 0; i < BNAXBUF; i++, cp += BNABSIZE) {
                    125:                        if (((int)cp&PGOFSET) > (((int)cp+sizeof(struct bvpdg))&PGOFSET))
                    126:                                cp = (char *)(((int)cp+PGOFSET)&~PGOFSET);
                    127:                        bnaxbuf(bn, (struct dgi *)cp);
                    128:                }
                    129:        }
                    130:        bcopy(bn->bvp.r->addr, bn->myaddr, sizeof(bn->myaddr));
                    131:        return (1);
                    132: }
                    133: 
                    134: bnaclose(q)
                    135: register struct queue *q;
                    136: {
                    137:        register struct bnachan *bc;
                    138: 
                    139:        bc = (struct bnachan *)q->ptr;
                    140:        /* turn off PTDB? */
                    141:        bc->rq = NULL;
                    142:        bc->proto = 0;
                    143: }
                    144: 
                    145: /*
                    146:  * output put
                    147:  */
                    148: bnaput(q, bp)
                    149: register struct queue *q;
                    150: register struct block *bp;
                    151: {
                    152:        register struct bnachan *bc;
                    153:        register int s;
                    154: 
                    155:        bc = (struct bnachan *)q->ptr;
                    156:        switch (bp->type) {
                    157:        case M_IOCTL:
                    158:                bnaioctl(q, bp);
                    159:                return;
                    160: 
                    161:        case M_DATA:
                    162:                putq(q, bp);
                    163:                if (bp->class & S_DELIM)
                    164:                        break;
                    165:                return;
                    166: 
                    167:        default:
                    168:                freeb(bp);
                    169:                return;
                    170:        }
                    171:        /*
                    172:         * at least a whole packet on the queue
                    173:         */
                    174:        bc->dcnt++;
                    175:        s = spl6();
                    176:        while (bnasend(bc->unit))
                    177:                ;
                    178:        splx(s);
                    179: }
                    180: 
                    181: bnaioctl(q, bp)
                    182: register struct queue *q;
                    183: register struct block *bp;
                    184: {
                    185:        register struct bnachan *bc;
                    186:        register struct bnactl *bn;
                    187: 
                    188:        bc = (struct bnachan *)q->ptr;
                    189:        bn = &bna[bc->unit];
                    190:        bp->type = M_IOCACK;
                    191:        switch (stiocom(bp)) {
                    192:        case ENIOTYPE:          /* set proto */
                    193:                bc->proto = *((int *)stiodata(bp));
                    194:                bnastptdb(bn, bc);
                    195:                freeb(bp);      /* IOCACK when the port finishes */
                    196:                return;
                    197: 
                    198:        case ENIOADDR:
                    199:                bcopy(bn->myaddr, stiodata(bp), sizeof(bn->myaddr));
                    200:                bp->wptr = bp->rptr + sizeof(bn->myaddr) + STIOCHDR;
                    201:                break;
                    202: 
                    203:        default:
                    204:                bp->type = M_IOCNAK;
                    205:                break;
                    206:        }
                    207:        qreply(q, bp);
                    208: }
                    209: 
                    210: bnastptdb(bn, bc)
                    211: register struct bnactl *bn;
                    212: register struct bnachan *bc;
                    213: {
                    214:        register struct mst *dp;
                    215:        register int s;
                    216: 
                    217:        s = spl6();
                    218:        if ((dp = (struct mst *)bn->xfree) == NULL) {
                    219:                bc->needst = 1;
                    220:                bn->needst = 1;
                    221:                splx(s);
                    222:                return;
                    223:        }
                    224:        bn->xfree = (struct dgi *)(dp->h.q.head);
                    225:        bc->needst = 0;
                    226:        splx(s);
                    227:        bzero((caddr_t)dp, sizeof(*dp));
                    228:        dp->h.bd_opc = BVPSNDMSG;
                    229:        dp->h.bd_flag = BVPRSP;
                    230:        dp->h.bm_len = sizeof(*dp) - ((char *)&dp->h.bm_opc - (char *)dp);
                    231:        dp->h.bm_opc = NISTPTDB;
                    232:        dp->p.pt_proto = bc->proto;
                    233:        dp->p.pt_fqi = PFREQ;
                    234:        dp->p.pt_flag = PTABM|PTAAM;
                    235:        dp->p.pt_id = bc - bn->chan;
                    236:        if (insqti((caddr_t)dp, &bn->bvp.d->p.p_cmdq[PCMDQ]))
                    237:                bvpcomm(bn->bvp.r, PCOWN|PCCMDQ|(PCMDQ<<PCDS));
                    238: }
                    239: 
                    240: /*
                    241:  * here on an interrupt
                    242:  */
                    243: bna0int(unit)
                    244: int unit;
                    245: {
                    246:        register struct bvpdata *b;
                    247:        register struct bnactl *bn;
                    248:        register struct dgi *dp;
                    249:        register struct bnabuf *bf;     /* just for safety check */
                    250:        register int i;
                    251: 
                    252:        if ((unsigned)unit >= bnacnt)
                    253:                panic("bna0int");
                    254:        bn = &bna[unit];
                    255:        if (bn->bvp.r == NULL) {
                    256:                printf("debna %d stray intr\n", unit);
                    257:                return;
                    258:        }
                    259:        bn->bvp.rsave = *bn->bvp.r;     /* copy all, for debugging */
                    260:        if (bn->bvp.rsave.stat & PSOWN)
                    261:                bn->bvp.r->stat &=~ PSOWN;      /* allow fresh status */
                    262:        if ((bn->bvp.rsave.stat & PSSTAT) != SENAB) {
                    263:                printf("debna %d: ps %x pe %x pd %x\n", unit,
                    264:                        bn->bvp.rsave.stat, bn->bvp.rsave.err, bn->bvp.rsave.data);
                    265:                return;
                    266:        }
                    267:        b = bn->bvp.d;
                    268:        bf = &bnabuf[unit];
                    269:        while ((dp = (struct dgi *)remqhi(&b->p.p_rspq)) != NULL) {
                    270:                if (dp->h.bd_sts != BVPSUC)
                    271:                        printf("debna %d opc %x sts %x\n", unit, dp->h.bd_opc, dp->h.bd_sts);
                    272:                switch (dp->h.bd_opc) {
                    273:                case BVPSNDDGI:         /* datagram sent */
                    274:                        for (i = ETHERALEN-1; i >= 0; --i)
                    275:                                if (((struct etherpup *)dp->d)->dhost[i] != 0xff
                    276:                                &&  ((struct etherpup *)dp->d)->dhost[i] != bn->myaddr[i])
                    277:                                        goto notecho;
                    278:                        /*
                    279:                         * packet sent to ourselves;
                    280:                         * port won't echo it back
                    281:                         */
                    282:                        dp->h.bd_len += ETHERCKSUM;     /* banrdg will trim */
                    283:                        bcopy(bn->myaddr, ((struct etherpup *)dp->d)->shost, sizeof(bn->myaddr));
                    284:                        bnardg(bn, dp);
                    285: notecho:
                    286:                        /* fall through */
                    287:                case BVPSNDMSG:         /* message sent */
                    288:                        if ((char *)dp < bf->xbuf
                    289:                        ||  (char *)dp >= &bf->xbuf[sizeof(bf->xbuf)])
                    290:                                panic("bna0int sent");
                    291:                        bnaxbuf(bn, dp);
                    292:                        continue;
                    293: 
                    294:                case BVPRCVDGI:         /* datagram received */
                    295:                        if ((char *)dp < bf->rbuf
                    296:                        ||  (char *)dp >= &bf->rbuf[sizeof(bf->rbuf)])
                    297:                                panic("bna0int rcv dg");
                    298:                        bnardg(bn, dp);
                    299:                        bnarbuf(bn, dp);
                    300:                        continue;
                    301: 
                    302:                case BVPRCVMSG:         /* message received */
                    303:                        if ((char *)dp < bf->rbuf
                    304:                        ||  (char *)dp >= &bf->rbuf[sizeof(bf->rbuf)])
                    305:                                panic("bna0int rcv msg");
                    306:                        bnarmsg(bn, (struct bvpmsg *)dp);
                    307:                        bnarbuf(bn, dp);
                    308:                        continue;
                    309: 
                    310:                default:
                    311:                        printf("debna %d: %x: opc %x\n", unit, dp, dp->h.bd_opc);
                    312:                        continue;       /* leaving buffer tied up */
                    313:                }
                    314:        }
                    315:        while (bnasend(unit))
                    316:                ;
                    317: }
                    318: 
                    319: /*
                    320:  * here is a received datagram;
                    321:  * find the right channel,
                    322:  * and send it up the queue
                    323:  */
                    324: bnardg(bn, dp)
                    325: register struct bnactl *bn;
                    326: register struct dgi *dp;
                    327: {
                    328:        register int n;
                    329:        register struct block *bp;
                    330:        register char *p;
                    331:        register struct queue *q;
                    332:        int len;
                    333:        short proto;
                    334: 
                    335:        if (dp->h.bd_dgsts != NISUC) {
                    336:                printf("debna %d dg sts %x\n", bn - bna, dp->h.bd_dgsts);
                    337:                return;
                    338:        }
                    339:        len = (dp->h.bd_len+BVPHSIZE)-sizeof(struct bvpdg)-ETHERCKSUM;
                    340:        proto = (short)((struct etherpup *)dp->d)->type;
                    341:        for (n = 0; n < BNACHAN; n++)
                    342:                if (bn->chan[n].proto == proto)
                    343:                        break;
                    344:        if (n >= BNACHAN)
                    345:                return;         /* unexpected proto */
                    346:        q = bn->chan[n].rq;
                    347:        if (q == NULL)
                    348:                return;         /* snh */
                    349:        if (q->next->flag & QFULL)
                    350:                return;         /* no room */
                    351:        p = dp->d;
                    352:        while (len > 0) {
                    353:                if ((bp = allocb(len)) == NULL)
                    354:                        return;         /* wrong, but hard */
                    355:                n = bp->lim - bp->wptr;
                    356:                if (len < n)
                    357:                        n = len;
                    358:                bcopy(p, bp->wptr, n);
                    359:                bp->wptr += n;
                    360:                p += n;
                    361:                len -= n;
                    362:                if (len <= 0)
                    363:                        bp->class |= S_DELIM;
                    364:                (*q->next->qinfo->putp)(q->next, bp);
                    365:        }
                    366: }
                    367: 
                    368: /*
                    369:  * here is a message
                    370:  */
                    371: 
                    372: bnarmsg(bn, dp)
                    373: register struct bnactl *bn;
                    374: register struct bvpmsg *dp;
                    375: {
                    376:        register struct bnachan *bc;
                    377:        register struct mst *sdp;
                    378: 
                    379:        switch (dp->bm_opc) {
                    380:        case NISTPTDB:  /* ptdb set, sent ioctl back */
                    381:                sdp = (struct mst *)dp;
                    382:                if (sdp->p.pt_id < 0 || sdp->p.pt_id >= BNACHAN)
                    383:                        panic("bnastptdb");
                    384:                bc = &bn->chan[sdp->p.pt_id];
                    385:                if (bc->rq == NULL || bc->proto != sdp->p.pt_proto)
                    386:                        return; /* early close? */
                    387:                if (sdp->h.bm_nists != NISUC)
                    388:                        printf("debna %d %d stptdb sts %x\n", bn - bna,
                    389:                                sdp->p.pt_id, sdp->h.bm_nists);
                    390:                putctl(bc->rq->next, M_IOCACK);
                    391:                return;
                    392: 
                    393:        default:
                    394:                printf("debna %d msg opc %x sts %x\n", dp->bm_opc, dp->bm_nists);
                    395:                return;
                    396:        }
                    397: }
                    398: 
                    399: /*
                    400:  * find a channel with a packet,
                    401:  * find a buffer,
                    402:  * and send
                    403:  */
                    404: bnasend(unit)
                    405: int unit;
                    406: {
                    407:        register struct bnactl *bn;
                    408:        register struct bnachan *bc;
                    409:        register struct dgi *dp;
                    410:        register char *p;
                    411:        register struct block *bp;
                    412:        register int n;
                    413:        char *ep;
                    414: 
                    415:        bn = &bna[unit];
                    416:        n = bn->lastx;
                    417:        while (bn->chan[n].dcnt == 0) {
                    418:                if (++n >= BNACHAN)
                    419:                        n = 0;
                    420:                if (n == bn->lastx)
                    421:                        return (0);             /* nothing to send */
                    422:        }
                    423:        bn->lastx = n;
                    424:        bc = &bn->chan[n];
                    425:        if ((dp = bn->xfree) == NULL)
                    426:                return (0);                     /* no buffer */
                    427:        bn->xfree = (struct dgi *)dp->h.q.head;
                    428:        bzero((caddr_t)&dp->h, sizeof(dp->h));
                    429:        p = dp->d;
                    430:        ep = p + sizeof(dp->d);
                    431:        while ((bp = getq(WR(bc->rq))) != NULL) {
                    432:                n = bp->wptr - bp->rptr;
                    433:                if (p + n > ep)
                    434:                        n = ep - p;     /* quietly truncate */
                    435:                if (n) {
                    436:                        bcopy(bp->rptr, p, n);
                    437:                        p += n;
                    438:                }
                    439:                if (bp->class & S_DELIM) {
                    440:                        bc->dcnt--;
                    441:                        freeb(bp);
                    442:                        break;
                    443:                }
                    444:                freeb(bp);
                    445:        }
                    446:        if (bp == NULL) {
                    447:                printf("debna %d no delim\n", unit);
                    448:                bc->dcnt = 0;
                    449:                dp->h.q.head = (quadque *)bn->xfree;
                    450:                bn->xfree = dp;
                    451:                return (1);     /* ok to try another channel */
                    452:        }
                    453:        if (p - dp->d < ETHERMINTU)
                    454:                p = dp->d + ETHERMINTU; /* quietly extend */
                    455:        dp->h.bd_opc = BVPSNDDGI;
                    456:        dp->h.bd_flag = BVPRSP;         /* so it will appear on rsp queue */
                    457:        dp->h.bd_len = p - &dp->h.bd_dgsts;
                    458:        dp->h.bd_ptdb = unit;   /* some valid number */
                    459:        /* probably should zero some other fields */
                    460:        if (insqti((caddr_t)dp, &bn->bvp.d->p.p_cmdq[PCMDQ]))
                    461:                bvpcomm(bn->bvp.r, PCOWN|PCCMDQ|(PCMDQ<<PCDS));
                    462:        return (1);
                    463: }
                    464: 
                    465: /*
                    466:  * free a buffer for the port to fill in
                    467:  * -- port fusses if buffer bigger than an Ethernet packet + BVP header
                    468:  */
                    469: bnarbuf(bn, dp)
                    470: register struct bnactl *bn;
                    471: register struct dgi *dp;
                    472: {
                    473: 
                    474:        dp->h.bd_sts = 0;       /* just in case */
                    475:        dp->h.bd_opc = BVPRCVDGI;
                    476:        dp->h.bd_len = sizeof(struct bvpdg) + NIRCVBUF - BVPHSIZE;
                    477:        if (insqti((caddr_t)dp, &bn->bvp.d->f[PFREQ].f_q))
                    478:                bvpcomm(bn->bvp.r, PCOWN|PCFREQ|(PFREQ<<PCDS));
                    479: }
                    480: 
                    481: bnaxbuf(bn, dp)
                    482: register struct bnactl *bn;
                    483: register struct dgi *dp;
                    484: {
                    485:        register int i;
                    486: 
                    487:        dp->h.q.head = (quadque *)bn->xfree;
                    488:        bn->xfree = dp;
                    489:        if (bn->needst) {
                    490:                bn->needst = 0;
                    491:                for (i = 0; i < BNACHAN; i++)
                    492:                        if (bn->chan[i].needst)
                    493:                                bnastptdb(bn, &bn->chan[i]);
                    494:        }
                    495: }
                    496: 
                    497: /*
                    498:  * (fairly) general BVP routines
                    499:  */
                    500: bvpinit(bv, ap, roff)
                    501: register struct bvp *bv;
                    502: struct biaddr *ap;
                    503: int roff;
                    504: {
                    505:        register struct bvpregs *r;
                    506:        register struct biic *rb;
                    507:        register long ps;       /* most recent status */
                    508: 
                    509:        if ((rb = bv->rb) == NULL) {
                    510:                if ((rb = (struct biic *)biaddr(ap)) == NULL
                    511:                ||  badaddr(rb, sizeof(long))) {
                    512:                        printf("bvp absent\n");
                    513:                        return (0);
                    514:                }
                    515:                bv->rb = rb;
                    516:        }
                    517:        if (bv->r == NULL) {
                    518:                r = (struct bvpregs *)((char *)rb + roff);
                    519:                if (badaddr(r, sizeof(long))) {
                    520:                        printf("bvp off %x absent\n", roff);
                    521:                        return (0);
                    522:                }
                    523:                bv->r = r;
                    524:        }
                    525:        if (bv->dbuf == NULL) {
                    526:                bv->dbuf = geteblk();
                    527:                if (bv->dbuf->b_bcount < sizeof(struct bvpdata)) {
                    528:                        printf("bcount too small\n");
                    529:                        brelse(bv->dbuf);
                    530:                        return (0);
                    531:                }
                    532:                clrbuf(bv->dbuf);
                    533:                bv->d = (struct bvpdata *)bv->dbuf->b_un.b_addr;
                    534:        }
                    535:        r = bv->r;
                    536:        ps = r->stat;
                    537:        if ((ps & PSSTAT) == SUNDEF) {
                    538:                biinit(ap, 0);
                    539:                bvpdatinit(bv->d);
                    540:                bv->d->p.p_nodmsk = rb->biintr;
                    541:                bv->d->p.p_vector = (ap->vec<<2) | 5;   /* vec, br */
                    542:                bvpcomm(r, physadr(&bv->d->p)|PCOWN|PCINIT);
                    543:                ps = bvpstat(r);
                    544:        }
                    545:        if ((ps & PSSTAT) == SINIT) {
                    546:                bvpcomm(r, PCOWN|PCENAB);
                    547:                ps = bvpstat(r);
                    548:        }
                    549:        if ((ps & PSSTAT) != SENAB) {
                    550:                printf("ps %x pe %x pd %x\n", r->stat, r->err, r->data);
                    551:                return (0);
                    552:        }
                    553:        return (1);
                    554: }
                    555: 
                    556: bvpdatinit(b)
                    557: register struct bvpdata *b;
                    558: {
                    559:        bzero((char *)b, sizeof(*b));
                    560:        b->p.p_nfreeq = NFREEQ;
                    561:        b->p.p_fqb = b->f;
                    562:        b->p.p_bvplvl = 1;
                    563:        b->p.p_pqb = &b->p;
                    564:        b->p.p_bdt = b->b;
                    565:        b->p.p_bdtlen = NBDT;   /* -1? */
                    566:        b->p.p_spt = (struct pte *)physadr(Sysmap);
                    567:        b->p.p_sptlen = 0x100000;       /* huge */
                    568:        b->p.p_gpt = b->p.p_spt;
                    569:        b->p.p_gptlen = b->p.p_sptlen;
                    570: }
                    571: 
                    572: /*
                    573:  * send a port command
                    574:  */
                    575: #define        COMMTIME        1000000
                    576: 
                    577: bvpcomm(r, c)
                    578: register struct bvpregs *r;
                    579: long c;
                    580: {
                    581:        register int i;
                    582: 
                    583:        i = COMMTIME;
                    584:        while (r->ctrl & PCOWN)
                    585:                if (--i <= 0) {
                    586:                        printf("bvpcomm timeout c %x\n", c);
                    587:                        return; /* what else to do? */
                    588:                }
                    589:        r->stat &=~ PSOWN;
                    590:        r->ctrl = c;
                    591: }
                    592: 
                    593: /*
                    594:  * wait for status in init
                    595:  */
                    596: 
                    597: #define        STATTIME        1000000
                    598: 
                    599: int
                    600: bvpstat(r)
                    601: register struct bvpregs *r;
                    602: {
                    603:        register long ps;
                    604:        register int i;
                    605: 
                    606:        i = STATTIME;
                    607:        while (((ps = r->stat) & PSOWN) == 0)
                    608:                if (--i <= 0) {
                    609:                        printf("bvpstat timeout, ps %x\n", ps);
                    610:                        return (0);
                    611:                }
                    612:        return (ps);
                    613: }
                    614: 
                    615: /*
                    616:  * VAX queue primitives
                    617:  *
                    618:  * -- to set up empty queue, just zero both longwords
                    619:  */
                    620: 
                    621: /*
                    622:  * remove entry from head;
                    623:  * return entry, or 0 if none
                    624:  */
                    625: caddr_t
                    626: remqhi(q)
                    627: quadque *q;
                    628: {
                    629:        asm("0: remqhi *4(ap),r0");
                    630:        asm("bcs 0b");          /* couldn't interlock; try again */
                    631:        asm("bvc 1f");          /* br if removed something */
                    632:        asm("clrl r0");
                    633:        asm("1:");
                    634: }
                    635: 
                    636: /*
                    637:  * insert entry to tail
                    638:  * return 1 if this was the first entry
                    639:  */
                    640: insqti(e, q)
                    641: caddr_t e;
                    642: quadque *q;
                    643: {
                    644:        asm("clrl r0");
                    645:        asm("0: insqti *4(ap),*8(ap)");
                    646:        asm("bcs 0b");
                    647:        asm("bneq 1f");
                    648:        asm("incl r0");
                    649:        asm("1:");
                    650: }

unix.superglobalmegacorp.com

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