|
|
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: return(0); ! 116: if (dkstate[chan] != DKOPEN) ! 117: return(0); /* closing channels can't reopen */ ! 118: return(1); ! 119: } ! 120: dkp->dkrq = q; ! 121: q->ptr = (caddr_t)dkp; ! 122: WR(q)->ptr = (caddr_t)dkp; ! 123: dkp->flag = DKXCL; ! 124: dkp->icnt = 0; ! 125: dkp->isize = 0; ! 126: dkp->ibuf = 0; ! 127: dkp->ialloc = DKISML; ! 128: dkstate[chan] = DKOPEN; ! 129: return(1); ! 130: } ! 131: ! 132: /* ! 133: * Timer to recover from lost interrupt condition. ! 134: */ ! 135: dkrecover(dev) ! 136: dev_t dev; ! 137: { ! 138: register int ps = spl5(); ! 139: ! 140: if (DKADDR->csr & DKRDONE) ! 141: dk1int(dev); ! 142: splx(ps); ! 143: ! 144: timeout(dkrecover, (caddr_t)dev, HZ/2); ! 145: } ! 146: ! 147: /* ! 148: * close DK channel ! 149: */ ! 150: dkclose(q) ! 151: register struct queue *q; ! 152: { ! 153: register struct dk *dkp; ! 154: register struct block *bp; ! 155: ! 156: dkp = (struct dk *)q->ptr; ! 157: dkp->dkrq = NULL; ! 158: dkp->flag = 0; ! 159: if (dkstate[dkp->chan] == DKRCLOSE || dkmodp->listnrq==NULL) ! 160: dkstate[dkp->chan] = DKCLOSED; ! 161: else if (dkstate[dkp->chan] == DKOPEN) ! 162: dkstate[dkp->chan] = DKLCLOSE; ! 163: if (dkmodp->listnrq) ! 164: putctl2(RD(dkmodp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan); ! 165: if (dkp->ibuf) ! 166: freeb(dkp->ibuf); ! 167: while ((bp = dkp->ofirst) != NULL) { ! 168: dkp->ofirst = bp->next; ! 169: freeb(bp); ! 170: } ! 171: dkp->ibuf = 0; ! 172: } ! 173: ! 174: /* ! 175: * DK receiver interrupt. ! 176: */ ! 177: ! 178: #define PUTIN(bp, q) {\ ! 179: dkstat.input += (bp)->wptr - (bp)->rptr;\ ! 180: if (((q)->next->flag & QFULL) == 0)\ ! 181: (*(q)->next->qinfo->putp)(q->next, bp);\ ! 182: else\ ! 183: freeb(bp);\ ! 184: } ! 185: ! 186: #define DKSIZUP(dkp) {\ ! 187: if (dkp->isize > DKITHRES) {\ ! 188: dkp->ialloc = dkp->isize;\ ! 189: dkp->icnt = 3;\ ! 190: } else if (--dkp->icnt <= 0) {\ ! 191: dkp->icnt = 0;\ ! 192: dkp->ialloc = DKISML;\ ! 193: }\ ! 194: dkp->isize = 0;\ ! 195: } ! 196: ! 197: dk1int(dev) ! 198: { ! 199: register struct queue *q; ! 200: register struct block *bp; ! 201: register struct dk *dkp; ! 202: register struct device *reg; ! 203: register c, nbytes; ! 204: register sane, chan; ! 205: register struct block **bpp; ! 206: struct block *blist[DKIPKT+2]; ! 207: ! 208: if ((reg = DKADDR) == NULL) ! 209: return; ! 210: c = 0; ! 211: dkp = NULL; ! 212: while (reg->csr & DKRDONE) { ! 213: reg->csr = D_READ|ENABS; ! 214: if ((c & DKMARK) == 0) { ! 215: /* Search for channel number */ ! 216: sane = 256; ! 217: do { ! 218: c = reg->dki; ! 219: if (c & DKMARK || --sane==0) ! 220: break; ! 221: } while (reg->csr & DKRDONE); ! 222: } ! 223: if ((c & DKMARK) == 0) { ! 224: dkstat.markflt++; ! 225: continue; ! 226: } ! 227: if ((c & DKPARITY) == 0) { ! 228: dkstat.markparity++; ! 229: c = 0; ! 230: continue; ! 231: } ! 232: /* check channel */ ! 233: chan = c & 0777; ! 234: if (dkp && dkp->chan != chan) { ! 235: if ((bp = dkp->ibuf) != NULL) ! 236: PUTIN(bp, q); ! 237: DKSIZUP(dkp); ! 238: dkp->ibuf = NULL; ! 239: } ! 240: if (chan == 0 || chan >= dkcnt || (q = dk[chan].dkrq)==NULL) { ! 241: if (chan>0 && chan<dkcnt) { ! 242: if (dkmodp->listnrq) ! 243: putctl2(RD(dkmodp->listnrq), ! 244: M_PRICTL, DKMCLOSE, chan); ! 245: dkstat.closepack++; ! 246: } else if (chan == 0) ! 247: dkstat.pack0++; ! 248: else ! 249: dkstat.packstrange++; ! 250: for (nbytes=0; nbytes<DKIPKT; nbytes++) { ! 251: c = reg->dki; ! 252: if (c & DKMARK) ! 253: break; ! 254: } ! 255: continue; ! 256: } ! 257: dkp = (struct dk *)q->ptr; ! 258: if ((bp = dkp->ibuf) == NULL ! 259: && (bp = allocb(dkp->ialloc)) == NULL) ! 260: return; ! 261: bpp = blist; ! 262: for (nbytes=0; nbytes<DKIPKT; nbytes++) { ! 263: #ifdef SAFETY ! 264: if ((reg->csr&DKRDONE) == 0) ! 265: break; ! 266: #endif ! 267: c = reg->dki; ! 268: if ((c&(DKPARITY|DKMARK|DKDATA)) == (DKPARITY|DKDATA)) { ! 269: if (bp->wptr >= bp->lim) { ! 270: *bpp++ = bp; ! 271: if ((bp = allocb(DKISML)) == NULL) ! 272: break; ! 273: } ! 274: *bp->wptr++ = c; ! 275: dkp->isize++; ! 276: continue; ! 277: } ! 278: /* ! 279: * control or error ! 280: */ ! 281: if (c & DKMARK) { ! 282: dkstat.shortpack++; ! 283: break; ! 284: } ! 285: if ((c & DKPARITY) == 0) { ! 286: dkstat.parity++; ! 287: break; ! 288: } ! 289: if ((c & 0377) == 0) /* control-null */ ! 290: continue; ! 291: if (bp->wptr > bp->rptr) { ! 292: *bpp++ = bp; ! 293: if ((bp = allocb(DKISML)) == NULL) ! 294: break; ! 295: } ! 296: bp->type = M_CTL; ! 297: *bp->wptr++ = c; ! 298: } ! 299: if (bpp == blist && bp->type == M_DATA) { ! 300: dkp->ibuf = bp; ! 301: continue; ! 302: } ! 303: *bpp++ = bp; ! 304: *bpp = NULL; ! 305: bpp = blist; ! 306: while ((bp = *bpp++) != NULL) ! 307: PUTIN(bp, q); ! 308: DKSIZUP(dkp); ! 309: dkp->ibuf = NULL; ! 310: } ! 311: if (dkp && (bp = dkp->ibuf) != NULL) { ! 312: PUTIN(bp, q); ! 313: DKSIZUP(dkp); ! 314: dkp->ibuf = NULL; ! 315: } ! 316: } ! 317: ! 318: /* ! 319: * DK put procedure ! 320: */ ! 321: dkput(q, bp) ! 322: register struct queue *q; ! 323: register struct block *bp; ! 324: { ! 325: register n; ! 326: register bn; ! 327: int s; ! 328: register struct device *reg = DKADDR; ! 329: register struct dk *dkp; ! 330: ! 331: dkp = (struct dk *)q->ptr; ! 332: if (dkp == NULL) { ! 333: freeb(bp); ! 334: return; ! 335: } ! 336: switch (bp->type) { ! 337: ! 338: case M_IOCTL: ! 339: bp->type = M_IOCACK; ! 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: default: ! 348: bp->type = M_IOCNAK; ! 349: break; ! 350: } ! 351: qreply(q, bp); ! 352: return; ! 353: ! 354: case M_CTL: ! 355: case M_DATA: ! 356: s = spl6(); ! 357: bp->next = NULL; ! 358: if (dkp->ofirst == NULL) ! 359: dkp->ofirst = bp; ! 360: else ! 361: dkp->olast->next = bp; ! 362: dkp->olast = bp; ! 363: if ((bp->class&S_DELIM)==0 || dkalive == 0) { ! 364: splx(s); ! 365: return; ! 366: } ! 367: /* ! 368: * S_DELIM: ! 369: * push out data ! 370: */ ! 371: n = DKOPKT; ! 372: reg->csr = D_WRITE + ENABS; ! 373: reg->dko = DKMARK + dkp->chan; ! 374: while ((bp = dkp->ofirst) != NULL) { ! 375: dkp->ofirst = bp->next; ! 376: if (bp->wptr == bp->rptr) { ! 377: freeb(bp); ! 378: continue; ! 379: } ! 380: dkstat.output += bp->wptr - bp->rptr; ! 381: if (n <= 0) { ! 382: reg->csr = D_XPACK + ENABS; ! 383: reg->dko = 0; ! 384: n = DKOPKT; ! 385: reg->csr = D_WRITE + ENABS; ! 386: reg->dko = DKMARK + dkp->chan; ! 387: } ! 388: --n; ! 389: reg->dko = *bp->rptr++ | ((bp->type==M_DATA)?DKDATA:0); ! 390: while ((bn = bp->wptr - bp->rptr) > 0) { ! 391: if (bn > n) ! 392: bn = n; ! 393: n -= bn; ! 394: while (--bn >= 0) ! 395: reg->dko = *bp->rptr++ | DKDATA; ! 396: if (n <= 0) { ! 397: reg->csr = D_XPACK + ENABS; ! 398: reg->dko = 0; ! 399: n = DKOPKT; ! 400: reg->csr = D_WRITE + ENABS; ! 401: reg->dko = DKMARK + dkp->chan; ! 402: } ! 403: } ! 404: freeb(bp); ! 405: } ! 406: reg->csr = D_XPACK + ENABS; ! 407: reg->dko = 0; ! 408: splx(s); ! 409: return; ! 410: ! 411: case M_PRICTL: ! 412: switch (*bp->rptr) { ! 413: case DKMCLOSE: ! 414: n = bp->rptr[1]; ! 415: if (n < dkcnt) { ! 416: if (dkstate[n] == DKOPEN) { ! 417: dkstate[n] = DKRCLOSE; ! 418: putctl(dk[n].dkrq->next, M_HANGUP); ! 419: } else if (dkstate[n] == DKLCLOSE) ! 420: dkstate[n] = DKCLOSED; ! 421: } ! 422: freeb(bp); ! 423: return; ! 424: ! 425: case DKMXINIT: ! 426: n = bp->rptr[1]; ! 427: if (n < dkcnt && dkstate[n] == DKOPEN) ! 428: (*dk[n].dkrq->next->qinfo->putp)(dk[n].dkrq->next, bp); ! 429: else ! 430: freeb(bp); ! 431: return; ! 432: ! 433: default: ! 434: freeb(bp); ! 435: return; ! 436: } ! 437: ! 438: default: ! 439: freeb(bp); ! 440: return; ! 441: } ! 442: } ! 443: ! 444: /* ! 445: * transmit interrupt ! 446: */ ! 447: ! 448: dk0int(dev) ! 449: int dev; ! 450: { ! 451: printf("dk%d xmit stray\n", dev); ! 452: } ! 453: ! 454: /* ! 455: * unibus reset ! 456: */ ! 457: dkreset() ! 458: { ! 459: if (DKADDR) ! 460: DKADDR->csr = ENABS; ! 461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.