|
|
1.1 ! root 1: /* ! 2: * massbus adapter subroutines ! 3: * this version for comet ! 4: */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/nxaddr.h" ! 8: #include "sys/mbaddr.h" ! 9: #include "sys/mba.h" ! 10: #include "sys/pte.h" ! 11: #include "sys/buf.h" ! 12: ! 13: /* ! 14: * hardware things ! 15: */ ! 16: ! 17: #define NMAP 256 ! 18: ! 19: struct mbaregs { ! 20: long conf; /* configuration register; unused */ ! 21: long cr; /* control register */ ! 22: long sr; /* status register */ ! 23: long va; /* address */ ! 24: long bcr; /* count */ ! 25: long _junk0[251]; /* pad up to 0x400 */ ! 26: long devreg[MBAUNITS][32]; ! 27: long map[NMAP]; ! 28: }; ! 29: ! 30: #define mbas devreg[0][4] /* attn summary reg; same in all devs */ ! 31: ! 32: #define CRINIT 01 /* cr -- adapter init */ ! 33: #define CRIE 04 /* cr -- interrupt enable */ ! 34: ! 35: #define MRV 0x80000000 /* map register -- valid bit */ ! 36: #define MPAGE 0x001fffff /* map register -- page number */ ! 37: /* really only 15 bits on comet; others seem to read 0 */ ! 38: ! 39: /* ! 40: * things from mkconf ! 41: */ ! 42: ! 43: extern int mbacnt; ! 44: extern struct mba mba[]; ! 45: extern struct nxaddr mbaaddr[]; ! 46: extern int (*mbavec[][MBAUNITS])(); ! 47: extern char mbaid[][MBAUNITS]; ! 48: ! 49: #define BUSY 01 /* this mba already transferring */ ! 50: #define INIT 02 /* did init */ ! 51: ! 52: #define NOUNIT (-1) /* in mbq */ ! 53: ! 54: caddr_t ! 55: mbaddr(ap) ! 56: register struct mbaddr *ap; ! 57: { ! 58: register struct mba *mp; ! 59: ! 60: if (ap->mbno < 0 || ap->mbno >= mbacnt) ! 61: return (0); ! 62: if (ap->unit < 0 || ap->unit >= MBAUNITS) ! 63: return (0); ! 64: mp = &mba[ap->mbno]; ! 65: if ((mp->flags & INIT) == 0 ! 66: && mbinit(ap->mbno) == 0) ! 67: return (0); ! 68: return ((caddr_t)mp->addr->devreg[ap->unit]); ! 69: } ! 70: ! 71: mbinit(dev) ! 72: int dev; ! 73: { ! 74: register struct mba *mp; ! 75: ! 76: mp = &mba[dev]; ! 77: if ((mp->addr = (struct mbaregs *)nxaddr(&mbaaddr[dev])) == NULL ! 78: || badaddr(&mp->addr->conf, sizeof(long))) { ! 79: printf("mba%d absent\n"); ! 80: return (0); ! 81: } ! 82: mp->addr->cr = CRINIT; ! 83: mp->addr->cr = CRIE; ! 84: mp->first = NOUNIT; ! 85: mp->flags |= INIT; ! 86: return (1); ! 87: } ! 88: ! 89: /* ! 90: * enqueue a transfer for this unit; ! 91: * if not busy, start ! 92: * if there's already a transfer for this unit, something is wrong ! 93: */ ! 94: mbstart(ap, bp, go) ! 95: register struct mbaddr *ap; ! 96: register struct buf *bp; ! 97: int (*go)(); ! 98: { ! 99: register struct mba *mp; ! 100: register int i; ! 101: ! 102: mp = &mba[ap->mbno]; ! 103: i = ap->unit; ! 104: if (mp->mbuf[i]) ! 105: panic("mbstart"); ! 106: if (mp->first == NOUNIT) ! 107: mp->first = i; ! 108: else ! 109: mp->mbq[mp->last] = i; ! 110: mp->last = i; ! 111: mp->mbq[i] = NOUNIT; ! 112: mp->mbuf[i] = bp; ! 113: mp->xstart[i] = go; ! 114: if ((mp->flags & BUSY) == 0) ! 115: mbxfer(mp); ! 116: } ! 117: ! 118: /* ! 119: * really start a transfer ! 120: * mp->lastoff is saved only for mbadj ! 121: */ ! 122: ! 123: mbxfer(mp) ! 124: register struct mba *mp; ! 125: { ! 126: register struct mbaregs *reg; ! 127: register struct pte *p; ! 128: register long *map; ! 129: register long size; ! 130: register struct buf *bp; ! 131: ! 132: if (mp->first == NOUNIT) ! 133: return; ! 134: reg = mp->addr; ! 135: bp = mp->mbuf[mp->first]; ! 136: mp->lastoff = (long)bp->b_un.b_addr & PGOFSET; ! 137: size = btoc(bp->b_bcount); ! 138: if (mp->lastoff) ! 139: size++; ! 140: if (size >= NMAP) ! 141: size = NMAP-1; /* tough */ ! 142: p = btopte(bp); ! 143: map = reg->map; ! 144: while (--size >= 0) ! 145: *map++ = p++->pg_pfnum | MRV; ! 146: *map = 0; /* safety */ ! 147: reg->bcr = -bp->b_bcount; ! 148: reg->va = mp->lastoff; ! 149: mp->flags |= BUSY; ! 150: (*mp->xstart[mp->first])(bp); ! 151: } ! 152: ! 153: /* ! 154: * cheats needed for ECC correction ! 155: * must be called from interrupt code, ! 156: * before we've started another transfer ! 157: */ ! 158: ! 159: long ! 160: mbcuraddr(ap) ! 161: struct mbaddr *ap; ! 162: { ! 163: return (mba[ap->mbno].addr->va); ! 164: } ! 165: ! 166: /* ! 167: * adjust registers to redo current transfer ! 168: * somewhere in the middle, but not where we were ! 169: * new buffer address is original+aoff; ! 170: * new count is as given ! 171: */ ! 172: ! 173: mbadj(ap, aoff, count) ! 174: struct mbaddr *ap; ! 175: int aoff, count; ! 176: { ! 177: register struct mba *mp; ! 178: register struct mbaregs *reg; ! 179: ! 180: mp = &mba[ap->mbno]; ! 181: reg = mp->addr; ! 182: reg->bcr = -count; ! 183: reg->va = aoff + mp->lastoff; ! 184: } ! 185: ! 186: /* ! 187: * xfer was restarted ! 188: * just mark adapter busy again, and delicately re-insert us in the queue ! 189: * -- we know we were at the head before ! 190: */ ! 191: ! 192: mbcontin(ap) ! 193: register struct mbaddr *ap; ! 194: { ! 195: register struct mba *mp; ! 196: ! 197: mp = &mba[ap->mbno]; ! 198: mp->flags |= BUSY; ! 199: mp->mbq[ap->unit] = mp->first; ! 200: mp->first = ap->unit; ! 201: } ! 202: ! 203: /* ! 204: * get, put a byte in MASSBUS space ! 205: */ ! 206: ! 207: static long ! 208: mbphys(ap, addr) ! 209: struct mbaddr *ap; ! 210: long addr; ! 211: { ! 212: register long m; ! 213: register int pg; ! 214: register struct mba *mp; ! 215: ! 216: mp = &mba[ap->mbno]; ! 217: if (mp->addr == 0) ! 218: panic("mbphys"); ! 219: pg = addr / NBPG; ! 220: if (pg >= NMAP) ! 221: return (-1); ! 222: m = mp->addr->map[pg]; ! 223: if ((m & MRV) == 0) ! 224: return (-1); ! 225: return ((m & MPAGE) * NBPG + addr % NBPG); ! 226: } ! 227: ! 228: mbgetc(ap, addr) ! 229: struct mbaddr *ap; ! 230: long addr; ! 231: { ! 232: register long phys; ! 233: ! 234: phys = mbphys(ap, addr); ! 235: if (phys < 0) ! 236: return (-1); ! 237: return (phgetc(phys)); ! 238: } ! 239: ! 240: int ! 241: mbputc(ap, addr, c) ! 242: struct mbaddr *ap; ! 243: long addr; ! 244: char c; ! 245: { ! 246: register long phys; ! 247: ! 248: phys = mbphys(ap, addr); ! 249: if (phys < 0) ! 250: return (-1); ! 251: return (phputc(phys, c)); ! 252: } ! 253: ! 254: /* ! 255: * massbus interrupt ! 256: * if a transfer in progress, call the driver ! 257: * if attn, call drivers for that too ! 258: * it is up to the driver to clear attn ! 259: * (but for convenience, we promise to tell them what bit to clear) ! 260: */ ! 261: ! 262: mba0int(dev) ! 263: register int dev; ! 264: { ! 265: register struct mba *mp; ! 266: register struct mbaregs *reg; ! 267: register long sr; ! 268: register int as, i; ! 269: ! 270: if (dev < 0 || dev > mbacnt ! 271: || (mp = &mba[dev], (mp->flags & INIT)) == 0) { ! 272: mbshutup(dev); ! 273: return; ! 274: } ! 275: reg = mp->addr; ! 276: sr = reg->sr; ! 277: reg->sr = sr; /* clear attn and error latches */ ! 278: as = reg->mbas&0377; ! 279: if (mp->flags & BUSY) { ! 280: i = mp->first; ! 281: mp->mbuf[i] = NULL; ! 282: mp->first = mp->mbq[i]; ! 283: mp->flags &=~ BUSY; ! 284: (*mbavec[dev][i])(mbaid[dev][i], sr, (-reg->bcr)&0xffff, as & (1<<i)); ! 285: as &=~ (1<<i); ! 286: } ! 287: for (i = 0; as; i++, as >>= 1) ! 288: if (as & 01) ! 289: (*mbavec[dev][i])(mbaid[dev][i], 0, 0, 1<<i); ! 290: if ((mp->flags & BUSY) == 0) ! 291: mbxfer(mp); ! 292: } ! 293: ! 294: /* ! 295: * mbavec for non-existent drives points here ! 296: */ ! 297: ! 298: mbastray(dev) ! 299: int dev; ! 300: { ! 301: printf("mba%d drive %d stray attn\n", dev>>3, dev&07); ! 302: } ! 303: ! 304: /* ! 305: * here if didn't expect mba interrupt ! 306: * might just be a leftover ATTN from a previous boot; ! 307: * not necessarily cleared ! 308: */ ! 309: ! 310: mbshutup(dev) ! 311: int dev; ! 312: { ! 313: register struct mbaregs *reg; ! 314: ! 315: if (dev < 0 || dev >= mbacnt ! 316: || (reg = (struct mbaregs *)nxaddr(&mbaaddr[dev])) == NULL ! 317: || badaddr(®->conf, sizeof(long))) { ! 318: printf("mb%d: unacceptable interrupt\n", dev); ! 319: return; /* and probably get stuck forever */ ! 320: } ! 321: reg->cr = CRINIT; /* quiet, please */ ! 322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.