|
|
1.1 ! root 1: /* ! 2: * Datakit driver ! 3: */ ! 4: #include "sys/param.h" ! 5: #include "sys/systm.h" ! 6: #include "sys/stream.h" ! 7: #include "sys/dkio.h" ! 8: #include "sys/ubaddr.h" ! 9: #include "sys/conf.h" ! 10: #include "sys/dk.h" ! 11: #include "sys/dkstat.h" ! 12: #include "sys/dkmod.h" ! 13: ! 14: #define SAFETY 1 /* turn off doubtful speed hack */ ! 15: ! 16: struct device { ! 17: unsigned short csr; ! 18: unsigned short dko; ! 19: unsigned short dki; ! 20: }; ! 21: ! 22: struct device *DKADDR; /* assume one addr for now */ ! 23: ! 24: extern struct dk dk[]; ! 25: extern int dkcnt; ! 26: extern char dkstate[]; ! 27: ! 28: #define DKXCL 01 ! 29: ! 30: int dkalive; ! 31: struct dkstat dkstat; ! 32: extern struct dkmodule dkmod[]; ! 33: struct dkmodule *dkmodp; ! 34: ! 35: /* ! 36: * Hardware control bits ! 37: */ ! 38: #define DKTENAB 0100 ! 39: #define DKRENAB 040 ! 40: #define ENABS (DKRENAB) ! 41: #define DKTDONE 0200 ! 42: #define DKRDONE 0100000 ! 43: #define D_OSEQ 0 ! 44: #define D_READ 01 ! 45: #define D_WRITE 02 ! 46: #define D_XPACK 03 ! 47: #define DKMARK 01000 ! 48: #define DKDATA 0400 ! 49: #define DKPARITY 0100000 ! 50: ! 51: #define DKOPKT 16 /* biggest output packet */ ! 52: #define DKIPKT 16 /* biggest input packet */ ! 53: #define DKISML 16 /* smallest interesting allocation */ ! 54: #define DKITHRES 200 ! 55: ! 56: int dkclose(), dkput(); ! 57: long dkopen(); ! 58: ! 59: static struct qinit dkrinit = { noput, NULL, dkopen, dkclose, 0, 0 }; ! 60: struct qinit dkwinit = { dkput, NULL, dkopen, dkclose, 0, 0 }; ! 61: struct streamtab dkinfo = { &dkrinit, &dkwinit }; ! 62: struct cdevsw dkcdev = cstrinit(&dkinfo); ! 63: extern struct ubaddr dkaddr[]; ! 64: ! 65: /* ! 66: * open DK channel ! 67: */ ! 68: long ! 69: dkopen(q, dev) ! 70: register struct queue *q; ! 71: register dev_t dev; ! 72: { ! 73: register struct dk *dkp; ! 74: static opened, badtime; ! 75: register chan; ! 76: ! 77: chan = minor(dev); ! 78: if (chan<=0 || chan>=dkcnt) ! 79: return(0); ! 80: if (!opened) { ! 81: register i; ! 82: ! 83: if ((DKADDR = (struct device *)ubaddr(&dkaddr[0])) == NULL ! 84: || badaddr(DKADDR, 2)) { ! 85: printf("dk0 absent\n"); ! 86: return (0); ! 87: } ! 88: DKADDR->csr = D_OSEQ; ! 89: DKADDR->dko = 0; /* Clear fifo's */ ! 90: i = 256; /* sanity count */ ! 91: DELAY(1000); /* wait for board to reset */ ! 92: do { ! 93: if (DKADDR->csr & DKTDONE) { ! 94: dkalive = 0; ! 95: if (time > badtime + 300) { ! 96: badtime = time; ! 97: printf("DK interface bad\n"); ! 98: } ! 99: return(0); ! 100: } ! 101: } while (--i); ! 102: if ((dkmodp = dkmodall(dev, 0, dkcnt)) == NULL) ! 103: return (0); ! 104: dkmodp->dkstate = dkstate; ! 105: dkalive = 1; ! 106: for (dkp = dk, i = 0; i < dkcnt; dkp++, i++) ! 107: dkp->chan = i; ! 108: DKADDR->csr = ENABS; ! 109: opened++; ! 110: dkrecover(chan); ! 111: } ! 112: dkp = &dk[chan]; ! 113: if (dkstate[chan] != DKCLOSED) { /* already open */ ! 114: if (dkp->flag & DKXCL) { ! 115: /* printf("DK XCL chan %d state %o flag %o\n", chan, dkstate[chan], dkp->flag); */ ! 116: return(0); ! 117: } ! 118: if (dkstate[chan] != DKOPEN) { ! 119: /* printf("DK XCL chan %d state %o flag %o\n", chan, dkstate[chan], dkp->flag); */ ! 120: return(0); /* closing channels can't reopen */ ! 121: } ! 122: return(1); ! 123: } ! 124: dkp->dkrq = q; ! 125: q->ptr = (caddr_t)dkp; ! 126: WR(q)->ptr = (caddr_t)dkp; ! 127: dkp->flag = DKXCL; ! 128: dkp->icnt = 0; ! 129: dkp->isize = 0; ! 130: dkp->ibuf = 0; ! 131: dkp->ialloc = DKISML; ! 132: dkstate[chan] = DKOPEN; ! 133: return(1); ! 134: } ! 135: ! 136: /* ! 137: * Timer to recover from lost interrupt condition. ! 138: */ ! 139: dkrecover(dev) ! 140: dev_t dev; ! 141: { ! 142: register int ps = spl5(); ! 143: ! 144: if (DKADDR->csr & DKRDONE) ! 145: dk1int(dev); ! 146: splx(ps); ! 147: ! 148: timeout(dkrecover, (caddr_t)dev, HZ/2); ! 149: } ! 150: ! 151: /* ! 152: * close DK channel ! 153: */ ! 154: dkclose(q) ! 155: register struct queue *q; ! 156: { ! 157: register struct dk *dkp; ! 158: register struct block *bp; ! 159: ! 160: dkp = (struct dk *)q->ptr; ! 161: dkp->dkrq = NULL; ! 162: dkp->flag = 0; ! 163: if (dkstate[dkp->chan] == DKRCLOSE || dkmodp->listnrq==NULL) ! 164: dkstate[dkp->chan] = DKCLOSED; ! 165: else if (dkstate[dkp->chan] == DKOPEN) ! 166: dkstate[dkp->chan] = DKLCLOSE; ! 167: if (dkmodp->listnrq) ! 168: putctl2(RD(dkmodp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan); ! 169: if (dkp->ibuf) ! 170: freeb(dkp->ibuf); ! 171: while ((bp = dkp->ofirst) != NULL) { ! 172: dkp->ofirst = bp->next; ! 173: freeb(bp); ! 174: } ! 175: dkp->ibuf = 0; ! 176: } ! 177: ! 178: /* ! 179: * DK receiver interrupt. ! 180: */ ! 181: ! 182: #define PUTIN(bp, q) {\ ! 183: dkstat.input += (bp)->wptr - (bp)->rptr;\ ! 184: if (((q)->next->flag & QFULL) == 0)\ ! 185: (*(q)->next->qinfo->putp)(q->next, bp);\ ! 186: else\ ! 187: freeb(bp);\ ! 188: } ! 189: ! 190: #define DKSIZUP(dkp) {\ ! 191: if (dkp->isize > DKITHRES) {\ ! 192: dkp->ialloc = dkp->isize;\ ! 193: dkp->icnt = 3;\ ! 194: } else if (--dkp->icnt <= 0) {\ ! 195: dkp->icnt = 0;\ ! 196: dkp->ialloc = DKISML;\ ! 197: }\ ! 198: dkp->isize = 0;\ ! 199: } ! 200: ! 201: dk1int(dev) ! 202: { ! 203: register struct queue *q; ! 204: register struct block *bp; ! 205: register struct dk *dkp; ! 206: register struct device *reg; ! 207: register c, nbytes; ! 208: register sane, chan; ! 209: register struct block **bpp; ! 210: struct block *blist[DKIPKT+2]; ! 211: ! 212: if ((reg = DKADDR) == NULL) ! 213: return; ! 214: c = 0; ! 215: dkp = NULL; ! 216: while (reg->csr & DKRDONE) { ! 217: reg->csr = D_READ|ENABS; ! 218: if ((c & DKMARK) == 0) { ! 219: /* Search for channel number */ ! 220: sane = 256; ! 221: do { ! 222: c = reg->dki; ! 223: if (c & DKMARK || --sane==0) ! 224: break; ! 225: } while (reg->csr & DKRDONE); ! 226: } ! 227: if ((c & DKMARK) == 0) { ! 228: dkstat.markflt++; ! 229: continue; ! 230: } ! 231: if ((c & DKPARITY) == 0) { ! 232: dkstat.markparity++; ! 233: c = 0; ! 234: continue; ! 235: } ! 236: /* check channel */ ! 237: chan = c & 0777; ! 238: if (dkp && dkp->chan != chan) { ! 239: if ((bp = dkp->ibuf) != NULL) ! 240: PUTIN(bp, q); ! 241: DKSIZUP(dkp); ! 242: dkp->ibuf = NULL; ! 243: } ! 244: if (chan == 0 || chan >= dkcnt || (q = dk[chan].dkrq)==NULL) { ! 245: if (chan>0 && chan<dkcnt) ! 246: dkstat.closepack++; ! 247: else if (chan == 0) ! 248: dkstat.pack0++; ! 249: else ! 250: dkstat.packstrange++; ! 251: for (nbytes=0; nbytes<DKIPKT; nbytes++) { ! 252: c = reg->dki; ! 253: if (c & DKMARK) ! 254: break; ! 255: } ! 256: continue; ! 257: } ! 258: dkp = (struct dk *)q->ptr; ! 259: if ((bp = dkp->ibuf) == NULL ! 260: && (bp = allocb(dkp->ialloc)) == NULL) ! 261: return; ! 262: bpp = blist; ! 263: for (nbytes=0; nbytes<DKIPKT; nbytes++) { ! 264: #ifdef SAFETY ! 265: if ((reg->csr&DKRDONE) == 0) ! 266: break; ! 267: #endif ! 268: c = reg->dki; ! 269: if ((c&(DKPARITY|DKMARK|DKDATA)) == (DKPARITY|DKDATA)) { ! 270: if (bp->wptr >= bp->lim) { ! 271: *bpp++ = bp; ! 272: if ((bp = allocb(DKISML)) == NULL) ! 273: break; ! 274: } ! 275: *bp->wptr++ = c; ! 276: dkp->isize++; ! 277: continue; ! 278: } ! 279: /* ! 280: * control or error ! 281: */ ! 282: if (c & DKMARK) { ! 283: dkstat.shortpack++; ! 284: break; ! 285: } ! 286: if ((c & DKPARITY) == 0) { ! 287: dkstat.parity++; ! 288: break; ! 289: } ! 290: if ((c & 0377) == 0) /* control-null */ ! 291: continue; ! 292: if (bp->wptr > bp->rptr) { ! 293: *bpp++ = bp; ! 294: if ((bp = allocb(DKISML)) == NULL) ! 295: break; ! 296: } ! 297: bp->type = M_CTL; ! 298: *bp->wptr++ = c; ! 299: } ! 300: if (bpp == blist && bp->type == M_DATA) { ! 301: dkp->ibuf = bp; ! 302: continue; ! 303: } ! 304: *bpp++ = bp; ! 305: *bpp = NULL; ! 306: bpp = blist; ! 307: while ((bp = *bpp++) != NULL) ! 308: PUTIN(bp, q); ! 309: DKSIZUP(dkp); ! 310: dkp->ibuf = NULL; ! 311: } ! 312: if (dkp && (bp = dkp->ibuf) != NULL) { ! 313: PUTIN(bp, q); ! 314: DKSIZUP(dkp); ! 315: dkp->ibuf = NULL; ! 316: } ! 317: } ! 318: ! 319: /* ! 320: * DK put procedure ! 321: */ ! 322: dkput(q, bp) ! 323: register struct queue *q; ! 324: register struct block *bp; ! 325: { ! 326: register n; ! 327: register bn; ! 328: int s; ! 329: register struct device *reg = DKADDR; ! 330: register struct dk *dkp; ! 331: ! 332: dkp = (struct dk *)q->ptr; ! 333: if (dkp == NULL) { ! 334: freeb(bp); ! 335: return; ! 336: } ! 337: switch (bp->type) { ! 338: ! 339: case M_IOCTL: ! 340: bp->type = M_IOCACK; ! 341: switch (stiocom(bp)) { ! 342: case DIOCNXCL: ! 343: dkp->flag &=~ DKXCL; ! 344: bp->wptr = bp->rptr; ! 345: bp->type = M_IOCACK; ! 346: break; ! 347: ! 348: default: ! 349: bp->type = M_IOCNAK; ! 350: break; ! 351: } ! 352: qreply(q, bp); ! 353: return; ! 354: ! 355: case M_CTL: ! 356: case M_DATA: ! 357: s = spl6(); ! 358: bp->next = NULL; ! 359: if (dkp->ofirst == NULL) ! 360: dkp->ofirst = bp; ! 361: else ! 362: dkp->olast->next = bp; ! 363: dkp->olast = bp; ! 364: if ((bp->class&S_DELIM)==0 || dkalive == 0) { ! 365: splx(s); ! 366: return; ! 367: } ! 368: /* ! 369: * S_DELIM: ! 370: * push out data ! 371: */ ! 372: n = DKOPKT; ! 373: reg->csr = D_WRITE + ENABS; ! 374: reg->dko = DKMARK + dkp->chan; ! 375: while ((bp = dkp->ofirst) != NULL) { ! 376: dkp->ofirst = bp->next; ! 377: if (bp->wptr == bp->rptr) { ! 378: freeb(bp); ! 379: continue; ! 380: } ! 381: dkstat.output += bp->wptr - bp->rptr; ! 382: if (n <= 0) { ! 383: reg->csr = D_XPACK + ENABS; ! 384: reg->dko = 0; ! 385: n = DKOPKT; ! 386: reg->csr = D_WRITE + ENABS; ! 387: reg->dko = DKMARK + dkp->chan; ! 388: } ! 389: --n; ! 390: reg->dko = *bp->rptr++ | ((bp->type==M_DATA)?DKDATA:0); ! 391: while ((bn = bp->wptr - bp->rptr) > 0) { ! 392: if (bn > n) ! 393: bn = n; ! 394: n -= bn; ! 395: while (--bn >= 0) ! 396: reg->dko = *bp->rptr++ | DKDATA; ! 397: if (n <= 0) { ! 398: reg->csr = D_XPACK + ENABS; ! 399: reg->dko = 0; ! 400: n = DKOPKT; ! 401: reg->csr = D_WRITE + ENABS; ! 402: reg->dko = DKMARK + dkp->chan; ! 403: } ! 404: } ! 405: freeb(bp); ! 406: } ! 407: reg->csr = D_XPACK + ENABS; ! 408: reg->dko = 0; ! 409: splx(s); ! 410: return; ! 411: ! 412: case M_PRICTL: ! 413: switch (*bp->rptr) { ! 414: case DKMCLOSE: ! 415: n = bp->rptr[1]; ! 416: if (n < dkcnt) { ! 417: if (dkstate[n] == DKOPEN) { ! 418: dkstate[n] = DKRCLOSE; ! 419: putctl(dk[n].dkrq->next, M_HANGUP); ! 420: } else if (dkstate[n] == DKLCLOSE) ! 421: dkstate[n] = DKCLOSED; ! 422: } ! 423: freeb(bp); ! 424: return; ! 425: ! 426: case DKMXINIT: ! 427: n = bp->rptr[1]; ! 428: if (n < dkcnt && dkstate[n] == DKOPEN) ! 429: (*dk[n].dkrq->next->qinfo->putp)(dk[n].dkrq->next, bp); ! 430: else ! 431: freeb(bp); ! 432: return; ! 433: ! 434: default: ! 435: freeb(bp); ! 436: return; ! 437: } ! 438: ! 439: default: ! 440: freeb(bp); ! 441: return; ! 442: } ! 443: } ! 444: ! 445: /* ! 446: * transmit interrupt ! 447: */ ! 448: ! 449: dk0int(dev) ! 450: int dev; ! 451: { ! 452: printf("dk%d xmit stray\n", dev); ! 453: } ! 454: ! 455: /* ! 456: * unibus reset ! 457: */ ! 458: dkreset() ! 459: { ! 460: if (DKADDR) ! 461: DKADDR->csr = ENABS; ! 462: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.