|
|
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_LSTNR 4
34: #define T_CHG 3
35: #define T_REPLY 10
36: #define D_CLOSE 1
37: #define D_ISCLOSED 2
38: #define D_ENQ 3
39: #define D_ENQANS 4
40:
41: /*
42: * Raw-mode line discipline for DK (only)
43: */
44: long rdkopen();
45: int rdkclose(), rdkiput(), rdkoput(), rdkosrv();
46: static struct qinit rdkrinit = { rdkiput, NULL, rdkopen, rdkclose, 72, 36};
47: static struct qinit rdkwinit = { rdkoput, rdkosrv, rdkopen, nulldev, 72, 36};
48: struct streamtab rdkstream = { &rdkrinit, &rdkwinit };
49:
50: extern struct dkstat dkstat;
51: extern struct dkmodule dkmod[];
52: extern int dkmodcnt;
53:
54: #define NDKRAW 32
55: struct rdk {
56: struct queue *q;
57: struct dkmodule *module;
58: short chan;
59: } rdk[NDKRAW];
60:
61: long
62: rdkopen(q, dev)
63: register struct queue *q;
64: {
65: static timer_on = 0;
66: register struct rdk *dkp, *edkp;
67: register struct dkmodule *dkm;
68:
69: if ((dkm = getdkmod(dev)) == NULL)
70: return (0);
71: edkp = NULL;
72: for (dkp=rdk; dkp < &rdk[NDKRAW]; dkp++) {
73: if (dkp->q == q) {
74: if (dkp->chan != minor(dev) - dkm->lo || WR(q)->ptr==NULL) {
75: printf("q %x dkp %x\n", q, dkp);
76: panic("rdkopen");
77: }
78: return(1);
79: }
80: if (dkp->q == NULL && edkp==NULL)
81: edkp = dkp;
82: }
83: if (edkp==NULL)
84: return(0);
85: edkp->q = q;
86: edkp->module = dkm;
87: edkp->chan = minor(dev) - dkm->lo;
88: q->flag |= QDELIM;
89: q->ptr = 0;
90: WR(q)->ptr = (caddr_t)edkp;
91: if (timer_on==0) {
92: dktimer();
93: timer_on = 1;
94: }
95: return(1);
96: }
97:
98: rdkclose(q)
99: register struct queue *q;
100: {
101: register struct block *bp;
102: register struct rdk *dkp = (struct rdk *)WR(q)->ptr;
103:
104: if (WR(q)==dkp->module->listnrq) {
105: dkp->module->listnrq = NULL;
106: dkp->module->type = 0;
107: }
108: while (bp = getq(q))
109: (*q->next->qinfo->putp)(q->next, bp);
110: dkp->q = NULL;
111: dkp->module = NULL;
112: }
113:
114: /*
115: * output put procedure.
116: */
117: rdkoput(q, bp)
118: register struct queue *q;
119: register struct block *bp;
120: {
121: register struct rdk *dkp = (struct rdk *)q->ptr;
122: register struct dkmodule *modp = dkp->module;
123: register i;
124:
125: switch (bp->type) {
126:
127: case M_IOCTL:
128: switch (stiocom(bp)) {
129:
130: /* hang everybody up */
131: case DIOCHUP:
132: /* must be on listener chan */
133: if (q == modp->listnrq) {
134: dkmesg(modp, T_LSTNR, 0, 0, 0, 1);
135: bp->type = M_IOCACK;
136: bp->rptr = bp->wptr;
137: qreply(q, bp);
138: return;
139: }
140: break;
141:
142: /* announce listener channel */
143: case DIOCLHN:
144: if (modp->listnrq == NULL) {
145: modp->listnrq = q;
146: modp->type = CMCLD;
147: dkmesg(modp, T_LSTNR, 0, 0, 0, 0);
148: bp->type = M_IOCACK;
149: bp->rptr = bp->wptr;
150: qreply(q, bp);
151: return;
152: }
153: break;
154:
155: /* delay input */
156: case DIOCSTOP:
157: RD(q)->ptr = (caddr_t)1;
158: bp->type = M_IOCACK;
159: bp->rptr = bp->wptr;
160: qreply(q, bp);
161: return;
162:
163: /* suggest a free outgoing channel */
164: case DIOCCHAN:
165: for (i=modp->lo + 3; i<modp->hi; i+=2) {
166: if (modp->dkstate[i]==DKCLOSED) {
167: stiodata(bp)[0] = i;
168: for (i = 1; i < sizeof(int); i++)
169: stiodata(bp)[i] = 0; /* silly */
170: bp->wptr = bp->rptr+STIOCHDR+sizeof(int);
171: bp->type = M_IOCACK;
172: break;
173: }
174: }
175: qreply(q, bp);
176: return;
177:
178: default:
179: (*q->next->qinfo->putp)(q->next, bp);
180: return;
181: }
182: bp->type = M_IOCNAK;
183: bp->wptr = bp->rptr;
184: qreply(q, bp);
185: return;
186: }
187: putq(q, bp);
188: }
189:
190: rdkosrv(q)
191: register struct queue *q;
192: {
193: register struct block *bp;
194:
195: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
196: (*q->next->qinfo->putp)(q->next, bp);
197: }
198:
199: /*
200: * input put procedure
201: * -- ignores all control bytes
202: */
203: rdkiput(q, bp)
204: register struct queue *q;
205: register struct block *bp;
206: {
207: register struct rdk *dkp = (struct rdk *)WR(q)->ptr;
208:
209: switch (bp->type) {
210:
211: case M_DATA:
212: if (WR(q)==dkp->module->listnrq && dklstnr(dkp->module, bp))
213: return;
214: if (q->next->flag&QFULL) { /* you lose */
215: freeb(bp);
216: return;
217: }
218: bp->class |= S_DELIM; /* always push through */
219: if (q->ptr) { /* input delayed */
220: putq(q, bp);
221: return;
222: }
223: (*q->next->qinfo->putp)(q->next, bp);
224: return;
225:
226: case M_IOCACK:
227: case M_IOCNAK:
228: case M_HANGUP:
229: (*q->next->qinfo->putp)(q->next, bp);
230: return;
231:
232: case M_PRICTL:
233: switch (*bp->rptr) {
234: case DKMCLOSE:
235: if (dkp->module->dkstate[bp->rptr[1]] == DKRCLOSE)
236: dkmesg(dkp->module, T_CHG, D_ISCLOSED, 0, bp->rptr[1], 0);
237: else
238: dkmesg(dkp->module, T_CHG, D_CLOSE, 0, bp->rptr[1], 0);
239: freeb(bp);
240: return;
241:
242: default:
243: freeb(bp);
244: return;
245: }
246:
247: default:
248: freeb(bp);
249: }
250: }
251:
252: /*
253: * listener sends a message to CMC
254: */
255: dkmesg(modp, type, srv, p0, p1, p2)
256: register struct dkmodule *modp;
257: {
258: register struct dialout *dp;
259: register struct block *bp;
260:
261: if (modp->listnrq==NULL || modp->listnrq->next->flag&QFULL)
262: return;
263: if ((bp = allocb(sizeof(struct dialout))) == NULL)
264: return; /* hope it will be retried later */
265: dp = (struct dialout *)bp->wptr;
266: dp->chan = ((struct rdk *)modp->listnrq->ptr)->chan;
267: dp->d.type = type;
268: dp->d.srv = srv;
269: dp->d.param0 = p0;
270: dp->d.param1 = p1;
271: dp->d.param2 = p2;
272: bp->wptr += sizeof(struct dialout);
273: bp->class |= S_DELIM;
274: (*modp->listnrq->next->qinfo->putp)(modp->listnrq->next, bp);
275: }
276:
277: /*
278: * Receive message for listener
279: */
280: dklstnr(modp, bp)
281: register struct block *bp;
282: struct dkmodule *modp;
283: {
284: register struct dialin *dialp;
285: register i;
286: register struct queue *listnrq = modp->listnrq;
287: register struct rdk *dkp;
288:
289: dialp = (struct dialin *)bp->rptr;
290: switch (dialp->type) {
291:
292: case T_CHG:
293: i = dialp->param1;
294: if (i <= 0 || i >= modp->hi - modp->lo) {
295: dkstat.chgstrange++;
296: if (dialp->srv)
297: dkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
298: freeb(bp);
299: return(1);
300: }
301: switch (dialp->srv) {
302:
303: case D_CLOSE: /* remote shutdown */
304: switch (modp->dkstate[i]) {
305:
306: case DKRCLOSE:
307: dkstat.notclosed++;
308: case DKOPEN:
309: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
310: break;
311:
312: case DKLCLOSE:
313: case DKCLOSED:
314: dkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
315: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
316: break;
317: }
318: break;
319:
320: case D_ISCLOSED:
321: switch (modp->dkstate[i]) {
322:
323: case DKLCLOSE:
324: case DKCLOSED:
325: putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
326: break;
327:
328: case DKOPEN:
329: case DKRCLOSE:
330: dkstat.isclosed++;
331: break;
332: }
333: break;
334:
335: case D_ENQ:
336: dkmesg(modp, T_CHG, D_ENQANS, 0, i, modp->dkstate[i]);
337: break;
338: }
339: freeb(bp);
340: return(1);
341:
342: case T_REPLY: /* CMC sends reply; find, and hand to process */
343: i = dialp->param0;
344: if (i < 0 || i >= modp->hi - modp->lo)
345: return(0);
346: for (dkp=rdk; dkp<&rdk[NDKRAW]; dkp++) {
347: if (dkp->module==modp && dkp->chan==i) {
348: bp->class |= S_DELIM;
349: (*dkp->q->next->qinfo->putp)(dkp->q->next, bp);
350: return(1);
351: }
352: }
353: return(0);
354:
355: default:
356: return(0);
357: }
358: }
359:
360: /*
361: * 15-second timer
362: * -- should look at dkmod->type, so different
363: * listeners can coexist
364: */
365: dktimer()
366: {
367: register i;
368: register struct dkmodule *dkp;
369:
370: for (dkp = dkmod; dkp < &dkmod[dkmodcnt]; dkp++) {
371: if (dkp->listnrq && dkp->type == CMCLD) {
372: dkmesg(dkp, T_LSTNR, 0, 0, 0, 0);
373: for (i=dkp->hi - dkp->lo - 1; i >= 0; --i)
374: if (dkp->dkstate[i] == DKLCLOSE)
375: dkmesg(dkp, T_CHG, D_CLOSE, 0, i, 0);
376: }
377: }
378: timeout(dktimer, (caddr_t)NULL, 15*HZ);
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.