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