Annotation of researchv8dc/sys/dev/stream.c, revision 1.1.1.1

1.1       root        1: #include "../h/param.h"
                      2: #include "../h/stream.h"
                      3: #include "../h/mtpr.h"
                      4: #include "../h/conf.h"
                      5: #include "sparam.h"
                      6: 
                      7: #define        M_HIPRI 127                     /* for use of putbq */
                      8: 
                      9: #ifndef        NBLKBIG
                     10: #define        NBLKBIG 0
                     11: #endif
                     12: #define        NBLOCK (NBLKBIG+NBLK64+NBLK16+NBLK4)
                     13: struct block cblock[NBLOCK];           /* allocation of blocks */
                     14: u_char blkdata[1024*NBLKBIG+64*NBLK64+NBLK16*16+NBLK4*4];
                     15: long   blkubad;                        /* unibus address of blocks */
                     16: struct queue queue[NQUEUE];            /* allocation of queues */
                     17: struct queue *qhead;                   /* head of queues to run */
                     18: struct queue *qtail;                   /* last queue */
                     19: struct block *qfreelist[4];            /* allocation of freelist heads */
                     20: int    cblockC[] = { NBLK4, NBLK16, NBLK64, NBLKBIG };
                     21: int    cblockM[] = { 1000, 1000, 1000, 1000 };
                     22: 
                     23: int    rbsize[] = { 4, 16, 64, 1024 }; /* real block sizes */
                     24: int    bsize[] = { 4, 16, 64, 250 };   /* size for q limits */
                     25: 
                     26: int    nballoc;
                     27: 
                     28: struct block *
                     29: allocb(size)
                     30: register size;
                     31: {
                     32:        register struct block *bp;
                     33:        register s = spl6();
                     34:        register class;
                     35: 
                     36:        if (size <= 4)
                     37:                class = 0;
                     38:        else if (size <= 16)
                     39:                class = 1;
                     40:        else if (size <= 64)
                     41:                class = 2;
                     42:        else {
                     43:                class = 3;
                     44:                nballoc++;
                     45:        }
                     46:        if (bp = qfreelist[class])
                     47:                qfreelist[class] = bp->next;
                     48:        else {
                     49:                if (qfreelist[2])
                     50:                        return(allocb(64));
                     51:                panic("allocb out of blocks\n");
                     52:        }
                     53:        splx(s);
                     54:        if (--cblockC[class] < cblockM[class])
                     55:                cblockM[class] = cblockC[class];
                     56:        bp->rptr = bp->base;
                     57:        bp->wptr = bp->base;
                     58:        bp->lim = bp->base+rbsize[class];
                     59:        bp->class = class;
                     60:        bp->type = M_DATA;
                     61:        bp->next = NULL;
                     62:        return(bp);
                     63: }
                     64: 
                     65: freeb(bp)
                     66: register struct block *bp;
                     67: {
                     68:        register s = spl6();
                     69:        register struct block *bp1;
                     70:        register class = bp->class;
                     71: 
                     72: #ifdef CAREFUL
                     73:        if (bp < &cblock[0] || bp >= &cblock[NBLOCK])
                     74:                printf("freeing %x\n", bp);
                     75:        bp1 = qfreelist[class];
                     76:        while (bp1) {
                     77:                if (bp1 == bp)
                     78:                        panic("Free of free block");
                     79:                bp1 = bp1->next;
                     80:        }
                     81: #endif
                     82:        bp->next = qfreelist[class];
                     83:        qfreelist[class] = bp;
                     84:        cblockC[class]++;
                     85:        splx(s);
                     86: }
                     87: 
                     88: struct block *
                     89: getq(q)
                     90: register struct queue *q;
                     91: {
                     92:        register struct block *bp;
                     93:        register s = spl6();
                     94: 
                     95:        if ((bp = q->first) == NULL) {
                     96:                if ((q->flag&QENAB) == 0)
                     97:                        q->flag |= QWANTR;
                     98:        } else {
                     99: if (bp < &cblock[0] || bp >= &cblock[NBLOCK]) panic("getting bad block\n", bp);
                    100:                if ((q->first = bp->next) == NULL)
                    101:                        q->last = NULL;
                    102:                q->count -= bsize[bp->class];
                    103:                if (q->count < q->qinfo->limit)
                    104:                        q->flag &= ~QFULL;
                    105:                q->flag &= ~QWANTR;
                    106:        }
                    107:        if (q->count<=q->qinfo->lolimit && q->flag&QWANTW && OTHERQ(q)->next) {
                    108:                register struct queue *bq = backq(q);
                    109:                if (bq->qinfo->srvp) {
                    110:                        qenable(bq);
                    111:                }
                    112:                q->flag &= ~QWANTW;
                    113:        }
                    114:        splx(s);
                    115:        return(bp);
                    116: }
                    117: 
                    118: putq(q, bp)
                    119: register struct queue *q;
                    120: register struct block *bp;
                    121: {
                    122:        int s;
                    123: 
                    124:        if (bp->type==M_FLUSH)
                    125:                flushq(q, 0);
                    126:        s = spl6();
                    127:        if (q->first==NULL) {                   /* empty, just tack on */
                    128:                q->first = bp;
                    129:                q->last = bp;
                    130:                bp->next = NULL;
                    131:        } else if (bp->type<QPCTL || q->last->type>=QPCTL) {    /* put at end */
                    132:                register struct block *lastp = q->last;
                    133:                register n = bp->wptr - bp->rptr;
                    134:                if (bp->type==M_DATA && lastp->type==M_DATA
                    135:                 && n <= lastp->lim-lastp->wptr && lastp->wptr>=lastp->base){
                    136:                        bcopy(bp->rptr, lastp->wptr, n);
                    137:                        lastp->wptr += n;
                    138:                        freeb(bp);
                    139:                        bp = NULL;
                    140:                } else {
                    141:                        lastp->next = bp;
                    142:                        q->last = bp;
                    143:                        bp->next = NULL;
                    144:                }
                    145:        } else {                                /* pri, put after any others */
                    146:                register struct block *nbp = q->first;
                    147:                if (nbp->type < QPCTL) {
                    148:                        bp->next = q->first;
                    149:                        q->first = bp;
                    150:                } else {
                    151:                        while (nbp->next->type>=QPCTL)
                    152:                                nbp = nbp->next;
                    153:                        bp->next = nbp->next;
                    154:                        nbp->next = bp;
                    155:                }
                    156:        }
                    157:        if (bp) {
                    158:                q->count += bsize[bp->class];
                    159:                if (bp->type >= QPCTL && bp->type!= M_HIPRI)
                    160:                        q->flag |= QWANTR;
                    161:        }
                    162:        if (q->count >= q->qinfo->limit)
                    163:                q->flag |= QFULL|QWANTW;
                    164:        if ((q->flag & (QWANTR|QENAB|QNOENB)) == QWANTR && q->qinfo->srvp)
                    165:                qenable(q);
                    166:        splx(s);
                    167: }
                    168: 
                    169: /*
                    170:  * Put stuff back at beginning of Q
                    171:  * (but after any priority msgs)
                    172:  */
                    173: putbq(q, bp)
                    174: register struct queue *q;
                    175: register struct block *bp;
                    176: {
                    177:        register savetype = bp->type;
                    178:        register s = spl6();
                    179: 
                    180:        bp->type = M_HIPRI;             /* fake priority, to force to start */
                    181:        putq(q, bp);
                    182:        bp->type = savetype;
                    183:        splx(s);
                    184: }
                    185: 
                    186: /*
                    187:  * empty a queue.  Leave any non-data messages, unless flag is 1.
                    188:  */
                    189: flushq(q, flag)
                    190: register struct queue *q;
                    191: {
                    192:        register struct block *bp, *nbp;
                    193:        register s = spl6();
                    194: 
                    195:        bp = q->first;
                    196:        q->first = NULL;
                    197:        if (q->last)
                    198:                q->last->next = NULL;
                    199:        q->last = NULL;
                    200:        q->count = 0;
                    201:        q->flag &= ~QFULL;
                    202:        while (bp) {
                    203:                nbp = bp->next;
                    204:                if (bp->type != M_DATA && bp->type != M_DELIM
                    205:                 && bp->type != M_CTL && bp->type != M_DELAY
                    206:                 && bp->type != M_FLUSH && !flag)
                    207:                        putq(q, bp);
                    208:                else {
                    209:                        if (bp->type == M_PASS)
                    210:                                printf("flushing PASS %x\n",*(int *)(bp->rptr));
                    211:                        freeb(bp);
                    212:                }
                    213:                bp = nbp;
                    214:        }
                    215:        if (q->flag&QWANTW && OTHERQ(q)->next) {
                    216:                q->flag &= ~QWANTW;
                    217:                qenable(backq(q));
                    218:        }
                    219:        splx(s);
                    220: }
                    221: 
                    222: qinit()
                    223: {
                    224:        register struct block *bp;
                    225:        register i, j;
                    226:        register u_char *base;
                    227: 
                    228:        base = blkdata;
                    229:        /* blocks are allocated on unibus for DMA.  Assumes unibus 0 */
                    230:        blkubad = uballoc(0, (caddr_t)blkdata, sizeof(blkdata), 0);
                    231:        if (blkubad == 0)
                    232:                panic("Cannot map blocks on unibus in qinit");
                    233:        i = 0;
                    234:        for (j=0; j<NBLK4; i++, j++) {
                    235:                bp = &cblock[i];
                    236:                bp->class = 0;
                    237:                bp->base = base;
                    238:                base += 4;
                    239:                bp->next = qfreelist[0];
                    240:                qfreelist[0] = bp;
                    241:        }
                    242:        for (j=0; j<NBLK16; i++, j++) {
                    243:                bp = &cblock[i];
                    244:                bp->class = 1;
                    245:                bp->base = base;
                    246:                base += 16;
                    247:                bp->next = qfreelist[1];
                    248:                qfreelist[1] = bp;
                    249:        }
                    250:        for (j=0; j<NBLK64; i++, j++) {
                    251:                bp = &cblock[i];
                    252:                bp->class = 2;
                    253:                bp->base = base;
                    254:                base += 64;
                    255:                bp->next = qfreelist[2];
                    256:                qfreelist[2] = bp;
                    257:        }
                    258:        for (j=0; j<NBLKBIG; i++, j++) {
                    259:                bp = &cblock[i];
                    260:                bp->class = 3;
                    261:                bp->base = base;
                    262:                base += 1024;
                    263:                bp->next = qfreelist[3];
                    264:                qfreelist[3] = bp;
                    265:        }
                    266: }
                    267: 
                    268: /*
                    269:  * allocate a pair of queues
                    270:  */
                    271: struct queue *
                    272: allocq()
                    273: {
                    274:        register struct queue *qp;
                    275:        static struct queue zeroR =
                    276:          { NULL,NULL,NULL,NULL,NULL,NULL,0,QUSE|QREADR};
                    277:        static struct queue zeroW =
                    278:          { NULL,NULL,NULL,NULL,NULL,NULL,0,QUSE};
                    279: 
                    280:        for (qp = queue; qp < &queue[NQUEUE]; qp += 2) {
                    281:                if ((qp->flag & QUSE) == 0) {
                    282:                        *qp = zeroR;
                    283:                        *WR(qp) = zeroW;
                    284:                        return(qp);
                    285:                }
                    286:        }
                    287:        return(NULL);
                    288: }
                    289: 
                    290: /*
                    291:  * Put one data char on a queue, using f
                    292:  */
                    293: putd(f, q, c)
                    294: int (*f)();
                    295: register struct queue *q;
                    296: {
                    297:        register struct block *bp;
                    298:        register s = spl6();
                    299: 
                    300:        if (f==putq && (bp = q->last) && bp->type==M_DATA && bp->wptr<bp->lim) {
                    301:                *bp->wptr++ = c;
                    302:                splx(s);
                    303:         } else {
                    304:                splx(s);
                    305:                if ((bp = allocb(16)) == NULL)
                    306:                        return(0);
                    307:                bp->type = M_DATA;
                    308:                *bp->wptr++ = c;
                    309:                (*f)(q, bp);
                    310:        }
                    311:        return(1);
                    312: }
                    313: 
                    314: /*
                    315:  * Put a single-byte control record on queue (>=0100 implies QPCTL)
                    316:  */
                    317: putctl(q, c)
                    318: struct queue *q;
                    319: {
                    320:        register struct block *bp;
                    321: 
                    322:        if ((bp = allocb(1)) == NULL)
                    323:                return(0);
                    324:        bp->type = c;
                    325:        (*q->qinfo->putp)(q, bp);
                    326:        return(1);
                    327: }
                    328: 
                    329: /*
                    330:  * Control record with a single-byte parameter
                    331:  */
                    332: putctl1(q, c, p)
                    333: struct queue *q;
                    334: {
                    335:        register struct block *bp;
                    336: 
                    337:        if ((bp = allocb(1)) == NULL)
                    338:                return(0);
                    339:        bp->type = c;
                    340:        *bp->wptr++ = p;
                    341:        (*q->qinfo->putp)(q, bp);
                    342:        return(1);
                    343: }
                    344: 
                    345: /*
                    346:  * put control record, using putq instead of queue's putp
                    347:  */
                    348: qpctl(q, d)
                    349: register struct queue *q;
                    350: {
                    351:        register struct block *bp = allocb(1);
                    352: 
                    353:        if (bp) {
                    354:                bp->type = d;
                    355:                putq(q, bp);
                    356:        }
                    357: }
                    358: 
                    359: qpctl1(q, c, d)
                    360: register struct queue *q;
                    361: {
                    362:        register struct block *bp = allocb(1);
                    363: 
                    364:        if (bp) {
                    365:                bp->type = c;
                    366:                *bp->wptr++ = d;
                    367:                putq(q, bp);
                    368:        }
                    369: }
                    370: 
                    371: /*
                    372:  * Copy a literal record onto queue
                    373:  */
                    374: putcpy(q, cp, n)
                    375: register struct queue *q;
                    376: register char *cp;
                    377: {
                    378:        register struct block *bp;
                    379:        register nm;
                    380: 
                    381:        while (n) {
                    382:                if ((bp = allocb(n)) == NULL)   /* sorry */
                    383:                        return;
                    384:                bp->type = M_DATA;
                    385:                nm = bp->lim - bp->wptr;
                    386:                if (nm > n)
                    387:                        nm = n;
                    388:                bcopy(cp, bp->wptr, nm);
                    389:                cp += nm;
                    390:                bp->wptr += nm;
                    391:                n -= nm;
                    392:                (*q->qinfo->putp)(q, bp);
                    393:        }
                    394: }
                    395: 
                    396: /*
                    397:  * return the queue upstream from this one
                    398:  */
                    399: struct queue *
                    400: backq(q)
                    401: register struct queue *q;
                    402: {
                    403:        q = OTHERQ(q);
                    404:        if (q->next) {
                    405:                q = q->next;
                    406:                return(OTHERQ(q));
                    407:        }
                    408:        q = OTHERQ(q);
                    409:        printf("backq called with no back (Q %x)\n", q);
                    410:        panic("backq");
                    411:        return(NULL);
                    412: }
                    413: 
                    414: /*
                    415:  * Send a block back up the queue in reverse from this
                    416:  * one (e.g. to respond to ioctls)
                    417:  */
                    418: qreply(q, bp)
                    419: register struct queue *q;
                    420: struct block *bp;
                    421: {
                    422:        q = OTHERQ(q);
                    423:        (*q->next->qinfo->putp)(q->next, bp);
                    424: }
                    425: 
                    426: /*
                    427:  * Enable a queue: put it on list of those whose srvp's are
                    428:  * ready to run.
                    429:  */
                    430: qenable(q)
                    431: register struct queue *q;
                    432: {
                    433:        register s;
                    434: 
                    435:        s = spl6();
                    436:        if (q->flag & QENAB) {
                    437:                splx(s);
                    438:                return;
                    439:        }
                    440:        if (q->qinfo->srvp==NULL) {
                    441:                splx(s);
                    442:                return;
                    443:        }
                    444:        q->flag |= QENAB;
                    445:        q->link = NULL;
                    446:        if (qhead==NULL)
                    447:                qhead = q;
                    448:        else
                    449:                qtail->link = q;
                    450:        qtail = q;
                    451:        setqsched();
                    452:        splx(s);
                    453: }
                    454: 
                    455: /*
                    456:  * Run the srvp's of each enabled queue
                    457:  *     -- Should not be reentered
                    458:  */
                    459: queuerun()
                    460: {
                    461:        register struct queue *q;
                    462:        register s;
                    463:        extern int queueflag;
                    464:        extern char *panicstr;
                    465: 
                    466:        if (panicstr)
                    467:                return;         /* to minimize destruction */
                    468:        s = spl6();
                    469:        queueflag++;
                    470:        while (q = qhead) {
                    471:                if ((qhead = q->link) == NULL)
                    472:                        qtail = NULL;
                    473:                q->flag &= ~QENAB;
                    474:                splx(s);
                    475:                if (q->qinfo->srvp != NULL)
                    476:                        (*q->qinfo->srvp)(q);
                    477:                else
                    478:                        printf("Q %x run with no srvp\n", q);
                    479:                spl6();
                    480:        }
                    481:        queueflag--;
                    482:        splx(s);
                    483: }

unix.superglobalmegacorp.com

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