|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /*- ! 26: * Copyright (c) 1982, 1986, 1990, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * (c) UNIX System Laboratories, Inc. ! 29: * All or some portions of this file are derived from material licensed ! 30: * to the University of California by American Telephone and Telegraph ! 31: * Co. or Unix System Laboratories, Inc. and are reproduced herein with ! 32: * the permission of UNIX System Laboratories, Inc. ! 33: * ! 34: * Redistribution and use in source and binary forms, with or without ! 35: * modification, are permitted provided that the following conditions ! 36: * are met: ! 37: * 1. Redistributions of source code must retain the above copyright ! 38: * notice, this list of conditions and the following disclaimer. ! 39: * 2. Redistributions in binary form must reproduce the above copyright ! 40: * notice, this list of conditions and the following disclaimer in the ! 41: * documentation and/or other materials provided with the distribution. ! 42: * 3. All advertising materials mentioning features or use of this software ! 43: * must display the following acknowledgement: ! 44: * This product includes software developed by the University of ! 45: * California, Berkeley and its contributors. ! 46: * 4. Neither the name of the University nor the names of its contributors ! 47: * may be used to endorse or promote products derived from this software ! 48: * without specific prior written permission. ! 49: * ! 50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 60: * SUCH DAMAGE. ! 61: * ! 62: * from: @(#)kern_physio.c 8.1 (Berkeley) 6/10/93 ! 63: */ ! 64: /* ! 65: * HISTORY ! 66: * 27-July-97 Umesh Vaishampayan ([email protected]) ! 67: * Allow physio() to kernel space. ! 68: */ ! 69: ! 70: #include <sys/param.h> ! 71: #include <sys/systm.h> ! 72: #include <sys/buf.h> ! 73: #include <sys/conf.h> ! 74: #include <sys/proc.h> ! 75: ! 76: int ! 77: physio(strategy, bp, dev, flags, minphys, uio, blocksize) ! 78: int (*strategy)(); ! 79: struct buf *bp; ! 80: dev_t dev; ! 81: int flags; ! 82: u_int (*minphys)(); ! 83: struct uio *uio; ! 84: int blocksize; ! 85: { ! 86: struct iovec *iovp; ! 87: struct proc *p = current_proc(); ! 88: int error, done, i, nobuf, s, todo; ! 89: ! 90: error = 0; ! 91: flags &= B_READ | B_WRITE; ! 92: ! 93: /* ! 94: * [check user read/write access to the data buffer] ! 95: * ! 96: * Check each iov one by one. Note that we know if we're reading or ! 97: * writing, so we ignore the uio's rw parameter. Also note that if ! 98: * we're doing a read, that's a *write* to user-space. ! 99: */ ! 100: for (i = 0; i < uio->uio_iovcnt; i++) { ! 101: if(uio->uio_segflg != UIO_SYSSPACE) { ! 102: if (!useracc(uio->uio_iov[i].iov_base, ! 103: uio->uio_iov[i].iov_len, ! 104: (flags == B_READ) ? B_WRITE : B_READ)) ! 105: return (EFAULT); ! 106: } ! 107: } ! 108: /* Make sure we have a buffer, creating one if necessary. */ ! 109: if (nobuf = (bp == NULL)) { ! 110: // bp = getphysbuf(); ! 111: panic("physio: null buf pointer\n"); ! 112: } ! 113: ! 114: /* [raise the processor priority level to splbio;] */ ! 115: s = splbio(); ! 116: ! 117: /* [while the buffer is marked busy] */ ! 118: while (bp->b_flags & B_BUSY) { ! 119: /* [mark the buffer wanted] */ ! 120: bp->b_flags |= B_WANTED; ! 121: /* [wait until the buffer is available] */ ! 122: tsleep((caddr_t)bp, PRIBIO+1, "physbuf", 0); ! 123: } ! 124: ! 125: /* Mark it busy, so nobody else will use it. */ ! 126: bp->b_flags |= B_BUSY; ! 127: ! 128: /* [lower the priority level] */ ! 129: splx(s); ! 130: ! 131: /* [set up the fixed part of the buffer for a transfer] */ ! 132: bp->b_dev = dev; ! 133: bp->b_error = 0; ! 134: bp->b_proc = p; ! 135: ! 136: /* ! 137: * [while there are data to transfer and no I/O error] ! 138: * Note that I/O errors are handled with a 'goto' at the bottom ! 139: * of the 'while' loop. ! 140: */ ! 141: for (i = 0; i < uio->uio_iovcnt; i++) { ! 142: iovp = &uio->uio_iov[i]; ! 143: while (iovp->iov_len > 0) { ! 144: /* ! 145: * [mark the buffer busy for physical I/O] ! 146: * (i.e. set B_PHYS (because it's an I/O to user ! 147: * memory, and B_RAW, because B_RAW is to be ! 148: * "Set by physio for raw transfers.", in addition ! 149: * to the "busy" and read/write flag.) ! 150: */ ! 151: s = splbio(); ! 152: bp->b_flags = B_BUSY | B_PHYS | B_RAW | flags; ! 153: splx(s); ! 154: ! 155: /* [set up the buffer for a maximum-sized transfer] */ ! 156: bp->b_blkno = uio->uio_offset / blocksize; ! 157: #if hppa ! 158: bp->b_offset = (((u_int64_t)bp->b_blkno) * (u_int64_t)blocksize); ! 159: #endif /* hppa */ ! 160: bp->b_bcount = iovp->iov_len; ! 161: bp->b_data = iovp->iov_base; ! 162: ! 163: /* ! 164: * [call minphys to bound the tranfer size] ! 165: * and remember the amount of data to transfer, ! 166: * for later comparison. ! 167: */ ! 168: (*minphys)(bp); ! 169: todo = bp->b_bcount; ! 170: ! 171: /* ! 172: * [lock the part of the user address space involved ! 173: * in the transfer] ! 174: * Beware vmapbuf(); it clobbers b_data and ! 175: * saves it in b_saveaddr. However, vunmapbuf() ! 176: * restores it. ! 177: */ ! 178: ! 179: if(uio->uio_segflg == UIO_SYSSPACE) ! 180: bp->b_flags |= B_KERNSPACE; ! 181: else ! 182: vslock(bp->b_data, todo); ! 183: ! 184: #if 0 ! 185: vmapbuf(bp, todo); ! 186: #endif /* 0 */ ! 187: /* [call strategy to start the transfer] */ ! 188: (*strategy)(bp); ! 189: ! 190: /* ! 191: * Note that the raise/wait/lower/get error ! 192: * steps below would be done by biowait(), but ! 193: * we want to unlock the address space before ! 194: * we lower the priority. ! 195: * ! 196: * [raise the priority level to splbio] ! 197: */ ! 198: s = splbio(); ! 199: ! 200: /* [wait for the transfer to complete] */ ! 201: while ((bp->b_flags & B_DONE) == 0) ! 202: tsleep((caddr_t) bp, PRIBIO + 1, "physio", 0); ! 203: ! 204: /* ! 205: * [unlock the part of the address space previously ! 206: * locked] ! 207: */ ! 208: #if 0 ! 209: vunmapbuf(bp, todo); ! 210: #endif /* 0 */ ! 211: if(uio->uio_segflg != UIO_SYSSPACE) ! 212: vsunlock(bp->b_data, todo); ! 213: ! 214: /* remember error value (save a splbio/splx pair) */ ! 215: if (bp->b_flags & B_ERROR) ! 216: error = (bp->b_error ? bp->b_error : EIO); ! 217: ! 218: /* [lower the priority level] */ ! 219: splx(s); ! 220: ! 221: /* ! 222: * [deduct the transfer size from the total number ! 223: * of data to transfer] ! 224: */ ! 225: done = bp->b_bcount - bp->b_resid; ! 226: iovp->iov_len -= done; ! 227: iovp->iov_base += done; ! 228: uio->uio_offset += done; ! 229: uio->uio_resid -= done; ! 230: ! 231: /* ! 232: * Now, check for an error. ! 233: * Also, handle weird end-of-disk semantics. ! 234: */ ! 235: if (error || done < todo) ! 236: goto done; ! 237: } ! 238: } ! 239: ! 240: done: ! 241: /* ! 242: * [clean up the state of the buffer] ! 243: * Remember if somebody wants it, so we can wake them up below. ! 244: * Also, if we had to steal it, give it back. ! 245: */ ! 246: s = splbio(); ! 247: bp->b_flags &= ~(B_BUSY | B_PHYS | B_RAW); ! 248: #if 0 ! 249: if (nobuf) ! 250: putphysbuf(bp); ! 251: ! 252: else ! 253: #endif /* 0 */ ! 254: { ! 255: /* ! 256: * [if another process is waiting for the raw I/O buffer, ! 257: * wake up processes waiting to do physical I/O; ! 258: */ ! 259: if (bp->b_flags & B_WANTED) { ! 260: bp->b_flags &= ~B_WANTED; ! 261: wakeup(bp); ! 262: } ! 263: } ! 264: splx(s); ! 265: ! 266: return (error); ! 267: } ! 268: ! 269: /* ! 270: * Leffler, et al., says on p. 231: ! 271: * "The minphys() routine is called by physio() to adjust the ! 272: * size of each I/O transfer before the latter is passed to ! 273: * the strategy routine..." ! 274: * ! 275: * so, just adjust the buffer's count accounting to MAXPHYS here, ! 276: * and return the new count; ! 277: */ ! 278: u_int ! 279: minphys(bp) ! 280: struct buf *bp; ! 281: { ! 282: ! 283: bp->b_bcount = min(MAXPHYS, bp->b_bcount); ! 284: return bp->b_bcount; ! 285: } ! 286: ! 287: /* ! 288: * Do a read on a device for a user process. ! 289: */ ! 290: rawread(dev, uio) ! 291: dev_t dev; ! 292: struct uio *uio; ! 293: { ! 294: return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, ! 295: dev, B_READ, minphys, uio)); ! 296: } ! 297: ! 298: /* ! 299: * Do a write on a device for a user process. ! 300: */ ! 301: rawwrite(dev, uio) ! 302: dev_t dev; ! 303: struct uio *uio; ! 304: { ! 305: return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, ! 306: dev, B_WRITE, minphys, uio)); ! 307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.