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