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