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

unix.superglobalmegacorp.com

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