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