|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.