|
|
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: /* ! 17: * hardware stuff ! 18: */ ! 19: ! 20: struct device { ! 21: short sts; /* written by KMC */ ! 22: short cmd; /* command and transmit chan -- written by host */ ! 23: short ba; /* low bus address -- written by host */ ! 24: short bc; /* negative buffer size -- written by host */ ! 25: }; ! 26: ! 27: /* ! 28: * status info ! 29: */ ! 30: #define SCOUNT 0xfff /* receive buffer resid count */ ! 31: #define SRRDY (020<<8) /* receive ready */ ! 32: #define SOK (040<<8) /* init ok */ ! 33: #define SERROR (0100<<8) /* transfer or other error */ ! 34: #define SXRDY (0200<<8) /* transmit ready */ ! 35: ! 36: /* ! 37: * commands ! 38: */ ! 39: #define CGO (01<<8) /* turned off when command read */ ! 40: #define CRCV (01<<8) /* here is a receive buffer */ ! 41: #define CSEND (03<<8) /* send this buffer of data */ ! 42: #define CSCTL (043<<8) /* send this data, first char is ctl */ ! 43: #define CIE (020<<8) /* interrupt after this command */ ! 44: #define CXA (014<<8) /* high address bits */ ! 45: #define XASHIFT 10 /* shift high address bits this much */ ! 46: ! 47: #define STALL 10000 /* max time to stall waiting for ready */ ! 48: /* ! 49: * per-channel stuff ! 50: */ ! 51: struct kb kb[]; ! 52: extern int kbcnt; ! 53: char kbstate[]; ! 54: ! 55: /* ! 56: * kb flags ! 57: */ ! 58: #define DKXCL 01 /* exclusive open */ ! 59: #define DKXWANT 02 /* output pending this channel */ ! 60: ! 61: /* ! 62: * per-controller stuff; ! 63: * always just one for now ! 64: */ ! 65: ! 66: struct kbkmc kbkmc[1]; ! 67: #define KBNO 0 /* always this kb for now */ ! 68: ! 69: /* ! 70: * kbkmc flags ! 71: */ ! 72: #define INIT 01 ! 73: ! 74: /* ! 75: * illicit linkage to other datakit code ! 76: */ ! 77: ! 78: struct dkstat dkstat; ! 79: ! 80: /* ! 81: * illicit linkage to kmc driver ! 82: */ ! 83: ! 84: extern struct kmc kmc[]; ! 85: extern struct ubaddr kmcaddr[]; ! 86: extern int kmccnt; ! 87: #define KNO 0 /* kmc0 is ours, by fiat */ ! 88: ! 89: #define DKISIZE 1024 /* preferred input buffer size */ ! 90: #define MAXOBUF 4096 /* max allowed output buffer -- for unibus map */ ! 91: ! 92: long kbopen(); ! 93: int kbclose(), kbput(), kbosrv(); ! 94: ! 95: static struct qinit kbrinit = { nodev, NULL, kbopen, kbclose, 0, 0 }; ! 96: struct qinit kbwinit = { kbput, NULL, kbopen, kbclose, 1500, 600 }; ! 97: struct streamtab kbinfo = { &kbrinit, &kbwinit }; ! 98: struct cdevsw kbcdev = cstrinit(&kbinfo); ! 99: ! 100: /* ! 101: * open DK channel ! 102: */ ! 103: long ! 104: kbopen(q, dev) ! 105: register struct queue *q; ! 106: register dev_t dev; ! 107: { ! 108: register struct kb *dkp; ! 109: register struct kbkmc *kk; ! 110: register chan; ! 111: ! 112: chan = minor(dev); ! 113: if (chan<=0 || chan>=kbcnt) ! 114: return(0); ! 115: kk = &kbkmc[KBNO]; ! 116: if ((kk->flags & INIT) == 0) { ! 117: if ((kk->modp = dkmodall(dev, 0, kbcnt)) == NULL) ! 118: return (0); ! 119: kk->modp->dkstate = kbstate; ! 120: if (kbinit(kk) == 0) ! 121: return (0); ! 122: kk->flags |= INIT; ! 123: } ! 124: dkp = &kb[chan]; ! 125: if (kbstate[chan] != DKCLOSED) { /* already open */ ! 126: if (dkp->flag & DKXCL) ! 127: return(0); ! 128: if (kbstate[chan] != DKOPEN) ! 129: return(0); /* closing channels can't reopen */ ! 130: return(1); ! 131: } ! 132: dkp->dkrq = q; ! 133: q->ptr = (caddr_t)dkp; ! 134: WR(q)->ptr = (caddr_t)dkp; ! 135: WR(q)->flag |= QNOENB|QBIGB; ! 136: dkp->flag = DKXCL; ! 137: dkp->chan = chan; ! 138: kbstate[chan] = DKOPEN; ! 139: return(1); ! 140: } ! 141: ! 142: /* ! 143: * make sure kmc is alive; ! 144: * init data structures once ! 145: */ ! 146: kbinit(kk) ! 147: register struct kbkmc *kk; ! 148: { ! 149: register struct kmc *kp; ! 150: register struct device *reg; ! 151: register int i; ! 152: extern kbintr(), kbreset(); ! 153: ! 154: kk->kno = KNO; ! 155: kk->ubno = kmcaddr[KNO].ubno; /* cheat */ ! 156: kp = &kmc[kk->kno]; ! 157: if ((reg = kp->k_addr) == 0) ! 158: return (0); ! 159: if ((reg->sts & SOK) == 0) ! 160: return (0); ! 161: if ((kk->omap = ubmalloc(kk->ubno, MAXOBUF, UBDP)) == 0) ! 162: return (0); ! 163: kp->k_rint = kbintr; ! 164: kp->k_xint = kbintr; ! 165: kp->k_reset = kbreset; ! 166: kk->addr = reg; ! 167: i = spl5(); ! 168: kbistart(kk); ! 169: splx(i); ! 170: return (1); ! 171: } ! 172: ! 173: /* ! 174: * called when, e.g., kmc is reloaded ! 175: */ ! 176: kbreset(kno) ! 177: int kno; ! 178: { ! 179: register struct kbkmc *kk; ! 180: register int s; ! 181: ! 182: kk = &kbkmc[KNO]; ! 183: if (kk->obuf) { ! 184: freeb(kk->obuf); ! 185: kk->obuf = NULL; ! 186: } ! 187: if (kk->imap) { ! 188: ubmfree(kk->ubno, kk->imap); ! 189: kk->imap = 0; ! 190: } ! 191: if (kk->ibuf) { ! 192: freeb(kk->ibuf); ! 193: kk->ibuf = NULL; ! 194: } ! 195: s = spl5(); ! 196: kbistart(kk); ! 197: splx(s); ! 198: } ! 199: ! 200: /* ! 201: * close DK channel ! 202: */ ! 203: kbclose(q) ! 204: register struct queue *q; ! 205: { ! 206: register struct kb *dkp; ! 207: register struct kbkmc *kk; ! 208: ! 209: kk = &kbkmc[KBNO]; ! 210: dkp = (struct kb *)q->ptr; ! 211: if (dkp == NULL) ! 212: panic("kbclose"); ! 213: dkp->dkrq = NULL; ! 214: dkp->flag = 0; ! 215: if (kbstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL) ! 216: kbstate[dkp->chan] = DKCLOSED; ! 217: else if (kbstate[dkp->chan] == DKOPEN) ! 218: kbstate[dkp->chan] = DKLCLOSE; ! 219: if (kk->modp->listnrq) ! 220: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan); ! 221: } ! 222: ! 223: /* ! 224: * interrupt -- receiver only ! 225: * try to short-circuit interrupts; ! 226: * data often comes in a large piece, followed by two small ones (URP trailer) ! 227: */ ! 228: ! 229: kbintr(dev) ! 230: { ! 231: register struct kbkmc *kk; ! 232: register struct block *bp; ! 233: register struct queue *q; ! 234: register int i; ! 235: ! 236: kk = &kbkmc[KBNO]; ! 237: if (kk->addr == NULL) ! 238: return; ! 239: i = kk->addr->sts; ! 240: if ((bp = kk->ibuf) == NULL) { /* shouldn't happen */ ! 241: kbistart(kk); ! 242: return; ! 243: } ! 244: ubmfree(kk->ubno, kk->imap); ! 245: kk->ibuf = NULL; ! 246: kbistart(kk); ! 247: i |= ~SCOUNT; /* crypto-sign-extend */ ! 248: if ((i & SCOUNT) == 0) ! 249: i = 0; /* overflow just means buffer full */ ! 250: bp->wptr = bp->lim + i; /* lim - residue */ ! 251: i = *bp->rptr; /* channel */ ! 252: bp->rptr++; ! 253: if (*bp->rptr) /* ctl flag */ ! 254: bp->type = M_CTL; ! 255: bp->rptr++; ! 256: if (i == 0 || i >= kbcnt || (q = kb[i].dkrq) == NULL) { ! 257: if (i == 0) ! 258: dkstat.pack0++; ! 259: else if (i >= kbcnt) ! 260: dkstat.packstrange++; ! 261: else { ! 262: if (kk->modp->listnrq) ! 263: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, i); ! 264: dkstat.closepack++; ! 265: } ! 266: freeb(bp); ! 267: return; ! 268: } ! 269: dkstat.input += bp->wptr - bp->rptr; ! 270: if ((q->next->flag & QFULL) == 0) ! 271: (*q->next->qinfo->putp)(q->next, bp); ! 272: else ! 273: freeb(bp); ! 274: } ! 275: ! 276: /* ! 277: * start the next input buffer ! 278: */ ! 279: kbistart(kk) ! 280: register struct kbkmc *kk; ! 281: { ! 282: register struct device *reg; ! 283: register int sts; ! 284: register struct block *bp; ! 285: register int n; ! 286: register uaddr_t ua; ! 287: ! 288: if ((reg = kk->addr) == NULL) ! 289: return; ! 290: if (kk->ibuf) ! 291: return; ! 292: for (sts = 0, n = 0; n < STALL; n++) { ! 293: if ((reg->cmd & CGO) == 0 ! 294: && (sts = reg->sts) & SRRDY) ! 295: break; ! 296: /* delay to free up unibus? */ ! 297: } ! 298: if ((sts & SRRDY) == 0) { ! 299: printf("kb rcv not ready, sts %o cmd %o\n", reg->sts, reg->cmd); ! 300: panic("kbistart"); ! 301: return; ! 302: } ! 303: if (sts & SERROR) ! 304: printf("kb err, sts %o\n", sts&0177777); ! 305: if ((bp = allocb(DKISIZE)) == NULL ! 306: || (kk->imap = ubmblk(kk->ubno, bp, 0)) == 0) { ! 307: panic("kbistart can't alloc\n"); /* later printf */ ! 308: if (bp) ! 309: freeb(bp); ! 310: return; ! 311: } ! 312: kk->ibuf = bp; ! 313: if ((int)bp->rptr & 01) ! 314: bp->rptr++; ! 315: kk->iaddr = ua = ubadrptr(kk->ubno, bp, kk->imap); ! 316: reg->bc = bp->rptr - bp->lim; /* sic - negative count */ ! 317: reg->ba = ua; ! 318: n = (ua >> 16) << XASHIFT; ! 319: n &= CXA; ! 320: n |= CIE|CRCV; ! 321: reg->cmd = n; ! 322: } ! 323: ! 324: /* ! 325: * put procedure for output ! 326: */ ! 327: kbput(q, bp) ! 328: struct queue *q; ! 329: register struct block *bp; ! 330: { ! 331: register struct kb *dkp; ! 332: register struct kbkmc *kk; ! 333: register int n; ! 334: register struct device *reg; ! 335: register int sts; ! 336: int s; ! 337: ! 338: dkp = (struct kb *)q->ptr; ! 339: kk = &kbkmc[KBNO]; ! 340: switch (bp->type) { ! 341: ! 342: case M_IOCTL: ! 343: switch (stiocom(bp)) { ! 344: case DIOCNXCL: ! 345: dkp->flag &=~ DKXCL; ! 346: bp->wptr = bp->rptr; ! 347: bp->type = M_IOCACK; ! 348: break; ! 349: ! 350: case KIOCINIT: ! 351: /* eventually, reset things here */ ! 352: ! 353: default: ! 354: bp->type = M_IOCNAK; ! 355: break; ! 356: } ! 357: qreply(q, bp); ! 358: return; ! 359: ! 360: case M_CTL: ! 361: case M_DATA: ! 362: if (bp->rptr == bp->wptr) { ! 363: freeb(bp); ! 364: return; ! 365: } ! 366: dkstat.output += bp->wptr - bp->rptr; ! 367: s = spl5(); ! 368: reg = kk->addr; ! 369: for (sts = 0, n = 0; n < STALL; n++) { ! 370: if ((reg->cmd & CGO) == 0 ! 371: && (sts = reg->sts) & SXRDY) ! 372: break; ! 373: DELAY(40); /* get off the UNIBUS */ ! 374: } ! 375: if ((sts & SXRDY) == 0) { /* n >= STALL */ ! 376: printf("kb xmit not ready, sts %o, cmd %o\n", sts, reg->cmd); ! 377: splx(s); ! 378: freeb(bp); ! 379: return; ! 380: } ! 381: if (sts & SERROR) ! 382: printf("kb err, sts %o\n", sts&0177777); ! 383: ubmflush(kk->ubno, ubmpath(kk->omap)); ! 384: if (kk->obuf) { ! 385: freeb(kk->obuf); ! 386: kk->obuf = NULL; ! 387: } ! 388: n = bp->wptr - bp->rptr; ! 389: kk->oaddr = ubmaddr(kk->ubno, bp->rptr, n, kk->omap); ! 390: reg->bc = -n; ! 391: reg->ba = kk->oaddr; ! 392: n = (kk->oaddr >> 16)<<XASHIFT; ! 393: n &= CXA; ! 394: n |= dkp->chan; ! 395: if (bp->type == M_DATA) ! 396: n |= CSEND; ! 397: else ! 398: n |= CSCTL; ! 399: reg->cmd = n; ! 400: kk->obuf = bp; ! 401: splx(s); ! 402: return; ! 403: ! 404: case M_PRICTL: ! 405: switch (*bp->rptr) { ! 406: case DKMCLOSE: ! 407: n = bp->rptr[1]; ! 408: if (n < kbcnt) { ! 409: if (kbstate[n] == DKOPEN) { ! 410: kbstate[n] = DKRCLOSE; ! 411: putctl(kb[n].dkrq->next, M_HANGUP); ! 412: } else if (kbstate[n] == DKLCLOSE) ! 413: kbstate[n] = DKCLOSED; ! 414: } ! 415: freeb(bp); ! 416: return; ! 417: ! 418: case DKMXINIT: ! 419: n = bp->rptr[1]; ! 420: if (n < kbcnt && kbstate[n] == DKOPEN) ! 421: (*kb[n].dkrq->next->qinfo->putp)(kb[n].dkrq->next, bp); ! 422: else ! 423: freeb(bp); ! 424: return; ! 425: ! 426: default: ! 427: freeb(bp); ! 428: return; ! 429: } ! 430: ! 431: default: ! 432: freeb(bp); ! 433: return; ! 434: } ! 435: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.