|
|
1.1 ! root 1: /* ! 2: * simple two-stream kmc datakit driver ! 3: * -- assumes it is the first kmc, and only one allowed for now ! 4: * (the latter not severe, as 256 channels are permitted) ! 5: */ ! 6: #include "sys/param.h" ! 7: #include "sys/stream.h" ! 8: #include "sys/dkio.h" ! 9: #include "sys/ubaddr.h" ! 10: #include "sys/conf.h" ! 11: #include "sys/kb.h" ! 12: #include "sys/kmc.h" ! 13: #include "sys/dkstat.h" ! 14: #include "sys/dkmod.h" ! 15: ! 16: #define TRACE 0 /* turn on to provoke tracing */ ! 17: ! 18: /* ! 19: * hardware stuff ! 20: */ ! 21: ! 22: struct device { ! 23: char ctl; /* control -- written by host */ ! 24: unsigned char sts; /* status -- written by device */ ! 25: short xlo; /* xmit descriptor, low address */ ! 26: short rlo; /* rcv descriptor, low address */ ! 27: char xhi, rhi; /* high addresses and flags */ ! 28: }; ! 29: ! 30: /* ! 31: * control bits ! 32: */ ! 33: #define CXIE 01 /* transmit interrupt enable */ ! 34: #define CRIE 02 /* receive interrupt enable */ ! 35: ! 36: /* ! 37: * status bits ! 38: */ ! 39: #define SERROR 0200 /* some error, usually NXM */ ! 40: ! 41: /* ! 42: * flags in xhi and rhi ! 43: */ ! 44: #define CNOADDR 0200 /* OK to give another descriptor address */ ! 45: #define CNODESC 0100 /* no descriptor being processed */ ! 46: #define CXA 014 /* high address bits */ ! 47: #define CXSHIFT 2 /* shift high bits this much */ ! 48: ! 49: /* ! 50: * descriptor flags ! 51: */ ! 52: #define DVALID 0200 /* valid descriptor for device */ ! 53: #define DCHAIN 020 /* `buffer' is a fresh descriptor address */ ! 54: #define DXA 014 /* high buffer address bits */ ! 55: #define DSCTL 01 /* first char of buffer is a control char */ ! 56: ! 57: #define DXSHIFT 2 /* shift high addr bits this much */ ! 58: ! 59: /* ! 60: * per-channel stuff ! 61: */ ! 62: struct kb kb[]; ! 63: extern int kbcnt; ! 64: char kbstate[]; ! 65: ! 66: /* ! 67: * kb flags ! 68: */ ! 69: #define DKXCL 01 /* exclusive open */ ! 70: #define DKXWANT 02 /* output pending this channel */ ! 71: ! 72: /* ! 73: * per-controller stuff; ! 74: * always just one for now ! 75: */ ! 76: ! 77: struct kbkmc kbkmc[1]; ! 78: #define KBNO 0 /* always this kb for now */ ! 79: ! 80: /* ! 81: * kbkmc flags ! 82: */ ! 83: #define INIT 01 ! 84: ! 85: /* ! 86: * illicit linkage to other datakit code ! 87: */ ! 88: ! 89: struct dkstat dkstat; ! 90: ! 91: /* ! 92: * illicit linkage to kmc driver ! 93: */ ! 94: ! 95: extern struct kmc kmc[]; ! 96: extern struct ubaddr kmcaddr[]; ! 97: extern int kmccnt; ! 98: #define KNO 0 /* kmc0 is ours, by fiat */ ! 99: ! 100: #define RBSIZE 1024 /* desired receive buffer size */ ! 101: #define MINRBYTES 4096 /* desired total receive buffer */ ! 102: ! 103: #define XNEXT(i) ((i)>=XRING-1?0:(i)+1) ! 104: #define RNEXT(i) ((i)>=RRING-1?0:(i)+1) ! 105: ! 106: long kbopen(); ! 107: int kbclose(), kbput(), kbosrv(); ! 108: ! 109: static struct qinit kbrinit = { nodev, NULL, kbopen, kbclose, 0, 0 }; ! 110: struct qinit kbwinit = { kbput, NULL, kbopen, kbclose, 1500, 600 }; ! 111: struct streamtab kbinfo = { &kbrinit, &kbwinit }; ! 112: struct cdevsw kbcdev = cstrinit(&kbinfo); ! 113: ! 114: /* ! 115: * open DK channel ! 116: */ ! 117: long ! 118: kbopen(q, dev) ! 119: register struct queue *q; ! 120: register dev_t dev; ! 121: { ! 122: register struct kb *dkp; ! 123: register struct kbkmc *kk; ! 124: register chan; ! 125: ! 126: chan = minor(dev); ! 127: if (chan<=0 || chan>=kbcnt) ! 128: return(0); ! 129: kk = &kbkmc[KBNO]; ! 130: if ((kk->flags & INIT) == 0) { ! 131: if ((kk->modp = dkmodall(dev, 0, kbcnt)) == NULL) ! 132: return (0); ! 133: kk->modp->dkstate = kbstate; ! 134: if (kbinit(kk) == 0) ! 135: return (0); ! 136: kk->flags |= INIT; ! 137: } ! 138: dkp = &kb[chan]; ! 139: if (kbstate[chan] != DKCLOSED) { /* already open */ ! 140: if (dkp->flag & DKXCL) ! 141: return(0); ! 142: if (kbstate[chan] != DKOPEN) ! 143: return(0); /* closing channels can't reopen */ ! 144: return(1); ! 145: } ! 146: dkp->dkrq = q; ! 147: q->ptr = (caddr_t)dkp; ! 148: WR(q)->ptr = (caddr_t)dkp; ! 149: WR(q)->flag |= QNOENB|QBIGB; ! 150: dkp->flag = DKXCL; ! 151: dkp->chan = chan; ! 152: kbstate[chan] = DKOPEN; ! 153: return(1); ! 154: } ! 155: ! 156: /* ! 157: * make sure kmc is alive; ! 158: * init data structures once ! 159: */ ! 160: kbinit(kk) ! 161: register struct kbkmc *kk; ! 162: { ! 163: register struct kmc *kp; ! 164: struct device *reg; ! 165: uaddr_t ua; ! 166: extern kbintr(), kbreset(); ! 167: ! 168: kk->kno = KNO; ! 169: kk->ubno = kmcaddr[KNO].ubno; /* cheat */ ! 170: kp = &kmc[kk->kno]; ! 171: if ((reg = kp->k_addr) == 0) ! 172: return (0); ! 173: if ((kk->ringmap = ubmalloc(kk->ubno, sizeof(kk->rings), 0)) == 0) { ! 174: printf("kb init no map\n"); ! 175: return (0); ! 176: } ! 177: ua = ubmaddr(kk->ubno, (caddr_t)&kk->rings, sizeof(kk->rings), kk->ringmap); ! 178: kk->xrua = ua + ((caddr_t)kk->xring - (caddr_t)&kk->rings); ! 179: kk->rrua = ua + ((caddr_t)kk->rring - (caddr_t)&kk->rings); ! 180: kp->k_rint = kbintr; ! 181: kp->k_xint = kbintr; ! 182: kp->k_reset = kbreset; ! 183: kk->addr = reg; ! 184: kbreset(KNO); ! 185: return (1); ! 186: } ! 187: ! 188: /* ! 189: * called when, e.g., kmc is reloaded ! 190: */ ! 191: kbreset(kno) ! 192: int kno; ! 193: { ! 194: register struct kbkmc *kk; ! 195: register int i; ! 196: register struct device *reg; ! 197: ! 198: kk = &kbkmc[kno]; ! 199: bzero((caddr_t)&kk->rings, sizeof(kk->rings)); ! 200: kk->rrp = 0; ! 201: kk->rwp = 0; ! 202: kk->xrp = 0; ! 203: kk->xwp = 0; ! 204: for (i = 0; i < XRING; i++) { ! 205: if (kk->xmap[i]) { ! 206: ubmfree(kk->ubno, kk->xmap[i]); ! 207: kk->xmap[i] = 0; ! 208: } ! 209: if (kk->xblock[i]) { ! 210: freeb(kk->xblock[i]); ! 211: kk->xblock[i] = 0; ! 212: } ! 213: } ! 214: kk->xring[XRING].loaddr = kk->xrua; ! 215: kk->xring[XRING].flag = DVALID|DCHAIN|((kk->xrua>>16)<<DXSHIFT); ! 216: for (i = 0; i < RRING; i++) { ! 217: if (kk->rmap[i]) { ! 218: ubmfree(kk->ubno, kk->rmap[i]); ! 219: kk->rmap[i] = 0; ! 220: } ! 221: if (kk->rblock[i]) { ! 222: freeb(kk->rblock[i]); ! 223: kk->rblock[i] = 0; ! 224: } ! 225: } ! 226: kk->rring[RRING].loaddr = kk->rrua; ! 227: kk->rring[RRING].flag = DVALID|DCHAIN|((kk->rrua>>16)<<DXSHIFT); ! 228: kk->rbytes = 0; ! 229: reg = kk->addr; ! 230: reg->ctl = CRIE; ! 231: i = spl5(); ! 232: kbibufs(kk); ! 233: reg->rlo = kk->rrua; /* kk->rring[0] */ ! 234: reg->rhi = (kk->rrua>>16)<<CXSHIFT; ! 235: splx(i); ! 236: } ! 237: ! 238: /* ! 239: * close DK channel ! 240: */ ! 241: kbclose(q) ! 242: register struct queue *q; ! 243: { ! 244: register struct kb *dkp; ! 245: register struct kbkmc *kk; ! 246: ! 247: kk = &kbkmc[KBNO]; ! 248: dkp = (struct kb *)q->ptr; ! 249: if (dkp == NULL) ! 250: panic("kbclose"); ! 251: dkp->dkrq = NULL; ! 252: dkp->flag = 0; ! 253: if (kbstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL) ! 254: kbstate[dkp->chan] = DKCLOSED; ! 255: else if (kbstate[dkp->chan] == DKOPEN) ! 256: kbstate[dkp->chan] = DKLCLOSE; ! 257: if (kk->modp->listnrq) ! 258: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan); ! 259: } ! 260: ! 261: /* ! 262: * interrupt ! 263: * receive any blocks that have arrived; ! 264: * reload receive buffers; ! 265: * clean up finished transmit buffers ! 266: * restart receiver or transmitter if needed ! 267: */ ! 268: ! 269: int kbxrst; /* debugging count */ ! 270: int kbxnst; /* debugging count */ ! 271: ! 272: kbintr(dev) ! 273: { ! 274: register struct kbkmc *kk; ! 275: register struct device *reg; ! 276: register int i; ! 277: register uaddr_t ua; ! 278: ! 279: kk = &kbkmc[dev]; ! 280: if ((reg = kk->addr) == NULL) ! 281: return; ! 282: #if NOTDEF /* straighten out protocol */ ! 283: i = reg->sts; ! 284: if (i & SERROR) { ! 285: reg->sts = 0; ! 286: printf("kb sts %o\n", i); ! 287: } ! 288: #endif ! 289: for (i = kk->rrp; i != kk->rwp; i = RNEXT(i)) { ! 290: if (kk->rring[i].flag & DVALID) ! 291: break; ! 292: kbrcv(kk, i); ! 293: } ! 294: if (kk->rbytes < MINRBYTES) ! 295: kbibufs(kk); ! 296: if ((reg->rhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) { ! 297: /* ! 298: * receiver has stopped, but may have finished ! 299: * another block or two since the loop above ! 300: */ ! 301: for (; i != kk->rwp; i = RNEXT(i)) { ! 302: if (kk->rring[i].flag & DVALID) ! 303: break; ! 304: kbrcv(kk, i); ! 305: } ! 306: if (kk->rbytes < MINRBYTES) ! 307: kbibufs(kk); ! 308: if (kk->rwp != i) { /* safety check */ ! 309: ua = kk->rrua + i * sizeof(struct kbdesc); ! 310: reg->rlo = ua; ! 311: reg->rhi = (ua>>16)<<CXSHIFT; ! 312: } ! 313: } ! 314: kk->rrp = i; ! 315: i = reg->xhi; ! 316: if (kk->xrp != kk->xwp) ! 317: kbxscan(kk); ! 318: if ((i & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC) ! 319: && kk->xrp != kk->xwp) { ! 320: ua = kk->xrua + kk->xrp * sizeof(struct kbdesc); ! 321: reg->xlo = ua; ! 322: reg->xhi = (ua>>16)<<CXSHIFT; ! 323: kbxrst++; ! 324: } ! 325: } ! 326: ! 327: /* ! 328: * receive a block ! 329: */ ! 330: kbrcv(kk, i) ! 331: register struct kbkmc *kk; ! 332: register int i; ! 333: { ! 334: register struct kbdesc *dxp; ! 335: register struct queue *q; ! 336: register int chan; ! 337: register struct block *bp; ! 338: struct block *xbp; ! 339: ! 340: dxp = &kk->rring[i]; ! 341: #if TRACE ! 342: trace('i', (i<<24)|(dxp->chan<<16)|dxp->flag, -dxp->len, ! 343: *(int *)(kk->rblock[i]->rptr)); ! 344: #endif ! 345: if (kk->rmap[i] == 0) ! 346: panic("kbrcv"); ! 347: ubmfree(kk->ubno, kk->rmap[i]); ! 348: kk->rmap[i] = 0; ! 349: bp = kk->rblock[i]; ! 350: kk->rblock[i] = NULL; ! 351: kk->rbytes -= bp->lim - bp->wptr; ! 352: bp->wptr = bp->lim + dxp->len; /* negative residual length */ ! 353: if (dxp->flag & DSCTL) { ! 354: /* ! 355: * special hack to save big blocks ! 356: */ ! 357: if (bp->wptr == bp->rptr + 1 ! 358: && (xbp = allocb(1)) != NULL) { ! 359: *xbp->wptr++ = *bp->rptr; ! 360: freeb(bp); ! 361: bp = xbp; ! 362: } ! 363: bp->type = M_CTL; ! 364: } ! 365: if (bp->wptr <= bp->base || bp->wptr > bp->lim) { ! 366: printf("kb ch%d bad len %d\n", dxp->chan, -dxp->len); ! 367: freeb(bp); ! 368: return; ! 369: } ! 370: chan = dxp->chan; ! 371: if (chan == 0 || chan >= kbcnt || (q = kb[chan].dkrq) == NULL) { ! 372: if (chan == 0) ! 373: dkstat.pack0++; ! 374: else if (chan >= kbcnt) ! 375: dkstat.packstrange++; ! 376: else ! 377: dkstat.closepack++; ! 378: freeb(bp); ! 379: return; ! 380: } ! 381: dkstat.input += bp->wptr - bp->rptr; ! 382: if ((q->next->flag & QFULL) == 0) ! 383: (*q->next->qinfo->putp)(q->next, bp); ! 384: else ! 385: freeb(bp); ! 386: } ! 387: ! 388: /* ! 389: * refresh our supply of input buffers ! 390: */ ! 391: kbibufs(kk) ! 392: register struct kbkmc *kk; ! 393: { ! 394: register struct block *bp; ! 395: register int i; ! 396: register struct kbdesc *dxp; ! 397: register uaddr_t ua; ! 398: ! 399: i = kk->rwp; ! 400: while (kk->rbytes < MINRBYTES) { ! 401: if (RNEXT(i) == kk->rrp) /* all descriptors used */ ! 402: break; ! 403: if ((bp = allocb(RBSIZE)) == NULL) ! 404: break; ! 405: if ((kk->rmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) { ! 406: printf("kb no rcv map\n"); ! 407: freeb(bp); ! 408: break; ! 409: } ! 410: kk->rblock[i] = bp; ! 411: ua = ubadrptr(kk->ubno, bp, kk->rmap[i]); ! 412: dxp = &kk->rring[i]; ! 413: dxp->loaddr = ua; ! 414: dxp->len = bp->wptr - bp->lim; /* negative length */ ! 415: dxp->flag = ((ua>>16)<<DXSHIFT)|DVALID; ! 416: kk->rbytes += bp->lim - bp->wptr; ! 417: i = RNEXT(i); ! 418: } ! 419: kk->rwp = i; ! 420: } ! 421: ! 422: /* ! 423: * put procedure for output ! 424: */ ! 425: kbput(q, bp) ! 426: struct queue *q; ! 427: register struct block *bp; ! 428: { ! 429: register struct kb *dkp; ! 430: register struct kbkmc *kk; ! 431: register int i; ! 432: register struct device *reg; ! 433: register struct kbdesc *dxp; ! 434: uaddr_t ua; ! 435: int s; ! 436: ! 437: dkp = (struct kb *)q->ptr; ! 438: kk = &kbkmc[KBNO]; ! 439: switch (bp->type) { ! 440: ! 441: case M_IOCTL: ! 442: switch (stiocom(bp)) { ! 443: case DIOCNXCL: ! 444: dkp->flag &=~ DKXCL; ! 445: bp->wptr = bp->rptr; ! 446: bp->type = M_IOCACK; ! 447: break; ! 448: ! 449: case KIOCINIT: ! 450: /* eventually, reset things here */ ! 451: ! 452: default: ! 453: bp->type = M_IOCNAK; ! 454: break; ! 455: } ! 456: qreply(q, bp); ! 457: return; ! 458: ! 459: case M_CTL: ! 460: case M_DATA: ! 461: if (bp->rptr == bp->wptr) { ! 462: freeb(bp); ! 463: return; ! 464: } ! 465: s = spl5(); ! 466: i = kk->xwp - kk->xrp; ! 467: if (i < 0) ! 468: i += XRING; ! 469: if (i > XRING/2) ! 470: kbxscan(kk); ! 471: if (XNEXT(kk->xwp) == kk->xrp) { /* no desc available? */ ! 472: splx(s); ! 473: printf("kb xmt ch%d lost block\n", dkp->chan); ! 474: freeb(bp); ! 475: return; ! 476: } ! 477: i = kk->xwp; ! 478: kk->xwp = XNEXT(i); ! 479: if ((kk->xmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) { ! 480: splx(s); ! 481: printf("kb xmt ch%d no map\n", dkp->chan); ! 482: freeb(bp); ! 483: return; ! 484: } ! 485: #if TRACE ! 486: trace('x', (i<<24)|(dkp->chan<<16)|bp->type, bp->wptr - bp->rptr, ! 487: *(int *)bp->rptr); ! 488: #endif ! 489: kk->xblock[i] = bp; ! 490: ua = ubadrptr(kk->ubno, bp, kk->xmap[i]); ! 491: dxp = &kk->xring[i]; ! 492: dxp->loaddr = ua; ! 493: dxp->len = bp->rptr - bp->wptr; /* negative length */ ! 494: dxp->chan = dkp->chan; ! 495: dxp->flag = (ua>>16)<<DXSHIFT; ! 496: if (bp->type != M_DATA) ! 497: dxp->flag |= DSCTL; ! 498: reg = kk->addr; ! 499: dxp->flag |= DVALID; ! 500: if ((reg->xhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) { ! 501: if (i != kk->xrp) ! 502: kbxscan(kk); ! 503: if (kk->xwp != kk->xrp) { /* maybe it finished it off -- unlikely */ ! 504: ua = kk->xrua + kk->xrp * sizeof(struct kbdesc); ! 505: reg->xlo = ua; ! 506: reg->xhi = ((ua>>16)<<CXSHIFT); ! 507: } ! 508: } ! 509: else /* debug */ ! 510: kbxnst++; /* debug */ ! 511: dkstat.output += bp->wptr - bp->rptr; ! 512: splx(s); ! 513: return; ! 514: ! 515: case M_PRICTL: ! 516: switch (*bp->rptr) { ! 517: case DKMCLOSE: ! 518: i = bp->rptr[1]; ! 519: if (i < kbcnt) { ! 520: if (kbstate[i] == DKOPEN) { ! 521: kbstate[i] = DKRCLOSE; ! 522: putctl(kb[i].dkrq->next, M_HANGUP); ! 523: } else if (kbstate[i] == DKLCLOSE) ! 524: kbstate[i] = DKCLOSED; ! 525: } ! 526: freeb(bp); ! 527: return; ! 528: ! 529: case DKMXINIT: ! 530: i = bp->rptr[1]; ! 531: if (i < kbcnt && kbstate[i] == DKOPEN) ! 532: (*kb[i].dkrq->next->qinfo->putp)(kb[i].dkrq->next, bp); ! 533: else ! 534: freeb(bp); ! 535: return; ! 536: ! 537: default: ! 538: freeb(bp); ! 539: return; ! 540: } ! 541: ! 542: default: ! 543: freeb(bp); ! 544: return; ! 545: } ! 546: } ! 547: ! 548: /* ! 549: * clean up finished transmit buffers ! 550: * call at spl5 ! 551: */ ! 552: ! 553: kbxscan(kk) ! 554: register struct kbkmc *kk; ! 555: { ! 556: register int i; ! 557: ! 558: for (i = kk->xrp; i != kk->xwp; i = XNEXT(i)) { ! 559: if (kk->xring[i].flag & DVALID) ! 560: break; ! 561: if (kk->xblock[i] == NULL) ! 562: panic("kbxscan"); ! 563: ubmfree(kk->ubno, kk->xmap[i]); ! 564: kk->xmap[i] = 0; ! 565: freeb(kk->xblock[i]); ! 566: kk->xblock[i] = NULL; ! 567: } ! 568: kk->xrp = i; ! 569: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.