|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)uba.c 7.10 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: #include "sys/param.h" ! 37: #include "sys/systm.h" ! 38: #include "sys/map.h" ! 39: #include "sys/buf.h" ! 40: #include "sys/vm.h" ! 41: #include "sys/user.h" ! 42: #include "sys/proc.h" ! 43: #include "sys/conf.h" ! 44: #include "sys/dkstat.h" ! 45: #include "sys/kernel.h" ! 46: ! 47: #include "../include/pte.h" ! 48: #include "../include/cpu.h" ! 49: #include "../include/mtpr.h" ! 50: #include "../vax/nexus.h" ! 51: #include "ubareg.h" ! 52: #include "ubavar.h" ! 53: ! 54: #ifdef DW780 ! 55: char ubasr_bits[] = UBASR_BITS; ! 56: #endif ! 57: ! 58: #define spluba spl7 /* IPL 17 */ ! 59: ! 60: /* ! 61: * Do transfer on device argument. The controller ! 62: * and uba involved are implied by the device. ! 63: * We queue for resource wait in the uba code if necessary. ! 64: * We return 1 if the transfer was started, 0 if it was not. ! 65: * ! 66: * The onq argument must be zero iff the device is not on the ! 67: * queue for this UBA. If onq is set, the device must be at the ! 68: * head of the queue. In any case, if the transfer is started, ! 69: * the device will be off the queue, and if not, it will be on. ! 70: * ! 71: * Drivers that allocate one BDP and hold it for some time should ! 72: * set ud_keepbdp. In this case um_bdp tells which BDP is allocated ! 73: * to the controller, unless it is zero, indicating that the controller ! 74: * does not now have a BDP. ! 75: */ ! 76: ubaqueue(ui, onq) ! 77: register struct uba_device *ui; ! 78: int onq; ! 79: { ! 80: register struct uba_ctlr *um = ui->ui_mi; ! 81: register struct uba_hd *uh; ! 82: register struct uba_driver *ud; ! 83: register int s, unit; ! 84: ! 85: uh = &uba_hd[um->um_ubanum]; ! 86: ud = um->um_driver; ! 87: s = spluba(); ! 88: /* ! 89: * Honor exclusive BDP use requests. ! 90: */ ! 91: if (ud->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) ! 92: goto rwait; ! 93: if (ud->ud_keepbdp) { ! 94: /* ! 95: * First get just a BDP (though in fact it comes with ! 96: * one map register too). ! 97: */ ! 98: if (um->um_bdp == 0) { ! 99: um->um_bdp = uballoc(um->um_ubanum, ! 100: (caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT); ! 101: if (um->um_bdp == 0) ! 102: goto rwait; ! 103: } ! 104: /* now share it with this transfer */ ! 105: um->um_ubinfo = ubasetup(um->um_ubanum, ! 106: um->um_tab.b_actf->b_actf, ! 107: um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT); ! 108: } else ! 109: um->um_ubinfo = ubasetup(um->um_ubanum, ! 110: um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT); ! 111: if (um->um_ubinfo == 0) ! 112: goto rwait; ! 113: uh->uh_users++; ! 114: if (ud->ud_xclu) ! 115: uh->uh_xclu = 1; ! 116: splx(s); ! 117: if (ui->ui_dk >= 0) { ! 118: unit = ui->ui_dk; ! 119: dk_busy |= 1<<unit; ! 120: dk_xfer[unit]++; ! 121: dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; ! 122: } ! 123: if (onq) ! 124: uh->uh_actf = ui->ui_forw; ! 125: (*ud->ud_dgo)(um); ! 126: return (1); ! 127: rwait: ! 128: if (!onq) { ! 129: ui->ui_forw = NULL; ! 130: if (uh->uh_actf == NULL) ! 131: uh->uh_actf = ui; ! 132: else ! 133: uh->uh_actl->ui_forw = ui; ! 134: uh->uh_actl = ui; ! 135: } ! 136: splx(s); ! 137: return (0); ! 138: } ! 139: ! 140: ubadone(um) ! 141: register struct uba_ctlr *um; ! 142: { ! 143: register struct uba_hd *uh = &uba_hd[um->um_ubanum]; ! 144: ! 145: if (um->um_driver->ud_xclu) ! 146: uh->uh_xclu = 0; ! 147: uh->uh_users--; ! 148: if (um->um_driver->ud_keepbdp) ! 149: um->um_ubinfo &= ~BDPMASK; /* keep BDP for misers */ ! 150: ubarelse(um->um_ubanum, &um->um_ubinfo); ! 151: } ! 152: ! 153: /* ! 154: * Allocate and setup UBA map registers, and bdp's ! 155: * Flags says whether bdp is needed, whether the caller can't ! 156: * wait (e.g. if the caller is at interrupt level). ! 157: * Return value encodes map register plus page offset, ! 158: * bdp number and number of map registers. ! 159: */ ! 160: ubasetup(uban, bp, flags) ! 161: int uban; ! 162: register struct buf *bp; ! 163: register int flags; ! 164: { ! 165: register struct uba_hd *uh = &uba_hd[uban]; ! 166: register struct pte *pte, *io; ! 167: register int npf; ! 168: int pfnum, temp; ! 169: int reg, bdp; ! 170: unsigned v; ! 171: struct proc *rp; ! 172: int a, o, ubinfo; ! 173: ! 174: #ifdef DW730 ! 175: if (uh->uh_type == DW730) ! 176: flags &= ~UBA_NEEDBDP; ! 177: #endif ! 178: #ifdef QBA ! 179: if (uh->uh_type == QBA) ! 180: flags &= ~UBA_NEEDBDP; ! 181: #endif ! 182: o = (int)bp->b_un.b_addr & PGOFSET; ! 183: npf = btoc(bp->b_bcount + o) + 1; ! 184: if (npf > UBA_MAXNMR) ! 185: panic("uba xfer too big"); ! 186: a = spluba(); ! 187: while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) { ! 188: if (flags & UBA_CANTWAIT) { ! 189: splx(a); ! 190: return (0); ! 191: } ! 192: uh->uh_mrwant++; ! 193: sleep((caddr_t)&uh->uh_mrwant, PSWP); ! 194: } ! 195: if ((flags & UBA_NEED16) && reg + npf > 128) { ! 196: /* ! 197: * Could hang around and try again (if we can ever succeed). ! 198: * Won't help any current device... ! 199: */ ! 200: rmfree(uh->uh_map, (long)npf, (long)reg); ! 201: splx(a); ! 202: return (0); ! 203: } ! 204: bdp = 0; ! 205: if (flags & UBA_NEEDBDP) { ! 206: while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) { ! 207: if (flags & UBA_CANTWAIT) { ! 208: rmfree(uh->uh_map, (long)npf, (long)reg); ! 209: splx(a); ! 210: return (0); ! 211: } ! 212: uh->uh_bdpwant++; ! 213: sleep((caddr_t)&uh->uh_bdpwant, PSWP); ! 214: } ! 215: uh->uh_bdpfree &= ~(1 << (bdp-1)); ! 216: } else if (flags & UBA_HAVEBDP) ! 217: bdp = (flags >> 28) & 0xf; ! 218: splx(a); ! 219: reg--; ! 220: ubinfo = UBAI_INFO(o, reg, npf, bdp); ! 221: temp = (bdp << 21) | UBAMR_MRV; ! 222: if (bdp && (o & 01)) ! 223: temp |= UBAMR_BO; ! 224: if ((bp->b_flags & B_PHYS) == 0) ! 225: pte = kvtopte(bp->b_un.b_addr); ! 226: else if (bp->b_flags & B_PAGET) ! 227: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; ! 228: else { ! 229: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; ! 230: v = btop(bp->b_un.b_addr); ! 231: if (bp->b_flags & B_UAREA) ! 232: pte = &rp->p_addr[v]; ! 233: else ! 234: pte = vtopte(rp, v); ! 235: } ! 236: io = &uh->uh_mr[reg]; ! 237: while (--npf > 0) { ! 238: pfnum = pte->pg_pfnum; ! 239: if (pfnum == 0) ! 240: panic("uba zero uentry"); ! 241: pte++; ! 242: *(int *)io++ = pfnum | temp; ! 243: } ! 244: *(int *)io = 0; ! 245: return (ubinfo); ! 246: } ! 247: ! 248: /* ! 249: * Non buffer setup interface... set up a buffer and call ubasetup. ! 250: */ ! 251: uballoc(uban, addr, bcnt, flags) ! 252: int uban; ! 253: caddr_t addr; ! 254: int bcnt, flags; ! 255: { ! 256: struct buf ubabuf; ! 257: ! 258: ubabuf.b_un.b_addr = addr; ! 259: ubabuf.b_flags = B_BUSY; ! 260: ubabuf.b_bcount = bcnt; ! 261: /* that's all the fields ubasetup() needs */ ! 262: return (ubasetup(uban, &ubabuf, flags)); ! 263: } ! 264: ! 265: /* ! 266: * Release resources on uba uban, and then unblock resource waiters. ! 267: * The map register parameter is by value since we need to block ! 268: * against uba resets on 11/780's. ! 269: */ ! 270: ubarelse(uban, amr) ! 271: int *amr; ! 272: { ! 273: register struct uba_hd *uh = &uba_hd[uban]; ! 274: register int bdp, reg, npf, s; ! 275: int mr; ! 276: ! 277: /* ! 278: * Carefully see if we should release the space, since ! 279: * it may be released asynchronously at uba reset time. ! 280: */ ! 281: s = spluba(); ! 282: mr = *amr; ! 283: if (mr == 0) { ! 284: /* ! 285: * A ubareset() occurred before we got around ! 286: * to releasing the space... no need to bother. ! 287: */ ! 288: splx(s); ! 289: return; ! 290: } ! 291: *amr = 0; ! 292: bdp = UBAI_BDP(mr); ! 293: if (bdp) { ! 294: switch (uh->uh_type) { ! 295: #ifdef DWBUA ! 296: case DWBUA: ! 297: BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; ! 298: break; ! 299: #endif ! 300: #ifdef DW780 ! 301: case DW780: ! 302: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; ! 303: break; ! 304: #endif ! 305: #ifdef DW750 ! 306: case DW750: ! 307: uh->uh_uba->uba_dpr[bdp] |= ! 308: UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; ! 309: break; ! 310: #endif ! 311: default: ! 312: break; ! 313: } ! 314: uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ ! 315: if (uh->uh_bdpwant) { ! 316: uh->uh_bdpwant = 0; ! 317: wakeup((caddr_t)&uh->uh_bdpwant); ! 318: } ! 319: } ! 320: /* ! 321: * Put back the registers in the resource map. ! 322: * The map code must not be reentered, ! 323: * nor can the registers be freed twice. ! 324: * Unblock interrupts once this is done. ! 325: */ ! 326: npf = UBAI_NMR(mr); ! 327: reg = UBAI_MR(mr) + 1; ! 328: rmfree(uh->uh_map, (long)npf, (long)reg); ! 329: splx(s); ! 330: ! 331: /* ! 332: * Wakeup sleepers for map registers, ! 333: * and also, if there are processes blocked in dgo(), ! 334: * give them a chance at the UNIBUS. ! 335: */ ! 336: if (uh->uh_mrwant) { ! 337: uh->uh_mrwant = 0; ! 338: wakeup((caddr_t)&uh->uh_mrwant); ! 339: } ! 340: while (uh->uh_actf && ubaqueue(uh->uh_actf, 1)) ! 341: ; ! 342: } ! 343: ! 344: ubapurge(um) ! 345: register struct uba_ctlr *um; ! 346: { ! 347: register struct uba_hd *uh = um->um_hd; ! 348: register int bdp = UBAI_BDP(um->um_ubinfo); ! 349: ! 350: switch (uh->uh_type) { ! 351: #ifdef DWBUA ! 352: case DWBUA: ! 353: BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; ! 354: break; ! 355: #endif ! 356: #ifdef DW780 ! 357: case DW780: ! 358: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; ! 359: break; ! 360: #endif ! 361: #ifdef DW750 ! 362: case DW750: ! 363: uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; ! 364: break; ! 365: #endif ! 366: default: ! 367: break; ! 368: } ! 369: } ! 370: ! 371: ubainitmaps(uhp) ! 372: register struct uba_hd *uhp; ! 373: { ! 374: ! 375: if (uhp->uh_memsize > UBA_MAXMR) ! 376: uhp->uh_memsize = UBA_MAXMR; ! 377: rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); ! 378: switch (uhp->uh_type) { ! 379: #ifdef DWBUA ! 380: case DWBUA: ! 381: uhp->uh_bdpfree = (1<<NBDPBUA) - 1; ! 382: break; ! 383: #endif ! 384: #ifdef DW780 ! 385: case DW780: ! 386: uhp->uh_bdpfree = (1<<NBDP780) - 1; ! 387: break; ! 388: #endif ! 389: #ifdef DW750 ! 390: case DW750: ! 391: uhp->uh_bdpfree = (1<<NBDP750) - 1; ! 392: break; ! 393: #endif ! 394: default: ! 395: break; ! 396: } ! 397: } ! 398: ! 399: /* ! 400: * Generate a reset on uba number uban. Then ! 401: * call each device in the character device table, ! 402: * giving it a chance to clean up so as to be able to continue. ! 403: */ ! 404: ubareset(uban) ! 405: int uban; ! 406: { ! 407: register struct cdevsw *cdp; ! 408: register struct uba_hd *uh = &uba_hd[uban]; ! 409: int s; ! 410: ! 411: s = spluba(); ! 412: uh->uh_users = 0; ! 413: uh->uh_zvcnt = 0; ! 414: uh->uh_xclu = 0; ! 415: uh->uh_actf = uh->uh_actl = 0; ! 416: uh->uh_bdpwant = 0; ! 417: uh->uh_mrwant = 0; ! 418: ubainitmaps(uh); ! 419: wakeup((caddr_t)&uh->uh_bdpwant); ! 420: wakeup((caddr_t)&uh->uh_mrwant); ! 421: printf("uba%d: reset", uban); ! 422: ubainit(uh->uh_uba); ! 423: ubameminit(uban); ! 424: for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) ! 425: (*cdp->d_reset)(uban); ! 426: ifubareset(uban); ! 427: printf("\n"); ! 428: splx(s); ! 429: } ! 430: ! 431: /* ! 432: * Init a uba. This is called with a pointer ! 433: * rather than a virtual address since it is called ! 434: * by code which runs with memory mapping disabled. ! 435: * In these cases we really don't need the interrupts ! 436: * enabled, but since we run with ipl high, we don't care ! 437: * if they are, they will never happen anyways. ! 438: * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. ! 439: */ ! 440: ubainit(uba) ! 441: register struct uba_regs *uba; ! 442: { ! 443: register struct uba_hd *uhp; ! 444: #ifdef QBA ! 445: int isphys = 0; ! 446: #endif ! 447: ! 448: for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { ! 449: if (uhp->uh_uba == uba) ! 450: break; ! 451: if (uhp->uh_physuba == uba) { ! 452: #ifdef QBA ! 453: isphys++; ! 454: #endif ! 455: break; ! 456: } ! 457: } ! 458: if (uhp >= uba_hd + numuba) { ! 459: printf("init unknown uba\n"); ! 460: return; ! 461: } ! 462: ! 463: switch (uhp->uh_type) { ! 464: #ifdef DWBUA ! 465: case DWBUA: ! 466: BUA(uba)->bua_csr |= BUACSR_UPI; ! 467: /* give devices time to recover from power fail */ ! 468: DELAY(500000); ! 469: break; ! 470: #endif ! 471: #ifdef DW780 ! 472: case DW780: ! 473: uba->uba_cr = UBACR_ADINIT; ! 474: uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; ! 475: while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) ! 476: ; ! 477: break; ! 478: #endif ! 479: #ifdef DW750 ! 480: case DW750: ! 481: #endif ! 482: #ifdef DW730 ! 483: case DW730: ! 484: #endif ! 485: #ifdef QBA ! 486: case QBA: ! 487: #endif ! 488: #if DW750 || DW730 || QBA ! 489: mtpr(IUR, 0); ! 490: /* give devices time to recover from power fail */ ! 491: /* THIS IS PROBABLY UNNECESSARY */ ! 492: DELAY(500000); ! 493: /* END PROBABLY UNNECESSARY */ ! 494: #ifdef QBA ! 495: /* ! 496: * Re-enable local memory access ! 497: * from the Q-bus. ! 498: */ ! 499: if (uhp->uh_type == QBA) { ! 500: if (isphys) ! 501: *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; ! 502: else ! 503: *(uhp->uh_iopage + QIPCR) = Q_LMEAE; ! 504: } ! 505: #endif QBA ! 506: break; ! 507: #endif DW750 || DW730 || QBA ! 508: } ! 509: } ! 510: ! 511: #ifdef QBA ! 512: /* ! 513: * Determine the interrupt priority of a Q-bus ! 514: * peripheral. The device probe routine must spl6(), ! 515: * attempt to make the device request an interrupt, ! 516: * delaying as necessary, then call this routine ! 517: * before resetting the device. ! 518: */ ! 519: qbgetpri() ! 520: { ! 521: int pri; ! 522: extern int cvec; ! 523: ! 524: for (pri = 0x17; pri > 0x14; ) { ! 525: if (cvec && cvec != 0x200) /* interrupted at pri */ ! 526: break; ! 527: pri--; ! 528: splx(pri - 1); ! 529: } ! 530: (void) spl0(); ! 531: return (pri); ! 532: } ! 533: #endif ! 534: ! 535: #ifdef DW780 ! 536: int ubawedgecnt = 10; ! 537: int ubacrazy = 500; ! 538: int zvcnt_max = 5000; /* in 8 sec */ ! 539: /* ! 540: * This routine is called by the locore code to process a UBA ! 541: * error on an 11/780 or 8600. The arguments are passed ! 542: * on the stack, and value-result (through some trickery). ! 543: * In particular, the uvec argument is used for further ! 544: * uba processing so the result aspect of it is very important. ! 545: * It must not be declared register. ! 546: */ ! 547: /*ARGSUSED*/ ! 548: ubaerror(uban, uh, ipl, uvec, uba) ! 549: register int uban; ! 550: register struct uba_hd *uh; ! 551: int ipl, uvec; ! 552: register struct uba_regs *uba; ! 553: { ! 554: register sr, s; ! 555: ! 556: if (uvec == 0) { ! 557: /* ! 558: * Declare dt as unsigned so that negative values ! 559: * are handled as >8 below, in case time was set back. ! 560: */ ! 561: u_long dt = time.tv_sec - uh->uh_zvtime; ! 562: ! 563: uh->uh_zvtotal++; ! 564: if (dt > 8) { ! 565: uh->uh_zvtime = time.tv_sec; ! 566: uh->uh_zvcnt = 0; ! 567: } ! 568: if (++uh->uh_zvcnt > zvcnt_max) { ! 569: printf("uba%d: too many zero vectors (%d in <%d sec)\n", ! 570: uban, uh->uh_zvcnt, dt + 1); ! 571: printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", ! 572: ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, ! 573: uba->uba_cnfgr&0xff); ! 574: printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", ! 575: uba->uba_sr, ubasr_bits, uba->uba_dcr, ! 576: (uba->uba_dcr&0x8000000)?"":"NOT "); ! 577: ubareset(uban); ! 578: } ! 579: return; ! 580: } ! 581: if (uba->uba_cnfgr & NEX_CFGFLT) { ! 582: printf("uba%d: sbi fault sr=%b cnfgr=%b\n", ! 583: uban, uba->uba_sr, ubasr_bits, ! 584: uba->uba_cnfgr, NEXFLT_BITS); ! 585: ubareset(uban); ! 586: uvec = 0; ! 587: return; ! 588: } ! 589: sr = uba->uba_sr; ! 590: s = spluba(); ! 591: printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", ! 592: uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); ! 593: splx(s); ! 594: uba->uba_sr = sr; ! 595: uvec &= UBABRRVR_DIV; ! 596: if (++uh->uh_errcnt % ubawedgecnt == 0) { ! 597: if (uh->uh_errcnt > ubacrazy) ! 598: panic("uba crazy"); ! 599: printf("ERROR LIMIT "); ! 600: ubareset(uban); ! 601: uvec = 0; ! 602: return; ! 603: } ! 604: return; ! 605: } ! 606: #endif ! 607: ! 608: /* ! 609: * Look for devices with unibus memory, allow them to configure, then disable ! 610: * map registers as necessary. Called during autoconfiguration and ubareset. ! 611: * The device ubamem routine returns 0 on success, 1 on success if it is fully ! 612: * configured (has no csr or interrupt, so doesn't need to be probed), ! 613: * and -1 on failure. ! 614: */ ! 615: ubameminit(uban) ! 616: { ! 617: register struct uba_device *ui; ! 618: register struct uba_hd *uh = &uba_hd[uban]; ! 619: caddr_t umembase = umem[uban] + 0x3e000, addr; ! 620: #define ubaoff(off) ((int)(off) & 0x1fff) ! 621: ! 622: uh->uh_lastmem = 0; ! 623: for (ui = ubdinit; ui->ui_driver; ui++) { ! 624: if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') ! 625: continue; ! 626: if (ui->ui_driver->ud_ubamem) { ! 627: /* ! 628: * During autoconfiguration, need to fudge ui_addr. ! 629: */ ! 630: addr = ui->ui_addr; ! 631: ui->ui_addr = umembase + ubaoff(addr); ! 632: switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { ! 633: case 1: ! 634: ui->ui_alive = 1; ! 635: /* FALLTHROUGH */ ! 636: case 0: ! 637: ui->ui_ubanum = uban; ! 638: break; ! 639: } ! 640: ui->ui_addr = addr; ! 641: } ! 642: } ! 643: #ifdef DW780 ! 644: /* ! 645: * On a DW780, throw away any map registers disabled by rounding ! 646: * the map disable in the configuration register ! 647: * up to the next 8K boundary, or below the last unibus memory. ! 648: */ ! 649: if (uh->uh_type == DW780) { ! 650: register i; ! 651: ! 652: i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192); ! 653: while (i) ! 654: (void) rmget(uh->uh_map, 1, i--); ! 655: } ! 656: #endif ! 657: } ! 658: ! 659: /* ! 660: * Allocate UNIBUS memory. Allocates and initializes ! 661: * sufficient mapping registers for access. On a 780, ! 662: * the configuration register is setup to disable UBA ! 663: * response on DMA transfers to addresses controlled ! 664: * by the disabled mapping registers. ! 665: * On a DW780, should only be called from ubameminit, or in ascending order ! 666: * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't ! 667: * the last unibus memory would free unusable map registers. ! 668: * Doalloc is 1 to allocate, 0 to deallocate. ! 669: */ ! 670: ubamem(uban, addr, npg, doalloc) ! 671: int uban, addr, npg, doalloc; ! 672: { ! 673: register struct uba_hd *uh = &uba_hd[uban]; ! 674: register int a; ! 675: int s; ! 676: ! 677: a = (addr >> 9) + 1; ! 678: s = spluba(); ! 679: if (doalloc) ! 680: a = rmget(uh->uh_map, npg, a); ! 681: else ! 682: rmfree(uh->uh_map, (long)npg, (long)a); ! 683: splx(s); ! 684: if (a) { ! 685: register int i, *m; ! 686: ! 687: m = (int *)&uh->uh_mr[a - 1]; ! 688: for (i = 0; i < npg; i++) ! 689: *m++ = 0; /* All off, especially 'valid' */ ! 690: i = addr + npg * 512; ! 691: if (doalloc && i > uh->uh_lastmem) ! 692: uh->uh_lastmem = i; ! 693: else if (doalloc == 0 && i == uh->uh_lastmem) ! 694: uh->uh_lastmem = addr; ! 695: #ifdef DW780 ! 696: /* ! 697: * On a 780, set up the map register disable ! 698: * field in the configuration register. Beware ! 699: * of callers that request memory ``out of order'' ! 700: * or in sections other than 8K multiples. ! 701: * Ubameminit handles such requests properly, however. ! 702: */ ! 703: if (uh->uh_type == DW780) { ! 704: i = uh->uh_uba->uba_cr &~ 0x7c000000; ! 705: i |= ((uh->uh_lastmem + 8191) / 8192) << 26; ! 706: uh->uh_uba->uba_cr = i; ! 707: } ! 708: #endif ! 709: } ! 710: return (a); ! 711: } ! 712: ! 713: #include "ik.h" ! 714: #include "vs.h" ! 715: #if NIK > 0 || NVS > 0 ! 716: /* ! 717: * Map a virtual address into users address space. Actually all we ! 718: * do is turn on the user mode write protection bits for the particular ! 719: * page of memory involved. ! 720: */ ! 721: maptouser(vaddress) ! 722: caddr_t vaddress; ! 723: { ! 724: ! 725: kvtopte(vaddress)->pg_prot = (PG_UW >> 27); ! 726: } ! 727: ! 728: unmaptouser(vaddress) ! 729: caddr_t vaddress; ! 730: { ! 731: ! 732: kvtopte(vaddress)->pg_prot = (PG_KW >> 27); ! 733: } ! 734: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.