|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)mb.c 1.1 86/02/03 Copyr 1983 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: /* ! 10: * Mainbus support routines. ! 11: */ ! 12: ! 13: #include "../h/param.h" ! 14: #include "../h/systm.h" ! 15: #include "../h/vmmac.h" ! 16: #include "../h/vmmeter.h" ! 17: #include "../h/vmparam.h" ! 18: #include "../h/map.h" ! 19: #include "../h/buf.h" ! 20: #include "../h/dir.h" ! 21: #include "../h/user.h" ! 22: #include "../h/proc.h" ! 23: #include "../h/conf.h" ! 24: /*#include "../h/kernel.h"*/ ! 25: ! 26: #include "../machine/mmu.h" ! 27: #include "../machine/cpu.h" ! 28: #include "../machine/psl.h" ! 29: #include "../machine/pte.h" ! 30: #include "../machine/reg.h" ! 31: ! 32: #include "../sundev/mbvar.h" ! 33: ! 34: /* ! 35: * Do transfer on controller argument. ! 36: * We queue for resource wait in the Mainbus code if necessary. ! 37: * We return 1 if the transfer was started, 0 if it was not. ! 38: * If you call this routine with the head of the queue for a ! 39: * Mainbus, it will automatically remove the controller from the Mainbus ! 40: * queue before it returns. If some other controller is given ! 41: * as argument, it will be added to the request queue if the ! 42: * request cannot be started immediately. This means that ! 43: * passing a controller which is on the queue but not at the head ! 44: * of the request queue is likely to be a disaster. ! 45: */ ! 46: mbgo(mc) ! 47: register struct mb_ctlr *mc; ! 48: { ! 49: register struct mb_hd *mh = mc->mc_mh; ! 50: register struct buf *bp = mc->mc_tab.b_actf->b_actf; ! 51: register int s; ! 52: ! 53: s = splx(pritospl(SPLMB)); ! 54: if ((mc->mc_driver->mdr_flags & MDR_XCLU) && ! 55: mh->mh_users > 0 || mh->mh_xclu) ! 56: goto rwait; ! 57: mc->mc_mbinfo = mbsetup(mh, bp, MB_CANTWAIT); ! 58: if (mc->mc_mbinfo == 0) ! 59: goto rwait; ! 60: mh->mh_users++; ! 61: if (mc->mc_driver->mdr_flags & MDR_XCLU) ! 62: mh->mh_xclu = 1; ! 63: (void) splx(s); ! 64: if (mh->mh_actf == mc) ! 65: mh->mh_actf = mc->mc_forw; ! 66: if ((mc->mc_driver->mdr_flags & MDR_SWAB) && (bp->b_flags&B_READ)==0) ! 67: swab(bp->b_un.b_addr, bp->b_un.b_addr, (int)bp->b_bcount); ! 68: (*mc->mc_driver->mdr_go)(mc); ! 69: return (1); ! 70: rwait: ! 71: if (mh->mh_actf != mc) { ! 72: mc->mc_forw = NULL; ! 73: if (mh->mh_actf == NULL) ! 74: mh->mh_actf = mc; ! 75: else ! 76: mh->mh_actl->mc_forw = mc; ! 77: mh->mh_actl = mc; ! 78: } ! 79: (void) splx(s); ! 80: return (0); ! 81: } ! 82: ! 83: mbdone(mc) ! 84: register struct mb_ctlr *mc; ! 85: { ! 86: register struct mb_hd *mh = mc->mc_mh; ! 87: register struct buf *bp = mc->mc_tab.b_actf->b_actf; ! 88: ! 89: if (mc->mc_driver->mdr_flags & MDR_XCLU) ! 90: mh->mh_xclu = 0; ! 91: mh->mh_users--; ! 92: mbrelse(mh, &mc->mc_mbinfo); ! 93: if (mc->mc_driver->mdr_flags & MDR_SWAB) ! 94: swab(bp->b_un.b_addr, bp->b_un.b_addr, (int)bp->b_bcount); ! 95: (*mc->mc_driver->mdr_done)(mc); ! 96: } ! 97: ! 98: /* ! 99: * Allocate and setup Mainbus map registers. ! 100: * Flags says whether the caller can't ! 101: * wait (e.g. if the caller is at interrupt level). ! 102: * ! 103: * We also allow DMA to memory already mapped at the Mainbus ! 104: * (e.g., for Sun Ethernet board memory) and denote this with ! 105: * a zero in the MBI_NMR field. ! 106: */ ! 107: mbsetup(mh, bp, flags) ! 108: register struct mb_hd *mh; ! 109: struct buf *bp; ! 110: int flags; ! 111: { ! 112: int npf, reg; ! 113: register struct pte *pte; ! 114: register char *addr; ! 115: int s, o; ! 116: struct mbcookie mbcookie; ! 117: #ifdef sun2 ! 118: int uc; ! 119: #endif ! 120: ! 121: o = (int)bp->b_un.b_addr & PGOFSET; ! 122: if ((bp->b_flags & B_PHYS) == 0) ! 123: pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)]; ! 124: else { ! 125: if (bp->b_kmx == 0) ! 126: panic("mbsetup: zero kmx"); ! 127: pte = &Usrptmap[bp->b_kmx]; ! 128: } ! 129: ! 130: npf = btoc(bp->b_bcount + o); ! 131: if (buscheck(pte, npf)) { ! 132: mbcookie.mbi_mapreg = pte->pg_pfnum; ! 133: mbcookie.mbi_offset = o; ! 134: return (*(int *)&mbcookie); ! 135: } ! 136: ! 137: /* Defensively invalidate the page following the allocation */ ! 138: npf++; ! 139: s = splx(pritospl(SPLMB)); ! 140: while ((reg = (int)rmalloc(mh->mh_map, (long)npf)) == 0) { ! 141: if (flags & MB_CANTWAIT) { ! 142: (void) splx(s); ! 143: return (0); ! 144: } ! 145: mh->mh_mrwant++; ! 146: sleep((caddr_t)&mh->mh_mrwant, PSWP); ! 147: } ! 148: (void) splx(s); ! 149: mbcookie.mbi_mapreg = reg; ! 150: mbcookie.mbi_offset = o; ! 151: addr = &DVMA[ctob(reg)]; ! 152: #ifdef sun2 ! 153: uc = getusercontext(); ! 154: setusercontext(KCONTEXT); ! 155: #endif ! 156: while (--npf > 0) { ! 157: register int pfnum; ! 158: ! 159: switch (*(int *)pte & PGT_MASK) { ! 160: default: ! 161: /* may not go from dvma back out to the bus */ ! 162: panic("mbsetup: bad PGT"); ! 163: case PGT_OBMEM: ! 164: case PGT_OBIO: ! 165: if ((pfnum = pte->pg_pfnum) == 0) ! 166: panic("mbsetup: zero pfnum"); ! 167: setpgmap(addr, (long)(PG_V | PG_KW | pfnum)); ! 168: addr += NBPG; ! 169: pte++; ! 170: } ! 171: } ! 172: setpgmap(addr, (long)0); ! 173: #ifdef sun2 ! 174: setusercontext(uc); ! 175: #endif ! 176: return (*(int *)&mbcookie); ! 177: } ! 178: ! 179: /* ! 180: * Non buffer setup interface... set up a buffer and call mbsetup. ! 181: */ ! 182: mballoc(mh, addr, bcnt, flags) ! 183: struct mb_hd *mh; ! 184: caddr_t addr; ! 185: int bcnt, flags; ! 186: { ! 187: struct buf mbbuf; ! 188: ! 189: mbbuf.b_un.b_addr = addr; ! 190: mbbuf.b_flags = B_BUSY; ! 191: mbbuf.b_bcount = bcnt; ! 192: /* that's all the fields mbsetup() needs */ ! 193: return (mbsetup(mh, &mbbuf, flags)); ! 194: } ! 195: ! 196: /* ! 197: * Release resources on Mainbus, and then unblock resource waiters. ! 198: * The map register parameter is by value since we need to block ! 199: * against Mainbus resets. ! 200: */ ! 201: mbrelse(mh, amr) ! 202: register struct mb_hd *mh; ! 203: int *amr; ! 204: { ! 205: register int reg, s; ! 206: register char *addr; ! 207: int mr; ! 208: #ifdef sun2 ! 209: int uc; ! 210: #endif ! 211: ! 212: /* ! 213: * Carefully see if we should release the space, since ! 214: * it may be released asynchronously at Mainbus reset time. ! 215: */ ! 216: s = splx(pritospl(SPLMB)); ! 217: mr = *amr; ! 218: if (mr == 0) { ! 219: printf("mbrelse: MR == 0!!!\n"); ! 220: (void) splx(s); ! 221: return; ! 222: } ! 223: *amr = 0; ! 224: (void) splx(s); /* let interrupts in, we're safe for a while */ ! 225: ! 226: if ((reg = MBI_MR(mr)) < dvmasize) { /* DVMA memory */ ! 227: long getpgmap(); ! 228: register int npf = 1; /* plus one for last entry */ ! 229: ! 230: #ifdef sun2 ! 231: uc = getusercontext(); ! 232: setusercontext(KCONTEXT); ! 233: #endif ! 234: for (addr = &DVMA[ctob(reg)]; getpgmap(addr) != (long)0; ! 235: addr += NBPG, npf++) ! 236: setpgmap(addr, (long)0); ! 237: #ifdef sun2 ! 238: setusercontext(uc); ! 239: #endif ! 240: /* ! 241: * Put back the registers in the resource map. ! 242: * The map code must not be reentered, so we do this ! 243: * at high spl. ! 244: */ ! 245: s = splx(pritospl(SPLMB)); ! 246: rmfree(mh->mh_map, (long)npf, (long)reg); ! 247: (void) splx(s); ! 248: ! 249: /* ! 250: * Wakeup sleepers for map registers, ! 251: * and also, if there are processes blocked in mbgo(), ! 252: * give them a chance at the Mainbus. ! 253: */ ! 254: if (mh->mh_mrwant) { ! 255: mh->mh_mrwant = 0; ! 256: wakeup((caddr_t)&mh->mh_mrwant); ! 257: } ! 258: } ! 259: while (mh->mh_actf && mbgo(mh->mh_actf)) ! 260: ; ! 261: } ! 262: ! 263: /* ! 264: * Swap bytes in 16-bit [half-]words ! 265: * for going between the 11 and the interdata ! 266: */ ! 267: swab(pf, pt, n) ! 268: register caddr_t pf, pt; ! 269: register int n; ! 270: { ! 271: register char temp; ! 272: ! 273: n = (n+1)>>1; ! 274: ! 275: while (--n >= 0) { ! 276: temp = *pf++; ! 277: *pt++ = *pf++; ! 278: *pt++ = temp; ! 279: } ! 280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.