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