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