|
|
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.