|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1987, 1988 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: * @(#)vba.c 7.6 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: /* ! 37: * Tahoe VERSAbus adapator support routines. ! 38: */ ! 39: ! 40: #include "sys/param.h" ! 41: #include "sys/buf.h" ! 42: #include "sys/cmap.h" ! 43: #include "sys/conf.h" ! 44: #include "dk.h" ! 45: #include "sys/map.h" ! 46: #include "sys/systm.h" ! 47: #include "sys/user.h" ! 48: #include "sys/vmparam.h" ! 49: #include "sys/vmmac.h" ! 50: #include "sys/proc.h" ! 51: #include "sys/syslog.h" ! 52: #include "sys/malloc.h" ! 53: ! 54: #include "../include/mtpr.h" ! 55: #include "../include/pte.h" ! 56: ! 57: #include "../vba/vbavar.h" ! 58: ! 59: /* ! 60: * Allocate private page map and intermediate buffer ! 61: * for a VERSAbus device, large enough for maximum transfer size. ! 62: * Intermediate buffer ! 63: * Make intermediate buffer uncacheable. ! 64: */ ! 65: vbainit(vb, xsize, flags) ! 66: register struct vb_buf *vb; ! 67: int xsize, flags; ! 68: { ! 69: register struct pte *pte; ! 70: register n; ! 71: ! 72: vb->vb_flags = flags; ! 73: if (vbmapalloc((int)btoc(xsize) + 1, &vb->vb_map, &vb->vb_utl) == 0) { ! 74: printf("vbmap exhausted\n"); ! 75: return (0); ! 76: } ! 77: n = roundup(xsize, NBPG); ! 78: vb->vb_bufsize = n; ! 79: if (vb->vb_rawbuf == 0) ! 80: vb->vb_rawbuf = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); ! 81: if (vb->vb_rawbuf == 0) { ! 82: printf("no memory for device buffer\n"); ! 83: return (0); ! 84: } ! 85: if ((int)vb->vb_rawbuf & PGOFSET) ! 86: panic("vbinit pgoff"); ! 87: vb->vb_physbuf = (u_long)kvtophys(vb->vb_rawbuf); ! 88: if (flags & VB_20BIT) ! 89: vb->vb_maxphys = btoc(VB_MAXADDR20); ! 90: else if (flags & VB_24BIT) ! 91: vb->vb_maxphys = btoc(VB_MAXADDR24); ! 92: else ! 93: vb->vb_maxphys = btoc(VB_MAXADDR32); ! 94: if (btoc(vb->vb_physbuf + n) > vb->vb_maxphys) ! 95: panic("vbinit physbuf"); ! 96: ! 97: /* ! 98: * Make raw buffer pages uncacheable. ! 99: */ ! 100: pte = kvtopte(vb->vb_rawbuf); ! 101: for (n = btoc(n); n--; pte++) ! 102: pte->pg_nc = 1; ! 103: mtpr(TBIA, 0); ! 104: return (1); ! 105: } ! 106: ! 107: /* ! 108: * Due to unknown hardware or software errors, some sites have problems ! 109: * with strange crashes or corruption of text images when DMA is attempted ! 110: * to kernel addresses spanning a page boundary, or to user addresses ! 111: * (even if the buffer is physically contiguous). To avoid this behavior, ! 112: * the following toggles inhibit such transfers when set. ! 113: * vba_copyk: copy transfers to kernel address that span a page boundary ! 114: * vba_copyu: copy transfers to user addresses ! 115: */ ! 116: #ifndef VBA_TRICKY ! 117: int vba_copyk = 1; ! 118: int vba_copyu = 1; ! 119: #else ! 120: int vba_copyk = 0; ! 121: int vba_copyu = 0; ! 122: #endif ! 123: ! 124: /* ! 125: * Check a transfer to see whether it can be done directly ! 126: * to the destination buffer, or whether it must be copied. ! 127: * On Tahoe, the lack of a bus I/O map forces data to be copied ! 128: * to a physically-contiguous buffer whenever one of the following is true: ! 129: * 1) The data length is not a multiple of sector size. ! 130: * (The swapping code does this, unfortunately.) ! 131: * 2) The buffer is not physically contiguous and the controller ! 132: * does not support scatter-gather operations. ! 133: * 3) The physical address for I/O is higher than addressible ! 134: * by the device. ! 135: * This routine is called by the start routine. ! 136: * If copying is necessary, the intermediate buffer is mapped; ! 137: * if the operation is a write, the data is copied into the buffer. ! 138: * It returns the physical address of the first byte for DMA, to ! 139: * be presented to the controller. ! 140: */ ! 141: u_long ! 142: vbasetup(bp, vb, sectsize) ! 143: register struct buf *bp; ! 144: register struct vb_buf *vb; ! 145: int sectsize; ! 146: { ! 147: register struct pte *spte, *dpte; ! 148: register int p, i; ! 149: int npf, o, v; ! 150: ! 151: o = (int)bp->b_un.b_addr & PGOFSET; ! 152: npf = btoc(bp->b_bcount + o); ! 153: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE); ! 154: if (vb->vb_iskernel) { ! 155: spte = kvtopte(bp->b_un.b_addr); ! 156: if (vba_copyk && (o != 0 || npf > 1)) goto copy; ! 157: } else { ! 158: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc, ! 159: btop(bp->b_un.b_addr)); ! 160: if (vba_copyu) goto copy; ! 161: } ! 162: if (bp->b_bcount % sectsize != 0 || (o & (sizeof(long) - 1)) != 0) ! 163: goto copy; ! 164: else if ((vb->vb_flags & VB_SCATTER) == 0 || ! 165: vb->vb_maxphys != btoc(VB_MAXADDR32)) { ! 166: dpte = spte; ! 167: p = (dpte++)->pg_pfnum; ! 168: for (i = npf; --i > 0; dpte++) { ! 169: if ((v = dpte->pg_pfnum) != p + CLSIZE && ! 170: (vb->vb_flags & VB_SCATTER) == 0) ! 171: goto copy; ! 172: if (p >= vb->vb_maxphys) ! 173: goto copy; ! 174: p = v; ! 175: } ! 176: if (p >= vb->vb_maxphys) ! 177: goto copy; ! 178: } ! 179: vb->vb_copy = 0; ! 180: if (vb->vb_iskernel) ! 181: vbastat.k_raw++; ! 182: else ! 183: vbastat.u_raw++; ! 184: return ((spte->pg_pfnum << PGSHIFT) + o); ! 185: ! 186: copy: ! 187: vb->vb_copy = 1; ! 188: if (bp->b_bcount > vb->vb_bufsize) ! 189: panic("vba xfer too large"); ! 190: if (vb->vb_iskernel) { ! 191: if ((bp->b_flags & B_READ) == 0) ! 192: bcopy(bp->b_un.b_addr, vb->vb_rawbuf, ! 193: (unsigned)bp->b_bcount); ! 194: vbastat.k_copy++; ! 195: } else { ! 196: dpte = vb->vb_map; ! 197: for (i = npf, p = (int)vb->vb_utl; i--; p += NBPG) { ! 198: *(int *)dpte++ = (spte++)->pg_pfnum | ! 199: PG_V | PG_KW | PG_N; ! 200: mtpr(TBIS, p); ! 201: } ! 202: if ((bp->b_flags & B_READ) == 0) ! 203: bcopy(vb->vb_utl + o, vb->vb_rawbuf, ! 204: (unsigned)bp->b_bcount); ! 205: vbastat.u_copy++; ! 206: } ! 207: return (vb->vb_physbuf); ! 208: } ! 209: ! 210: /* ! 211: * Called by the driver's interrupt routine, after DMA is completed. ! 212: * If the operation was a read, copy data to final buffer if necessary ! 213: * or invalidate data cache for cacheable direct buffers. ! 214: * Similar to the vbastart routine, but in the reverse direction. ! 215: */ ! 216: vbadone(bp, vb) ! 217: register struct buf *bp; ! 218: register struct vb_buf *vb; ! 219: { ! 220: register npf; ! 221: register caddr_t v; ! 222: int o; ! 223: ! 224: if (bp->b_flags & B_READ) { ! 225: o = (int)bp->b_un.b_addr & PGOFSET; ! 226: if (vb->vb_copy) { ! 227: if (vb->vb_iskernel) ! 228: bcopy(vb->vb_rawbuf, bp->b_un.b_addr, ! 229: (unsigned)(bp->b_bcount - bp->b_resid)); ! 230: else { ! 231: bcopy(vb->vb_rawbuf, vb->vb_utl + o, ! 232: (unsigned)(bp->b_bcount - bp->b_resid)); ! 233: dkeyinval(bp->b_proc); ! 234: } ! 235: } else { ! 236: if (vb->vb_iskernel) { ! 237: npf = btoc(bp->b_bcount + o); ! 238: for (v = bp->b_un.b_addr; npf--; v += NBPG) ! 239: mtpr(P1DC, (int)v); ! 240: } else ! 241: dkeyinval(bp->b_proc); ! 242: } ! 243: } ! 244: } ! 245: ! 246: /* ! 247: * Set up a scatter-gather operation for SMD/E controller. ! 248: * This code belongs half-way between {hd,vd}.c and this file. ! 249: */ ! 250: ! 251: #include "dk.h" ! 252: #if NVD > 0 ! 253: #include "vdreg.h" ! 254: ! 255: vd_sgsetup(bp, vb, sg) ! 256: register struct buf *bp; ! 257: struct vb_buf *vb; ! 258: struct trsg *sg; ! 259: { ! 260: register struct pte *spte; ! 261: register struct addr_chain *adr; ! 262: register int i; ! 263: int o; ! 264: ! 265: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE); ! 266: vb->vb_copy = 0; ! 267: if (vb->vb_iskernel) { ! 268: spte = kvtopte(bp->b_un.b_addr); ! 269: vbastat.k_sg++; ! 270: } else { ! 271: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc, ! 272: btop(bp->b_un.b_addr)); ! 273: vbastat.u_sg++; ! 274: } ! 275: ! 276: o = (int)bp->b_un.b_addr & PGOFSET; ! 277: i = min(NBPG - o, bp->b_bcount); ! 278: sg->start_addr.wcount = i >> 1; ! 279: sg->start_addr.memadr = ((spte++)->pg_pfnum << PGSHIFT) + o; ! 280: i = bp->b_bcount - i; ! 281: if (i > VDMAXPAGES * NBPG) ! 282: panic("vba xfer too large"); ! 283: i = i >> 1; ! 284: for (adr = sg->addr_chain; i > 0; adr++, i -= NBPG / 2) { ! 285: adr->nxt_addr = (spte++)->pg_pfnum << PGSHIFT; ! 286: adr->nxt_len = imin(i, NBPG / 2); ! 287: } ! 288: adr->nxt_addr = 0; ! 289: adr++->nxt_len = 0; ! 290: return ((adr - sg->addr_chain) * sizeof(*adr) / sizeof(long)); ! 291: } ! 292: #endif ! 293: ! 294: #include "hd.h" ! 295: #if NHD > 0 ! 296: #include "hdreg.h" ! 297: ! 298: hd_sgsetup(bp, vb, sg) ! 299: register struct buf *bp; ! 300: struct vb_buf *vb; ! 301: struct chain *sg; ! 302: { ! 303: register struct pte *spte; ! 304: register struct addr_chain *adr; ! 305: register int i, cnt; ! 306: int o; ! 307: ! 308: if (bp->b_bcount > HDC_MAXBC || ! 309: bp->b_bcount % sizeof(long) - 1 || ! 310: (u_int)bp->b_un.b_addr % sizeof(long) - 1) ! 311: return(0); ! 312: ! 313: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE); ! 314: vb->vb_copy = 0; ! 315: if (vb->vb_iskernel) { ! 316: spte = kvtopte(bp->b_un.b_addr); ! 317: vbastat.k_sg++; ! 318: } else { ! 319: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc, ! 320: btop(bp->b_un.b_addr)); ! 321: vbastat.u_sg++; ! 322: } ! 323: ! 324: o = (int)bp->b_un.b_addr & PGOFSET; ! 325: i = min(NBPG - o, bp->b_bcount); ! 326: sg->wcount = i >> 2; ! 327: sg->memadr = ((spte++)->pg_pfnum << PGSHIFT) + o; ! 328: cnt = 0; ! 329: for (i = (bp->b_bcount - i) >> 2; i > 0; i -= NBPG / sizeof(long)) { ! 330: if (++cnt == HDC_MAXCHAIN) ! 331: return(0); ! 332: sg->wcount |= LWC_DATA_CHAIN; ! 333: ++sg; ! 334: sg->wcount = imin(i, NBPG / sizeof(long)); ! 335: sg->memadr = (spte++)->pg_pfnum << PGSHIFT; ! 336: } ! 337: return(1); ! 338: } ! 339: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.