|
|
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: if (kk->modp->listnrq) ! 378: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, chan); ! 379: dkstat.closepack++; ! 380: } ! 381: freeb(bp); ! 382: return; ! 383: } ! 384: dkstat.input += bp->wptr - bp->rptr; ! 385: if ((q->next->flag & QFULL) == 0) ! 386: (*q->next->qinfo->putp)(q->next, bp); ! 387: else ! 388: freeb(bp); ! 389: } ! 390: ! 391: /* ! 392: * refresh our supply of input buffers ! 393: */ ! 394: kbibufs(kk) ! 395: register struct kbkmc *kk; ! 396: { ! 397: register struct block *bp; ! 398: register int i; ! 399: register struct kbdesc *dxp; ! 400: register uaddr_t ua; ! 401: ! 402: i = kk->rwp; ! 403: while (kk->rbytes < MINRBYTES) { ! 404: if (RNEXT(i) == kk->rrp) /* all descriptors used */ ! 405: break; ! 406: if ((bp = allocb(RBSIZE)) == NULL) ! 407: break; ! 408: if ((kk->rmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) { ! 409: printf("kb no rcv map\n"); ! 410: freeb(bp); ! 411: break; ! 412: } ! 413: kk->rblock[i] = bp; ! 414: ua = ubadrptr(kk->ubno, bp, kk->rmap[i]); ! 415: dxp = &kk->rring[i]; ! 416: dxp->loaddr = ua; ! 417: dxp->len = bp->wptr - bp->lim; /* negative length */ ! 418: dxp->flag = ((ua>>16)<<DXSHIFT)|DVALID; ! 419: kk->rbytes += bp->lim - bp->wptr; ! 420: i = RNEXT(i); ! 421: } ! 422: kk->rwp = i; ! 423: } ! 424: ! 425: /* ! 426: * put procedure for output ! 427: */ ! 428: kbput(q, bp) ! 429: struct queue *q; ! 430: register struct block *bp; ! 431: { ! 432: register struct kb *dkp; ! 433: register struct kbkmc *kk; ! 434: register int i; ! 435: register struct device *reg; ! 436: register struct kbdesc *dxp; ! 437: uaddr_t ua; ! 438: int s; ! 439: ! 440: dkp = (struct kb *)q->ptr; ! 441: kk = &kbkmc[KBNO]; ! 442: switch (bp->type) { ! 443: ! 444: case M_IOCTL: ! 445: switch (stiocom(bp)) { ! 446: case DIOCNXCL: ! 447: dkp->flag &=~ DKXCL; ! 448: bp->wptr = bp->rptr; ! 449: bp->type = M_IOCACK; ! 450: break; ! 451: ! 452: case KIOCINIT: ! 453: /* eventually, reset things here */ ! 454: ! 455: default: ! 456: bp->type = M_IOCNAK; ! 457: break; ! 458: } ! 459: qreply(q, bp); ! 460: return; ! 461: ! 462: case M_CTL: ! 463: case M_DATA: ! 464: if (bp->rptr == bp->wptr) { ! 465: freeb(bp); ! 466: return; ! 467: } ! 468: s = spl5(); ! 469: i = kk->xwp - kk->xrp; ! 470: if (i < 0) ! 471: i += XRING; ! 472: if (i > XRING/2) ! 473: kbxscan(kk); ! 474: if (XNEXT(kk->xwp) == kk->xrp) { /* no desc available? */ ! 475: splx(s); ! 476: printf("kb xmt ch%d lost block\n", dkp->chan); ! 477: freeb(bp); ! 478: return; ! 479: } ! 480: i = kk->xwp; ! 481: kk->xwp = XNEXT(i); ! 482: if ((kk->xmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) { ! 483: splx(s); ! 484: printf("kb xmt ch%d no map\n", dkp->chan); ! 485: freeb(bp); ! 486: return; ! 487: } ! 488: #if TRACE ! 489: trace('x', (i<<24)|(dkp->chan<<16)|bp->type, bp->wptr - bp->rptr, ! 490: *(int *)bp->rptr); ! 491: #endif ! 492: kk->xblock[i] = bp; ! 493: ua = ubadrptr(kk->ubno, bp, kk->xmap[i]); ! 494: dxp = &kk->xring[i]; ! 495: dxp->loaddr = ua; ! 496: dxp->len = bp->rptr - bp->wptr; /* negative length */ ! 497: dxp->chan = dkp->chan; ! 498: dxp->flag = (ua>>16)<<DXSHIFT; ! 499: if (bp->type != M_DATA) ! 500: dxp->flag |= DSCTL; ! 501: reg = kk->addr; ! 502: dxp->flag |= DVALID; ! 503: if ((reg->xhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) { ! 504: if (i != kk->xrp) ! 505: kbxscan(kk); ! 506: if (kk->xwp != kk->xrp) { /* maybe it finished it off -- unlikely */ ! 507: ua = kk->xrua + kk->xrp * sizeof(struct kbdesc); ! 508: reg->xlo = ua; ! 509: reg->xhi = ((ua>>16)<<CXSHIFT); ! 510: } ! 511: } ! 512: else /* debug */ ! 513: kbxnst++; /* debug */ ! 514: dkstat.output += bp->wptr - bp->rptr; ! 515: splx(s); ! 516: return; ! 517: ! 518: case M_PRICTL: ! 519: switch (*bp->rptr) { ! 520: case DKMCLOSE: ! 521: i = bp->rptr[1]; ! 522: if (i < kbcnt) { ! 523: if (kbstate[i] == DKOPEN) { ! 524: kbstate[i] = DKRCLOSE; ! 525: putctl(kb[i].dkrq->next, M_HANGUP); ! 526: } else if (kbstate[i] == DKLCLOSE) ! 527: kbstate[i] = DKCLOSED; ! 528: } ! 529: freeb(bp); ! 530: return; ! 531: ! 532: case DKMXINIT: ! 533: i = bp->rptr[1]; ! 534: if (i < kbcnt && kbstate[i] == DKOPEN) ! 535: (*kb[i].dkrq->next->qinfo->putp)(kb[i].dkrq->next, bp); ! 536: else ! 537: freeb(bp); ! 538: return; ! 539: ! 540: default: ! 541: freeb(bp); ! 542: return; ! 543: } ! 544: ! 545: default: ! 546: freeb(bp); ! 547: return; ! 548: } ! 549: } ! 550: ! 551: /* ! 552: * clean up finished transmit buffers ! 553: * call at spl5 ! 554: */ ! 555: ! 556: kbxscan(kk) ! 557: register struct kbkmc *kk; ! 558: { ! 559: register int i; ! 560: ! 561: for (i = kk->xrp; i != kk->xwp; i = XNEXT(i)) { ! 562: if (kk->xring[i].flag & DVALID) ! 563: break; ! 564: if (kk->xblock[i] == NULL) ! 565: panic("kbxscan"); ! 566: ubmfree(kk->ubno, kk->xmap[i]); ! 567: kk->xmap[i] = 0; ! 568: freeb(kk->xblock[i]); ! 569: kk->xblock[i] = NULL; ! 570: } ! 571: kk->xrp = i; ! 572: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.