|
|
1.1 ! root 1: /* uba.c 4.42 82/03/31 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/systm.h" ! 5: #include "../h/cpu.h" ! 6: #include "../h/map.h" ! 7: #include "../h/pte.h" ! 8: #include "../h/buf.h" ! 9: #include "../h/vm.h" ! 10: #include "../h/ubareg.h" ! 11: #include "../h/ubavar.h" ! 12: #include "../h/dir.h" ! 13: #include "../h/user.h" ! 14: #include "../h/proc.h" ! 15: #include "../h/conf.h" ! 16: #include "../h/mtpr.h" ! 17: #include "../h/nexus.h" ! 18: #include "../h/dk.h" ! 19: #include "../h/trace.h" ! 20: ! 21: #if VAX780 ! 22: char ubasr_bits[] = UBASR_BITS; ! 23: #endif ! 24: ! 25: /* ! 26: * Do transfer on device argument. The controller ! 27: * and uba involved are implied by the device. ! 28: * We queue for resource wait in the uba code if necessary. ! 29: * We return 1 if the transfer was started, 0 if it was not. ! 30: * If you call this routine with the head of the queue for a ! 31: * UBA, it will automatically remove the device from the UBA ! 32: * queue before it returns. If some other device is given ! 33: * as argument, it will be added to the request queue if the ! 34: * request cannot be started immediately. This means that ! 35: * passing a device which is on the queue but not at the head ! 36: * of the request queue is likely to be a disaster. ! 37: */ ! 38: ubago(ui) ! 39: register struct uba_device *ui; ! 40: { ! 41: register struct uba_ctlr *um = ui->ui_mi; ! 42: register struct uba_hd *uh; ! 43: register int s, unit; ! 44: ! 45: uh = &uba_hd[um->um_ubanum]; ! 46: s = spl6(); ! 47: if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) ! 48: goto rwait; ! 49: /* if(uh->uh_users < 0) ! 50: printf ("(1) uh_users = %d\n", uh->uh_users); */ ! 51: if(um->um_tab.b_actf == NULL) { ! 52: panic("null ptr in ubago\n"); ! 53: splx(s); ! 54: return; ! 55: } ! 56: um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, ! 57: UBA_NEEDBDP|UBA_CANTWAIT); ! 58: if (um->um_ubinfo == 0) ! 59: goto rwait; ! 60: uh->uh_users++; ! 61: trace(TR_BDPOFF, -1, uh->uh_users); /* overloaded lazy */ ! 62: if (um->um_driver->ud_xclu) ! 63: uh->uh_xclu = 1; ! 64: splx(s); ! 65: if (ui->ui_dk >= 0) { ! 66: unit = ui->ui_dk; ! 67: dk_busy |= 1<<unit; ! 68: dk_xfer[unit]++; ! 69: dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; ! 70: } ! 71: if (uh->uh_actf == ui) ! 72: uh->uh_actf = ui->ui_forw; ! 73: /* if(uh->uh_users <= 0) ! 74: printf ("(2) uh_users = %d\n", uh->uh_users); */ ! 75: (*um->um_driver->ud_dgo)(um); ! 76: return (1); ! 77: rwait: ! 78: trace(TR_BDPOFF, -3, uh->uh_users); ! 79: if (uh->uh_actf != ui) { ! 80: ui->ui_forw = NULL; ! 81: if (uh->uh_actf == NULL) ! 82: uh->uh_actf = ui; ! 83: else ! 84: uh->uh_actl->ui_forw = ui; ! 85: uh->uh_actl = ui; ! 86: } ! 87: splx(s); ! 88: return (0); ! 89: } ! 90: ! 91: ubadone(um) ! 92: register struct uba_ctlr *um; ! 93: { ! 94: register struct uba_hd *uh = &uba_hd[um->um_ubanum]; ! 95: ! 96: if (um->um_driver->ud_xclu) ! 97: uh->uh_xclu = 0; ! 98: uh->uh_users--; ! 99: trace(TR_BDPOFF, -2, uh->uh_users); /* overloaded lazy */ ! 100: /* if(uh->uh_users < 0) ! 101: printf ("(3) uh_users = %d\n", uh->uh_users); */ ! 102: ubarelse(um->um_ubanum, &um->um_ubinfo); ! 103: } ! 104: ! 105: /* ! 106: * Allocate and setup UBA map registers, and bdp's ! 107: * Flags says whether bdp is needed, whether the caller can't ! 108: * wait (e.g. if the caller is at interrupt level). ! 109: * ! 110: * Return value: ! 111: * Bits 0-8 Byte offset ! 112: * Bits 9-17 Start map reg. no. ! 113: * Bits 18-27 No. mapping reg's ! 114: * Bits 28-31 BDP no. ! 115: */ ! 116: ubasetup(uban, bp, flags) ! 117: struct buf *bp; ! 118: { ! 119: register struct uba_hd *uh = &uba_hd[uban]; ! 120: register int temp, i; ! 121: int npf, reg, bdp; ! 122: unsigned v; ! 123: register struct pte *pte, *io; ! 124: struct proc *rp; ! 125: int a, o, ubinfo; ! 126: ! 127: #if VAX7ZZ ! 128: if (cpu == VAX_7ZZ) ! 129: flags &= ~UBA_NEEDBDP; ! 130: #endif ! 131: v = btop(bp->b_un.b_addr); ! 132: o = (int)bp->b_un.b_addr & PGOFSET; ! 133: npf = btoc(bp->b_bcount + o) + 1; ! 134: a = spl6(); ! 135: while ((reg = rmalloc(uh->uh_map, npf)) == 0) { ! 136: if (flags & UBA_CANTWAIT) { ! 137: splx(a); ! 138: return (0); ! 139: } ! 140: uh->uh_mrwant++; ! 141: sleep((caddr_t)uh->uh_map, PSWP); ! 142: } ! 143: bdp = 0; ! 144: if (flags & UBA_NEEDBDP) { ! 145: while ((bdp = ffs(uh->uh_bdpfree)) == 0) { ! 146: if (flags & UBA_CANTWAIT) { ! 147: rmfree(uh->uh_map, npf, reg); ! 148: splx(a); ! 149: return (0); ! 150: } ! 151: uh->uh_bdpwant++; ! 152: sleep((caddr_t)uh->uh_map, PSWP); ! 153: } ! 154: uh->uh_bdpfree &= ~(1 << (bdp-1)); ! 155: } else if (flags & UBA_HAVEBDP) ! 156: bdp = (flags >> 28) & 0xf; ! 157: else if(flags & UBA_WANTBDP) { ! 158: bdp = ffs(uh->uh_bdpfree); ! 159: if(bdp) ! 160: uh->uh_bdpfree &= ~(1 << (bdp-1)); ! 161: } ! 162: trace(TR_BDPON, uh->uh_bdpfree, flags); ! 163: splx(a); ! 164: reg--; ! 165: ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; ! 166: temp = (bdp << 21) | UBAMR_MRV; ! 167: if (bdp && (o & 01)) ! 168: temp |= UBAMR_BO; ! 169: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; ! 170: if ((bp->b_flags & B_PHYS) == 0) ! 171: pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; ! 172: else if (bp->b_flags & B_UAREA) ! 173: pte = &rp->p_addr[v]; ! 174: else if (bp->b_flags & B_PAGET) ! 175: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; ! 176: else ! 177: pte = vtopte(rp, v); ! 178: io = &uh->uh_uba->uba_map[reg]; ! 179: while (--npf != 0) { ! 180: if (pte->pg_pfnum == 0) ! 181: panic("uba zero uentry"); ! 182: *(int *)io++ = pte++->pg_pfnum | temp; ! 183: } ! 184: *(int *)io++ = 0; ! 185: return (ubinfo); ! 186: } ! 187: ! 188: /* ! 189: * Non buffer setup interface... set up a buffer and call ubasetup. ! 190: */ ! 191: uballoc(uban, addr, bcnt, flags) ! 192: int uban; ! 193: caddr_t addr; ! 194: int bcnt, flags; ! 195: { ! 196: struct buf ubabuf; ! 197: ! 198: ubabuf.b_un.b_addr = addr; ! 199: ubabuf.b_flags = B_BUSY; ! 200: ubabuf.b_bcount = bcnt; ! 201: /* that's all the fields ubasetup() needs */ ! 202: return (ubasetup(uban, &ubabuf, flags)); ! 203: } ! 204: ! 205: /* ! 206: * Release resources on uba uban, and then unblock resource waiters. ! 207: * The map register parameter is by value since we need to block ! 208: * against uba resets on 11/780's. ! 209: */ ! 210: ubarelse(uban, amr) ! 211: int *amr; ! 212: { ! 213: register struct uba_hd *uh = &uba_hd[uban]; ! 214: register int bdp, reg, npf, s; ! 215: int mr; ! 216: ! 217: /* ! 218: * Carefully see if we should release the space, since ! 219: * it may be released asynchronously at uba reset time. ! 220: */ ! 221: s = spl6(); ! 222: mr = *amr; ! 223: if (mr == 0) { ! 224: /* ! 225: * A ubareset() occurred before we got around ! 226: * to releasing the space... no need to bother. ! 227: */ ! 228: splx(s); ! 229: return; ! 230: } ! 231: *amr = 0; ! 232: splx(s); /* let interrupts in, we're safe for a while */ ! 233: bdp = (mr >> 28) & 0x0f; ! 234: if (bdp) { ! 235: switch (cpu) { ! 236: #if VAX780 ! 237: case VAX_780: ! 238: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; ! 239: break; ! 240: #endif ! 241: #if VAX750 ! 242: case VAX_750: ! 243: uh->uh_uba->uba_dpr[bdp] |= ! 244: UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; ! 245: break; ! 246: #endif ! 247: } ! 248: uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ ! 249: trace(TR_BDPOFF, uh->uh_bdpfree, 0); ! 250: if (uh->uh_bdpwant) { ! 251: uh->uh_bdpwant = 0; ! 252: wakeup((caddr_t)uh->uh_map); ! 253: } ! 254: } ! 255: /* ! 256: * Put back the registers in the resource map. ! 257: * The map code must not be reentered, so we do this ! 258: * at high ipl. ! 259: */ ! 260: npf = (mr >> 18) & 0x3ff; ! 261: reg = ((mr >> 9) & 0x1ff) + 1; ! 262: s = spl6(); ! 263: rmfree(uh->uh_map, npf, reg); ! 264: splx(s); ! 265: ! 266: /* ! 267: * Wakeup sleepers for map registers, ! 268: * and also, if there are processes blocked in dgo(), ! 269: * give them a chance at the UNIBUS. ! 270: */ ! 271: if (uh->uh_mrwant) { ! 272: uh->uh_mrwant = 0; ! 273: wakeup((caddr_t)uh->uh_map); ! 274: } ! 275: while (uh->uh_actf && ubago(uh->uh_actf)) ! 276: ; ! 277: } ! 278: ! 279: #define PRGTIM 10 /* time to spin for bdp flush on comet */ ! 280: ! 281: ubapurge(um) ! 282: register struct uba_ctlr *um; ! 283: { ! 284: register struct uba_hd *uh = um->um_hd; ! 285: register int bdp = (um->um_ubinfo >> 28) & 0x0f; ! 286: register int i; ! 287: register int *reg; ! 288: ! 289: switch (cpu) { ! 290: #if VAX780 ! 291: case VAX_780: ! 292: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; ! 293: break; ! 294: #endif ! 295: #if VAX750 ! 296: case VAX_750: ! 297: reg = &uh->uh_uba->uba_dpr[bdp]; ! 298: *reg |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; ! 299: for (i = PRGTIM; i > 0; i--) ! 300: if ((*reg & UBADPR_PURGE) == 0) ! 301: break; ! 302: if (i <= 0) ! 303: printf("uba%d bdp%d stuck\n", um->um_ubanum, bdp); ! 304: if (*reg & UBADPR_ERROR) ! 305: printf("uba%d bdp%d error %x\n", um->um_ubanum, ! 306: bdp, *reg); ! 307: break; ! 308: #endif ! 309: } ! 310: } ! 311: ! 312: /* ! 313: * Generate a reset on uba number uban. Then ! 314: * call each device in the character device table, ! 315: * giving it a chance to clean up so as to be able to continue. ! 316: */ ! 317: ubareset(uban) ! 318: int uban; ! 319: { ! 320: register struct cdevsw *cdp; ! 321: register struct uba_hd *uh = &uba_hd[uban]; ! 322: int s; ! 323: ! 324: s = spl6(); ! 325: uh->uh_users = 0; ! 326: uh->uh_zvcnt = 0; ! 327: uh->uh_xclu = 0; ! 328: uh->uh_hangcnt = 0; ! 329: uh->uh_actf = uh->uh_actl = 0; ! 330: uh->uh_bdpwant = 0; ! 331: uh->uh_mrwant = 0; ! 332: wakeup((caddr_t)&uh->uh_bdpwant); ! 333: wakeup((caddr_t)&uh->uh_mrwant); ! 334: printf("uba%d: reset", uban); ! 335: ubainit(uh->uh_uba); ! 336: for (cdp = cdevsw; cdp->d_open; cdp++) ! 337: (*cdp->d_reset)(uban); ! 338: #ifdef INET ! 339: ifubareset(uban); ! 340: #endif ! 341: printf("\n"); ! 342: splx(s); ! 343: } ! 344: ! 345: /* ! 346: * Init a uba. This is called with a pointer ! 347: * rather than a virtual address since it is called ! 348: * by code which runs with memory mapping disabled. ! 349: * In these cases we really don't need the interrupts ! 350: * enabled, but since we run with ipl high, we don't care ! 351: * if they are, they will never happen anyways. ! 352: */ ! 353: ubainit(uba) ! 354: register struct uba_regs *uba; ! 355: { ! 356: ! 357: switch (cpu) { ! 358: #if VAX780 ! 359: case VAX_780: ! 360: uba->uba_cr = UBACR_ADINIT; ! 361: uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; ! 362: while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) ! 363: ; ! 364: break; ! 365: #endif ! 366: #if VAX750 ! 367: case VAX_750: ! 368: #endif ! 369: #if VAX7ZZ ! 370: case VAX_7ZZ: ! 371: #endif ! 372: #if defined(VAX750) || defined(VAX7ZZ) ! 373: mtpr(IUR, 0); ! 374: /* give devices time to recover from power fail */ ! 375: /* THIS IS PROBABLY UNNECESSARY */ ! 376: DELAY(500000); ! 377: /* END PROBABLY UNNECESSARY */ ! 378: break; ! 379: #endif ! 380: } ! 381: } ! 382: ! 383: #if VAX780 ! 384: /* ! 385: * Check to make sure the UNIBUS adaptor is not hung, ! 386: * with an interrupt in the register to be presented, ! 387: * but not presenting it for an extended period (5 seconds). ! 388: */ ! 389: unhang() ! 390: { ! 391: register int uban; ! 392: ! 393: for (uban = 0; uban < numuba; uban++) { ! 394: register struct uba_hd *uh = &uba_hd[uban]; ! 395: register struct uba_regs *up = uh->uh_uba; ! 396: ! 397: if (up->uba_sr == 0) ! 398: return; ! 399: up->uba_sr = UBASR_CRD|UBASR_LEB; ! 400: uh->uh_hangcnt++; ! 401: if (uh->uh_hangcnt > 5*hz) { ! 402: uh->uh_hangcnt = 0; ! 403: printf("uba%d: hung\n", uban); ! 404: ubareset(uban); ! 405: } ! 406: } ! 407: } ! 408: ! 409: /* ! 410: * This is a timeout routine which decrements the ``i forgot to ! 411: * interrupt'' counts, on an 11/780. This prevents slowly growing ! 412: * counts from causing a UBA reset since we are interested only ! 413: * in hang situations. ! 414: */ ! 415: ubawatch() ! 416: { ! 417: register struct uba_hd *uh; ! 418: register int uban; ! 419: ! 420: if (panicstr) ! 421: return; ! 422: for (uban = 0; uban < numuba; uban++) { ! 423: uh = &uba_hd[uban]; ! 424: if (uh->uh_hangcnt) ! 425: uh->uh_hangcnt--; ! 426: } ! 427: } ! 428: ! 429: int ubawedgecnt = 10; ! 430: int ubacrazy = 500; ! 431: /* ! 432: * This routine is called by the locore code to ! 433: * process a UBA error on an 11/780. The arguments are passed ! 434: * on the stack, and value-result (through some trickery). ! 435: * In particular, the uvec argument is used for further ! 436: * uba processing so the result aspect of it is very important. ! 437: * It must not be declared register. ! 438: */ ! 439: /*ARGSUSED*/ ! 440: ubaerror(uban, uh, xx, uvec, uba) ! 441: register int uban; ! 442: register struct uba_hd *uh; ! 443: int uvec; ! 444: register struct uba_regs *uba; ! 445: { ! 446: register sr, s; ! 447: ! 448: if (uvec == 0) { ! 449: uh->uh_zvcnt++; ! 450: if (uh->uh_zvcnt > 250000) { ! 451: printf("uba%d: too many zero vectors\n"); ! 452: ubareset(uban); ! 453: } ! 454: uvec = 0; ! 455: return; ! 456: } ! 457: if (uba->uba_cnfgr & NEX_CFGFLT) { ! 458: printf("uba%d: sbi fault sr=%b cnfgr=%b\n", ! 459: uban, uba->uba_sr, ubasr_bits, ! 460: uba->uba_cnfgr, NEXFLT_BITS); ! 461: ubareset(uban); ! 462: uvec = 0; ! 463: return; ! 464: } ! 465: sr = uba->uba_sr; ! 466: s = spl7(); ! 467: printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", ! 468: uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); ! 469: splx(s); ! 470: uba->uba_sr = sr; ! 471: uvec &= UBABRRVR_DIV; ! 472: if (++uh->uh_errcnt % ubawedgecnt == 0) { ! 473: if (uh->uh_errcnt > ubacrazy) ! 474: panic("uba crazy"); ! 475: printf("ERROR LIMIT "); ! 476: ubareset(uban); ! 477: uvec = 0; ! 478: return; ! 479: } ! 480: return; ! 481: } ! 482: #endif ! 483: ! 484: #if defined(CHAOS) ! 485: /* ! 486: * This routine allows remapping of previously ! 487: * allocated UNIBUS bdp and map resources ! 488: * onto different memory addresses. ! 489: * It should only be used by routines which need ! 490: * small fixed length mappings for long periods of time ! 491: * (like the ARPANET ACC IMP interface). ! 492: * It only maps kernel addresses. ! 493: */ ! 494: ubaremap(uban, ubinfo, addr) ! 495: int uban; ! 496: register unsigned ubinfo; ! 497: caddr_t addr; ! 498: { ! 499: register struct uba_hd *uh = &uba_hd[uban]; ! 500: register struct pte *pte, *io; ! 501: register int temp, bdp; ! 502: int npf, o; ! 503: ! 504: o = (int)addr & PGOFSET; ! 505: bdp = (ubinfo >> 28) & 0xf; ! 506: npf = (ubinfo >> 18) & 0x3ff; ! 507: io = &uh->uh_uba->uba_map[(ubinfo >> 9) & 0x1ff]; ! 508: temp = (bdp << 21) | UBAMR_MRV; ! 509: ! 510: /* ! 511: * If using buffered data path initiate purge ! 512: * of old data and set byte offset bit if next ! 513: * transfer will be from odd address. ! 514: */ ! 515: if (bdp) { ! 516: switch (cpu) { ! 517: #if VAX780 ! 518: case VAX_780: ! 519: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; ! 520: break; ! 521: #endif ! 522: #if VAX750 ! 523: case VAX_750: ! 524: uh->uh_uba->uba_dpr[bdp] |= ! 525: UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; ! 526: break; ! 527: #endif ! 528: } ! 529: if (o & 1) ! 530: temp |= UBAMR_BO; ! 531: } ! 532: ! 533: /* ! 534: * Set up the map registers, leaving an invalid reg ! 535: * at the end to guard against wild unibus transfers. ! 536: */ ! 537: pte = &Sysmap[btop(((int)addr)&0x7fffffff)]; ! 538: while (--npf != 0) ! 539: *(int *)io++ = pte++->pg_pfnum | temp; ! 540: *(int *)io = 0; ! 541: ! 542: /* ! 543: * Return effective UNIBUS address. ! 544: */ ! 545: return ((ubinfo & ~PGOFSET) | o); ! 546: } ! 547: #endif defined(CHAOS)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.