|
|
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: extern struct kb kb[]; ! 52: extern int kbcnt; ! 53: extern 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: dkstat.closepack++; ! 263: freeb(bp); ! 264: return; ! 265: } ! 266: dkstat.input += bp->wptr - bp->rptr; ! 267: if ((q->next->flag & QFULL) == 0) ! 268: (*q->next->qinfo->putp)(q->next, bp); ! 269: else ! 270: freeb(bp); ! 271: } ! 272: ! 273: /* ! 274: * start the next input buffer ! 275: */ ! 276: kbistart(kk) ! 277: register struct kbkmc *kk; ! 278: { ! 279: register struct device *reg; ! 280: register int sts; ! 281: register struct block *bp; ! 282: register int n; ! 283: register uaddr_t ua; ! 284: ! 285: if ((reg = kk->addr) == NULL) ! 286: return; ! 287: if (kk->ibuf) ! 288: return; ! 289: for (sts = 0, n = 0; n < STALL; n++) { ! 290: if ((reg->cmd & CGO) == 0 ! 291: && (sts = reg->sts) & SRRDY) ! 292: break; ! 293: /* delay to free up unibus? */ ! 294: } ! 295: if ((sts & SRRDY) == 0) { ! 296: printf("kb rcv not ready, sts %o cmd %o\n", reg->sts, reg->cmd); ! 297: panic("kbistart"); ! 298: return; ! 299: } ! 300: if (sts & SERROR) ! 301: printf("kb err, sts %o\n", sts&0177777); ! 302: if ((bp = allocb(DKISIZE)) == NULL ! 303: || (kk->imap = ubmblk(kk->ubno, bp, 0)) == 0) { ! 304: panic("kbistart can't alloc\n"); /* later printf */ ! 305: if (bp) ! 306: freeb(bp); ! 307: return; ! 308: } ! 309: kk->ibuf = bp; ! 310: if ((int)bp->rptr & 01) ! 311: bp->rptr++; ! 312: kk->iaddr = ua = ubadrptr(kk->ubno, bp, kk->imap); ! 313: reg->bc = bp->rptr - bp->lim; /* sic - negative count */ ! 314: reg->ba = ua; ! 315: n = (ua >> 16) << XASHIFT; ! 316: n &= CXA; ! 317: n |= CIE|CRCV; ! 318: reg->cmd = n; ! 319: } ! 320: ! 321: /* ! 322: * put procedure for output ! 323: */ ! 324: kbput(q, bp) ! 325: struct queue *q; ! 326: register struct block *bp; ! 327: { ! 328: register struct kb *dkp; ! 329: register struct kbkmc *kk; ! 330: register int n; ! 331: register struct device *reg; ! 332: register int sts; ! 333: int s; ! 334: ! 335: dkp = (struct kb *)q->ptr; ! 336: kk = &kbkmc[KBNO]; ! 337: switch (bp->type) { ! 338: ! 339: case M_IOCTL: ! 340: switch (stiocom(bp)) { ! 341: case DIOCNXCL: ! 342: dkp->flag &=~ DKXCL; ! 343: bp->wptr = bp->rptr; ! 344: bp->type = M_IOCACK; ! 345: break; ! 346: ! 347: case KIOCINIT: ! 348: /* eventually, reset things here */ ! 349: ! 350: default: ! 351: bp->type = M_IOCNAK; ! 352: break; ! 353: } ! 354: qreply(q, bp); ! 355: return; ! 356: ! 357: case M_CTL: ! 358: case M_DATA: ! 359: if (bp->rptr == bp->wptr) { ! 360: freeb(bp); ! 361: return; ! 362: } ! 363: dkstat.output += bp->wptr - bp->rptr; ! 364: s = spl5(); ! 365: reg = kk->addr; ! 366: for (sts = 0, n = 0; n < STALL; n++) { ! 367: if ((reg->cmd & CGO) == 0 ! 368: && (sts = reg->sts) & SXRDY) ! 369: break; ! 370: DELAY(40); /* get off the UNIBUS */ ! 371: } ! 372: if ((sts & SXRDY) == 0) { /* n >= STALL */ ! 373: printf("kb xmit not ready, sts %o, cmd %o\n", sts, reg->cmd); ! 374: splx(s); ! 375: freeb(bp); ! 376: return; ! 377: } ! 378: if (sts & SERROR) ! 379: printf("kb err, sts %o\n", sts&0177777); ! 380: ubmflush(kk->ubno, ubmpath(kk->omap)); ! 381: if (kk->obuf) { ! 382: freeb(kk->obuf); ! 383: kk->obuf = NULL; ! 384: } ! 385: n = bp->wptr - bp->rptr; ! 386: kk->oaddr = ubmaddr(kk->ubno, bp->rptr, n, kk->omap); ! 387: reg->bc = -n; ! 388: reg->ba = kk->oaddr; ! 389: n = (kk->oaddr >> 16)<<XASHIFT; ! 390: n &= CXA; ! 391: n |= dkp->chan; ! 392: if (bp->type == M_DATA) ! 393: n |= CSEND; ! 394: else ! 395: n |= CSCTL; ! 396: reg->cmd = n; ! 397: kk->obuf = bp; ! 398: splx(s); ! 399: return; ! 400: ! 401: case M_PRICTL: ! 402: switch (*bp->rptr) { ! 403: case DKMCLOSE: ! 404: n = bp->rptr[1]; ! 405: if (n < kbcnt) { ! 406: if (kbstate[n] == DKOPEN) { ! 407: kbstate[n] = DKRCLOSE; ! 408: putctl(kb[n].dkrq->next, M_HANGUP); ! 409: } else if (kbstate[n] == DKLCLOSE) ! 410: kbstate[n] = DKCLOSED; ! 411: } ! 412: freeb(bp); ! 413: return; ! 414: ! 415: case DKMXINIT: ! 416: n = bp->rptr[1]; ! 417: if (n < kbcnt && kbstate[n] == DKOPEN) ! 418: (*kb[n].dkrq->next->qinfo->putp)(kb[n].dkrq->next, bp); ! 419: else ! 420: freeb(bp); ! 421: return; ! 422: ! 423: default: ! 424: freeb(bp); ! 425: return; ! 426: } ! 427: ! 428: default: ! 429: freeb(bp); ! 430: return; ! 431: } ! 432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.