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