|
|
1.1 ! root 1: /* ! 2: * unibus adapter routines for DW780 ! 3: */ ! 4: ! 5: #include "sys/param.h" ! 6: #include "sys/ubaddr.h" ! 7: #include "sys/nexus.h" ! 8: #include "sys/nxaddr.h" ! 9: #include "sys/map.h" ! 10: #include "sys/uba.h" ! 11: #include "sys/pte.h" ! 12: #include "sys/vmparam.h" ! 13: ! 14: extern struct uba uba[]; ! 15: extern long ubavoff[]; ! 16: extern long *ubavreg[]; ! 17: extern long ubazvec[]; ! 18: extern struct nxaddr ubaaddr[]; ! 19: extern int ubacnt; ! 20: ! 21: /* ! 22: * 0x2000 bytes of nexus space, followed by the address window ! 23: */ ! 24: ! 25: #define NMAP 496 ! 26: #define NBDP 15 ! 27: ! 28: struct ubadev { ! 29: long cnfgr; /* configuration register */ ! 30: long uacr; /* adapter control */ ! 31: long uasr; /* adapter status */ ! 32: long dcr; /* diag stuff */ ! 33: long fmer; /* failed map entry */ ! 34: long fubar; /* failed unibus addr */ ! 35: long junk0[2]; ! 36: long bufsel[4]; ! 37: long brrvr[4]; /* vectors for each BR */ ! 38: long dpr[16]; /* data path registers */ ! 39: long junk1[0x1e0]; ! 40: long mreg[512]; /* unibus map registers; last 16 unused */ ! 41: long junk2[0x400]; ! 42: char ubspace[NXWSIZE]; ! 43: }; ! 44: ! 45: /* ! 46: * bits in uacr ! 47: */ ! 48: #define ADINIT 0x1 /* adapter init */ ! 49: #define CNFIE 0x4 /* config IE */ ! 50: #define SUEFIE 0x8 /* SBI to UNIBUS error IE */ ! 51: #define USEFIE 0x10 /* UNIBUS to SBI error IE */ ! 52: #define BRIE 0x20 /* BR interrupt enable */ ! 53: #define IFS 0x40 /* pass UNIBUS interrupts to SBI */ ! 54: ! 55: #define UBAIE (IFS|BRIE|USEFIE|SUEFIE|CNFIE) ! 56: ! 57: /* ! 58: * bits in cnfgr ! 59: */ ! 60: #define PARFLT 0x80000000 /* SBI Parity Fault */ ! 61: #define WSQFLT 0x40000000 /* SBI Write Sequence Fault */ ! 62: #define URDFLT 0x20000000 /* SBI Unexpected Read Fault */ ! 63: #define ISQFLT 0x10000000 /* SBI Interlock Sequence Fault */ ! 64: #define MXTFLT 0x8000000 /* SBI Multiple Transmitter Fault */ ! 65: #define XMTFLT 0x4000000 /* UBA is transmit faulter */ ! 66: #define UBIC 0x10000 /* init complete */ ! 67: ! 68: #define CFGFLT (PARFLT|WSQFLT|URDFLT|ISQFLT|MXTFLT|XMTFLT) ! 69: ! 70: /* ! 71: * bits in uasr ! 72: */ ! 73: #define DPPE 0x20 /* Data Path Parity Error */ ! 74: #define IVMR 0x10 /* Invalid Map Register */ ! 75: #define MRPF 0x8 /* Map Register Parity Failure */ ! 76: #define UBSSYNTO 0x1 /* unibus SSYN timeout */ ! 77: ! 78: #define BADMAP (MRPF|IVMR|DPPE) /* bits indicating mapping reg problem */ ! 79: ! 80: /* ! 81: * bits in the data path register ! 82: */ ! 83: ! 84: #define BNE 0x80000000 /* purge datapath */ ! 85: #define BTE 0x40000000 /* bdp transfer error */ ! 86: ! 87: /* ! 88: * bits in map register ! 89: */ ! 90: ! 91: #define MPAGE 0x7ffff /* physical page number */ ! 92: #define BO 0x2000000 /* offset address by one */ ! 93: #define MRV 0x80000000 /* map register valid */ ! 94: #define PSHIFT 21 /* shift data path number this much */ ! 95: ! 96: #define INITTIME 50000 /* time to stall waiting for UNIBUS init */ ! 97: /* 25ms nominal; 50000 for VAX-11/785 */ ! 98: ! 99: /* ! 100: * return the register address for a unibus device ! 101: */ ! 102: ! 103: caddr_t ! 104: ubaddr(up) ! 105: register struct ubaddr *up; ! 106: { ! 107: register struct uba *ub; ! 108: ! 109: if (up->ubno < 0 || up->ubno > ubacnt) { ! 110: printf("bad ubano %d\n", up->ubno); ! 111: return (0); ! 112: } ! 113: ub = &uba[up->ubno]; ! 114: if ((ub->flags & UBINIT) == 0) ! 115: if (ubstart(up->ubno) == 0) ! 116: return (0); ! 117: return ((caddr_t)&ub->addr->ubspace[up->uboff]); ! 118: } ! 119: ! 120: /* ! 121: * init the unibus adapter ! 122: */ ! 123: ! 124: ubstart(u) ! 125: int u; ! 126: { ! 127: register struct uba *ub; ! 128: ! 129: ub = &uba[u]; ! 130: if ((ub->addr = (struct ubadev *)nxaddr(&ubaaddr[u])) == 0) ! 131: return (0); ! 132: if (badaddr(&ub->addr->cnfgr, sizeof(long))) { ! 133: printf("ub%d not responding\n", u); ! 134: return (0); ! 135: } ! 136: rminit(ub->map, UBNMAP, NMAP-1, 1); /* NMAP-1 because can't alloc 0 */ ! 137: ub->path = ((1<<NBDP)-1)<<1; ! 138: if (ubmstart(u) == 0) ! 139: return (0); ! 140: ubinit(u); ! 141: ub->flags |= UBINIT; ! 142: return (1); ! 143: } ! 144: ! 145: /* ! 146: * init the unibus adapter hardware ! 147: */ ! 148: ! 149: ubinit(u) ! 150: int u; ! 151: { ! 152: register struct uba *ub; ! 153: register struct ubadev *up; ! 154: register int i; ! 155: register long *p; ! 156: ! 157: ub = &uba[u]; ! 158: up = ub->addr; ! 159: up->uacr = ADINIT; ! 160: for (i = 0; i < INITTIME; i++) ! 161: if (up->cnfgr & UBIC) ! 162: break; ! 163: if ((up->cnfgr & UBIC) == 0) { ! 164: printf("ub%d not ready\n", u); ! 165: return (0); ! 166: } ! 167: ubavoff[u] = ubaaddr[u].voff; ! 168: ubavreg[u] = &up->brrvr[0]; ! 169: up->cnfgr = up->cnfgr; /* clear power-up latches */ ! 170: up->uacr = UBAIE; ! 171: for (i = 0, p = ub->addr->mreg; i < NMAP; i++) ! 172: *p++ = 0; ! 173: ubminit(u); ! 174: return (1); ! 175: } ! 176: ! 177: /* ! 178: * determine whether a particular address, ! 179: * which happens to be in UNIBUS space, ! 180: * exists ! 181: */ ! 182: ubbadaddr(u, a, s) ! 183: int u, s; ! 184: caddr_t a; ! 185: { ! 186: register int p; ! 187: register struct ubadev *up; ! 188: ! 189: if (u < 0 || u >= ubacnt) ! 190: return (1); ! 191: up = uba[u].addr; ! 192: p = spl7(); ! 193: /* perhaps disable SBI-to-UNIBUS interrupts? */ ! 194: up->uasr = up->uasr; /* clear errors */ ! 195: s = badaddr(a, s); ! 196: if (up->uasr & UBSSYNTO) /* or perhaps any error? */ ! 197: s = 1; ! 198: up->uasr = up->uasr; /* clear errors again */ ! 199: splx(p); ! 200: return (s); ! 201: } ! 202: ! 203: /* ! 204: * get/put a single byte to a particular unibus address ! 205: * intended for use by ECC code ! 206: * work it out from first principles, ! 207: * because UNIBUS adapter may loop and hang otherwise ! 208: */ ! 209: ! 210: static long ! 211: ubphys(ubno, addr) ! 212: unsigned int ubno; ! 213: uaddr_t addr; ! 214: { ! 215: register struct uba *ub; ! 216: register int pg; ! 217: register long m; ! 218: ! 219: if (ubno >= ubacnt) ! 220: panic("ubphys"); ! 221: ub = &uba[ubno]; ! 222: if (ub->addr == NULL) ! 223: panic("ubphys"); ! 224: pg = addr / NBPG; ! 225: if (pg >= NMAP) ! 226: return (-1); /* addr too big */ ! 227: m = ub->addr->mreg[pg]; ! 228: if ((m & MRV) == 0) ! 229: return (-1); /* invalid */ ! 230: return ((m & MPAGE) * NBPG + addr % NBPG); ! 231: } ! 232: ! 233: int ! 234: ubgetc(ubno, addr) ! 235: unsigned int ubno; ! 236: uaddr_t addr; ! 237: { ! 238: register long phys; ! 239: ! 240: phys = ubphys(ubno, addr); ! 241: if (phys < 0) ! 242: return (-1); ! 243: return (phgetc(phys)); ! 244: } ! 245: ! 246: int ! 247: ubputc(ubno, addr, c) ! 248: unsigned int ubno; ! 249: uaddr_t addr; ! 250: char c; ! 251: { ! 252: register long phys; ! 253: ! 254: phys = ubphys(ubno, addr); ! 255: if (phys < 0) ! 256: return (-1); ! 257: return (phputc(phys, c)); ! 258: } ! 259: ! 260: /* ! 261: * unibus adapter interrupts ! 262: * here only on non-device interrupts: ! 263: * passive release, or adapter has something to say ! 264: * ! 265: * -- assertion: ! 266: * to get here, we must read the BRRVR, ! 267: * which means ubavreg is set up, ! 268: * which means uba.addr is set up ! 269: */ ! 270: ! 271: uba0int(u, vec) ! 272: int u; ! 273: { ! 274: register struct ubadev *up; ! 275: long cnfgr, uasr, fubar, fmer; ! 276: ! 277: if (vec == 0) { /* passive release */ ! 278: ubazvec[u]++; ! 279: return; ! 280: } ! 281: up = uba[u].addr; ! 282: cnfgr = up->cnfgr; ! 283: uasr = up->uasr; ! 284: fubar = up->fubar<<2; ! 285: fmer = up->fmer; ! 286: up->uasr = uasr; ! 287: up->cnfgr = cnfgr; ! 288: if (cnfgr & CFGFLT) { /* does this really happen? */ ! 289: printf("ub%d: SBI fault cnfgr%x sr%x\n", u, cnfgr, uasr); ! 290: return; ! 291: } ! 292: printf("ub%d: cfg%x sr%x fubar %o\n", u, cnfgr, uasr, fubar); ! 293: if (uasr & BADMAP) ! 294: printf("fmer %x\n", fmer); ! 295: } ! 296: ! 297: /* ! 298: * allocate a buffered data path ! 299: * return the ddp if none available ! 300: */ ! 301: int ubnopath; ! 302: ! 303: int ! 304: ubmapath(u) ! 305: int u; ! 306: { ! 307: register struct uba *ub; ! 308: register int path; ! 309: register int s; ! 310: ! 311: ub = &uba[u]; ! 312: s = spl6(); ! 313: for (path = NBDP; path > 0; path--) ! 314: if (ub->path & (1<<path)) { ! 315: ub->path &=~ (1<<path); ! 316: break; ! 317: } ! 318: splx(s); ! 319: if (path == 0) ! 320: ubnopath++; ! 321: return (path); ! 322: } ! 323: ! 324: ubmflush(u, path) ! 325: int u; ! 326: int path; ! 327: { ! 328: register long *reg; ! 329: ! 330: if (path == 0) ! 331: return; ! 332: reg = &uba[u].addr->dpr[path]; ! 333: *reg |= BNE; ! 334: DELAY(2); ! 335: if (*reg & BTE) { ! 336: printf("ub%d bdp%d err %x\n", u, path, *reg); ! 337: *reg = *reg; ! 338: } ! 339: } ! 340: ! 341: /* ! 342: * fill in a piece of unibus map ! 343: * return the address of the base ! 344: */ ! 345: ! 346: uaddr_t ! 347: ubmsetmap(u, p, nreg, um) ! 348: int u; ! 349: register struct pte *p; ! 350: register int nreg; ! 351: ubm_t um; ! 352: { ! 353: register long *m; ! 354: register long x; ! 355: ! 356: m = &uba[u].addr->mreg[ubmfirst(um)]; ! 357: x = (ubmpath(um)<<PSHIFT)|MRV; ! 358: if (nreg > ubmsize(um)-1) ! 359: panic("ubmsetmap"); ! 360: while (--nreg >= 0) ! 361: *m++ = p++->pg_pfnum | x; ! 362: *m = 0; ! 363: return (ctob(ubmfirst(um))); ! 364: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.