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