1 /*- 2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 * 7 * @(#)kern_physio.c 7.23 (Berkeley) 11/19/91 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/buf.h> 13 #include <sys/conf.h> 14 #include <sys/proc.h> 15 #include <sys/trace.h> 16 #include <sys/map.h> 17 #include <sys/vnode.h> 18 #include <sys/specdev.h> 19 20 #ifdef HPUXCOMPAT 21 #include <sys/user.h> 22 #endif 23 24 static void freeswbuf __P((struct buf *)); 25 static struct buf *getswbuf __P((int)); 26 27 /* 28 * This routine does device I/O for a user process. 29 * 30 * If the user has the proper access privileges, the process is 31 * marked 'delayed unlock' and the pages involved in the I/O are 32 * faulted and locked. After the completion of the I/O, the pages 33 * are unlocked. 34 */ 35 physio(strat, bp, dev, rw, mincnt, uio) 36 int (*strat)(); 37 register struct buf *bp; 38 dev_t dev; 39 int rw; 40 u_int (*mincnt)(); 41 struct uio *uio; 42 { 43 register struct iovec *iov; 44 register int requested, done; 45 register struct proc *p = curproc; 46 char *a; 47 int s, allocbuf = 0, error = 0; 48 49 if (bp == NULL) { 50 allocbuf = 1; 51 bp = getswbuf(PRIBIO+1); 52 } 53 for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 54 iov = uio->uio_iov; 55 if (!useracc(iov->iov_base, (u_int)iov->iov_len, 56 rw == B_READ ? B_WRITE : B_READ)) { 57 error = EFAULT; 58 break; 59 } 60 if (!allocbuf) { /* only if sharing caller's buffer */ 61 s = splbio(); 62 while (bp->b_flags&B_BUSY) { 63 bp->b_flags |= B_WANTED; 64 sleep((caddr_t)bp, PRIBIO+1); 65 } 66 splx(s); 67 } 68 bp->b_error = 0; 69 bp->b_proc = p; 70 #ifdef HPUXCOMPAT 71 if (ISHPMMADDR(iov->iov_base)) 72 bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 73 else 74 #endif 75 bp->b_un.b_addr = iov->iov_base; 76 while (iov->iov_len > 0) { 77 bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 78 bp->b_dev = dev; 79 bp->b_blkno = btodb(uio->uio_offset); 80 bp->b_bcount = iov->iov_len; 81 (*mincnt)(bp); 82 requested = bp->b_bcount; 83 p->p_flag |= SPHYSIO; 84 vslock(a = bp->b_un.b_addr, requested); 85 vmapbuf(bp); 86 (*strat)(bp); 87 s = splbio(); 88 while ((bp->b_flags & B_DONE) == 0) 89 sleep((caddr_t)bp, PRIBIO); 90 vunmapbuf(bp); 91 vsunlock(a, requested, rw); 92 p->p_flag &= ~SPHYSIO; 93 if (bp->b_flags&B_WANTED) /* rare */ 94 wakeup((caddr_t)bp); 95 splx(s); 96 done = bp->b_bcount - bp->b_resid; 97 bp->b_un.b_addr += done; 98 iov->iov_len -= done; 99 uio->uio_resid -= done; 100 uio->uio_offset += done; 101 /* temp kludge for disk drives */ 102 if (done < requested || bp->b_flags & B_ERROR) 103 break; 104 } 105 bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 106 error = biowait(bp); 107 /* temp kludge for disk drives */ 108 if (done < requested || bp->b_flags & B_ERROR) 109 break; 110 } 111 #if defined(hp300) 112 DCIU(); 113 #endif 114 if (allocbuf) 115 freeswbuf(bp); 116 return (error); 117 } 118 119 /* 120 * Calculate the maximum size of I/O request that can be requested 121 * in a single operation. This limit is necessary to prevent a single 122 * process from being able to lock more than a fixed amount of memory 123 * in the kernel. 124 */ 125 u_int 126 minphys(bp) 127 struct buf *bp; 128 { 129 if (bp->b_bcount > MAXPHYS) 130 bp->b_bcount = MAXPHYS; 131 } 132 133 static struct buf * 134 getswbuf(prio) 135 int prio; 136 { 137 int s; 138 struct buf *bp; 139 140 s = splbio(); 141 while (bswlist.av_forw == NULL) { 142 bswlist.b_flags |= B_WANTED; 143 sleep((caddr_t)&bswlist, prio); 144 } 145 bp = bswlist.av_forw; 146 bswlist.av_forw = bp->av_forw; 147 splx(s); 148 return (bp); 149 } 150 151 static void 152 freeswbuf(bp) 153 struct buf *bp; 154 { 155 int s; 156 157 s = splbio(); 158 bp->av_forw = bswlist.av_forw; 159 bswlist.av_forw = bp; 160 if (bp->b_vp) 161 brelvp(bp); 162 if (bswlist.b_flags & B_WANTED) { 163 bswlist.b_flags &= ~B_WANTED; 164 wakeup((caddr_t)&bswlist); 165 wakeup((caddr_t)pageproc); 166 } 167 splx(s); 168 } 169 170 /* 171 * Do a read on a device for a user process. 172 */ 173 rawread(dev, uio) 174 dev_t dev; 175 struct uio *uio; 176 { 177 return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 178 dev, B_READ, minphys, uio)); 179 } 180 181 /* 182 * Do a write on a device for a user process. 183 */ 184 rawwrite(dev, uio) 185 dev_t dev; 186 struct uio *uio; 187 { 188 return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 189 dev, B_WRITE, minphys, uio)); 190 } 191