|
|
1.1 root 1: /*
2: * Raw line discipline and listener stuff for talking to controller
3: */
4: #include "sys/param.h"
5: #include "sys/stream.h"
6: #include "sys/dkio.h"
7: #include "sys/conf.h"
8: #include "sys/dkstat.h"
9: #include "sys/dkmod.h"
10:
11: /*
12: * CMC/Listener message structure
13: */
14: struct dialin {
15: char type;
16: char srv;
17: short param0;
18: short param1;
19: short param2;
20: short param3;
21: short param4;
22: short param5;
23: };
24:
25: struct dialout {
26: short chan;
27: struct dialin d;
28: };
29:
30: /*
31: * Message codes
32: */
33: #define T_CALL '0'
34: #define T_LSTNR 4
35: #define T_CHG 3
36: #define T_REPLY 10
37: #define D_CLOSE 1
38: #define D_ISCLOSED 2
39: #define D_ENQ 3
40: #define D_ENQANS 4
41:
42: /*
43: * Raw-mode line discipline for DK (only)
44: */
45: long adkopen();
46: int adkclose(), adkiput(), adkoput(), adkosrv(), adkisrv();
47: static struct qinit adkrinit = { adkiput, adkisrv, adkopen, adkclose, 72, 36};
48: static struct qinit adkwinit = { adkoput, adkosrv, adkopen, nulldev, 72, 36};
49: struct streamtab adkstream = { &adkrinit, &adkwinit };
50:
51: extern struct dkstat dkstat;
52: extern struct dkmodule dkmod[];
53: extern int dkmodcnt;
54:
55: #define NDKRAW 32
56: struct adk {
57: struct queue *q;
58: struct dkmodule *module;
59: short chan;
60: } adk[NDKRAW];
61:
62: long
63: adkopen(q, dev)
64: register struct queue *q;
65: {
66: static timer_on = 0;
67: register struct adk *dkp, *edkp;
68: register struct dkmodule *dkm;
69:
70: if ((dkm = getdkmod(dev)) == NULL)
71: return (0);
72: edkp = NULL;
73: for (dkp=adk; dkp < &adk[NDKRAW]; dkp++) {
74: if (dkp->q == q) {
75: if (dkp->chan != minor(dev) - dkm->lo || WR(q)->ptr==NULL) {
76: printf("q %x dkp %x\n", q, dkp);
77: panic("adkopen");
78: }
79: return(1);
80: }
81: if (dkp->q == NULL && edkp==NULL)
82: edkp = dkp;
83: }
84: if (edkp==NULL)
85: return(0);
86: edkp->q = q;
87: edkp->module = dkm;
88: edkp->chan = minor(dev) - dkm->lo;
89: q->flag |= QDELIM;
90: q->ptr = 0;
91: WR(q)->ptr = (caddr_t)edkp;
92: if (timer_on==0) {
93: adktimer();
94: timer_on = 1;
95: }
96: return(1);
97: }
98:
99: adkclose(q)
100: register struct queue *q;
101: {
102: register struct block *bp;
103: register struct adk *dkp = (struct adk *)WR(q)->ptr;
104:
105: if (WR(q)==dkp->module->listnrq) {
106: dkp->module->listnrq = NULL;
107: dkp->module->type = 0;
108: }
109: while (bp = getq(q))
110: (*q->next->qinfo->putp)(q->next, bp);
111: dkp->q = NULL;
112: dkp->module = NULL;
113: }
114:
115: /*
116: * output put procedure.
117: */
118: adkoput(q, bp)
119: register struct queue *q;
120: register struct block *bp;
121: {
122: register struct adk *dkp = (struct adk *)q->ptr;
123: register struct dkmodule *modp = dkp->module;
124: register i;
125:
126: switch (bp->type) {
127:
128: case M_IOCTL:
129: switch (stiocom(bp)) {
130:
131: /* hang everybody up */
132: case DIOCHUP:
133: /* must be on listener chan */
134: if (q == modp->listnrq) {
135: adkmesg(modp, T_LSTNR, 0, 0, 0, 1);
136: bp->type = M_IOCACK;
137: bp->rptr = bp->wptr;
138: qreply(q, bp);
139: return;
140: }
141: break;
142:
143: /* announce listener channel */
144: case DIOCLHN:
145: if (modp->listnrq == NULL) {
146: modp->listnrq = q;
147: RD(q)->flag |= QNOENB;
148: modp->type = CMCLD;
149: adkmesg(modp, T_LSTNR, 0, 0, 0, 0);
150: bp->type = M_IOCACK;
151: bp->rptr = bp->wptr;
152: qreply(q, bp);
153: return;
154: }
155: break;
156:
157: /* delay input */
158: case DIOCSTOP:
159: RD(q)->ptr = (caddr_t)1;
160: bp->type = M_IOCACK;
161: bp->rptr = bp->wptr;
162: qreply(q, bp);
163: return;
164:
165: /* suggest a free outgoing channel */
166: case DIOCCHAN:
167: for (i=modp->lo + 3; i<modp->hi; i+=2) {
168: if (modp->dkstate[i]==DKCLOSED) {
169: stiodata(bp)[0] = i;
170: for (i = 1; i < sizeof(int); i++)
171: stiodata(bp)[i] = 0; /* silly */
172: bp->wptr = bp->rptr+STIOCHDR+sizeof(int);
173: bp->type = M_IOCACK;
174: break;
175: }
176: }
177: qreply(q, bp);
178: return;
179:
180: default:
181: (*q->next->qinfo->putp)(q->next, bp);
182: return;
183: }
184: bp->type = M_IOCNAK;
185: bp->wptr = bp->rptr;
186: qreply(q, bp);
187: return;
188: }
189: putq(q, bp);
190: }
191:
192: adkosrv(q)
193: register struct queue *q;
194: {
195: register struct block *bp;
196:
197: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
198: (*q->next->qinfo->putp)(q->next, bp);
199: }
200:
201: /*
202: * input put procedure
203: * -- ignores all control bytes
204: */
205: adkiput(q, bp)
206: register struct queue *q;
207: register struct block *bp;
208: {
209: register struct adk *dkp = (struct adk *)WR(q)->ptr;
210: register int delim;
211:
212: switch (bp->type) {
213:
214: case M_DATA:
215: if (WR(q) == dkp->module->listnrq) {
216: delim = bp->class & S_DELIM;
217: putq(q, bp);
218: if (delim)
219: qenable(q);
220: return;
221: }
222: if (q->next->flag&QFULL) { /* you lose */
223: freeb(bp);
224: return;
225: }
226: /* bp->class |= S_DELIM; always push through; this seems wrong */
227: if (q->ptr) { /* input delayed */
228: putq(q, bp);
229: return;
230: }
231: (*q->next->qinfo->putp)(q->next, bp);
232: return;
233:
234: case M_IOCACK:
235: case M_IOCNAK:
236: case M_HANGUP:
237: (*q->next->qinfo->putp)(q->next, bp);
238: return;
239:
240: case M_PRICTL:
241: switch (*bp->rptr) {
242: case DKMCLOSE:
243: if (dkp->module->dkstate[bp->rptr[1]] == DKRCLOSE)
244: adkmesg(dkp->module, T_CHG, D_ISCLOSED, 0, bp->rptr[1], 0);
245: else
246: adkmesg(dkp->module, T_CHG, D_CLOSE, 0, bp->rptr[1], 0);
247: freeb(bp);
248: return;
249:
250: default:
251: freeb(bp);
252: return;
253: }
254:
255: default:
256: freeb(bp);
257: }
258: }
259:
260: /*
261: * listener sends a message to CMC
262: */
263: adkmesg(modp, type, srv, p0, p1, p2)
264: register struct dkmodule *modp;
265: {
266: register struct dialout *dp;
267: register struct block *bp;
268:
269: if (modp->listnrq==NULL || modp->listnrq->next->flag&QFULL)
270: return;
271: if ((bp = allocb(sizeof(struct dialout))) == NULL)
272: return; /* hope it will be retried later */
273: dp = (struct dialout *)bp->wptr;
274: dp->chan = ((struct adk *)modp->listnrq->ptr)->chan;
275: dp->d.type = type;
276: dp->d.srv = srv;
277: dp->d.param0 = p0;
278: dp->d.param1 = p1;
279: dp->d.param2 = p2;
280: bp->wptr += sizeof(struct dialout);
281: bp->class |= S_DELIM;
282: (*modp->listnrq->next->qinfo->putp)(modp->listnrq->next, bp);
283: }
284:
285:
286: /* try to construct a struct dialin from the message */
287: struct block *
288: adkdialin(q, bp)
289: register struct queue *q;
290: register struct block *bp;
291: {
292: register struct block *nbp;
293: register int len;
294: register int delim;
295: register int n;
296: register int over;
297:
298: if ((len = bp->wptr - bp->rptr) == sizeof(struct dialin))
299: return bp;
300: n = sizeof(struct dialin) - len;
301: delim = bp->class & S_DELIM;
302:
303: if (bp->lim - bp->rptr >= sizeof(struct dialin))
304: nbp = bp;
305: else if ((nbp = allocb(sizeof(struct dialin))) == NULL) {
306: freeb(bp);
307: return NULL;
308: } else {
309: bcopy(bp->rptr, nbp->wptr, len);
310: nbp->wptr += len;
311: freeb(bp);
312: }
313:
314: over = 0;
315: while (!delim && (bp = getq(q))) {
316: len = bp->wptr - bp->rptr <= n ? bp->wptr - bp->rptr : (over = 1, n);
317: bcopy(bp->rptr, nbp->wptr, len);
318: nbp->wptr += len;
319: n -= len;
320: delim = bp->class & S_DELIM;
321: freeb(bp);
322: }
323: if (n == 0 && !over && delim)
324: return nbp;
325: freeb(nbp);
326: return NULL;
327: }
328:
329: /*
330: * Receive message for listener
331: */
332: adkisrv(q)
333: register struct queue *q;
334: {
335: register struct adk *dkp = (struct adk *)WR(q)->ptr;
336: struct dkmodule *modp = dkp->module;
337: register struct queue *listnrq = modp->listnrq;
338: register struct block *bp;
339: register struct dialin *dialp;
340: register int i;
341:
342: if (WR(q) != modp->listnrq)
343: return;
344:
345: while (bp = getq(q)) {
346:
347: switch (*bp->rptr) {
348:
349: case T_CALL:
350: bp->rptr++;
351: if (bp->wptr - bp->rptr <= 0 &&
352: ((bp->class & S_DELIM) == 0 || (bp = getq(q)) == NULL))
353: return;
354: do {
355: i = bp->class & S_DELIM;
356: if (q->next->flag & QFULL)
357: free(bp);
358: else
359: (*q->next->qinfo->putp)(q->next, bp);
360: } while (i == 0 && (bp = getq(q)));
361: break;
362: case T_CHG:
363: if ((bp = adkdialin(q, bp)) == NULL)
364: break;
365: dialp = (struct dialin *)bp->rptr;
366: i = dialp->param1;
367: if (i <= 0 || i >= modp->hi - modp->lo) {
368: dkstat.chgstrange++;
369: if (dialp->srv)
370: adkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
371: freeb(bp);
372: break;
373: }
374: switch (dialp->srv) {
375:
376: case D_CLOSE: /* remote shutdown */
377: switch (modp->dkstate[i]) {
378:
379: case DKRCLOSE:
380: dkstat.notclosed++;
381: case DKOPEN:
382: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
383: break;
384:
385: case DKLCLOSE:
386: case DKCLOSED:
387: adkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
388: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
389: break;
390: }
391: break;
392:
393: case D_ISCLOSED:
394: switch (modp->dkstate[i]) {
395:
396: case DKLCLOSE:
397: case DKCLOSED:
398: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
399: break;
400:
401: case DKOPEN:
402: case DKRCLOSE:
403: dkstat.isclosed++;
404: break;
405: }
406: break;
407:
408: case D_ENQ:
409: adkmesg(modp, T_CHG, D_ENQANS, 0, i, modp->dkstate[i]);
410: break;
411: }
412: freeb(bp);
413: break;
414:
415: case T_REPLY: /* CMC sends reply; find, and hand to process */
416: if ((bp = adkdialin(q, bp)) == NULL)
417: break;
418: dialp = (struct dialin *)bp->rptr;
419: i = dialp->param0;
420: if (i < 0 || i >= modp->hi - modp->lo) {
421: free(bp);
422: break;
423: }
424: for (dkp=adk; dkp<&adk[NDKRAW]; dkp++) {
425: if (dkp->module==modp && dkp->chan==i) {
426: bp->class |= S_DELIM;
427: (*dkp->q->next->qinfo->putp)(dkp->q->next, bp);
428: break;
429: }
430: }
431: if (dkp == &adk[NDKRAW])
432: free(bp);
433: break;
434:
435: default:
436: free(bp);
437: break;
438: }
439: }
440: }
441:
442: /*
443: * 15-second timer
444: * -- should look at dkmod->type, so different
445: * listeners can coexist
446: */
447: adktimer()
448: {
449: register i;
450: register struct dkmodule *dkp;
451:
452: for (dkp = dkmod; dkp < &dkmod[dkmodcnt]; dkp++) {
453: if (dkp->listnrq && dkp->type == CMCLD) {
454: adkmesg(dkp, T_LSTNR, 0, 0, 0, 0);
455: for (i=dkp->hi - dkp->lo - 1; i >= 0; --i)
456: if (dkp->dkstate[i] == DKLCLOSE)
457: adkmesg(dkp, T_CHG, D_CLOSE, 0, i, 0);
458: }
459: }
460: timeout(adktimer, (caddr_t)NULL, 15*HZ);
461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.