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