1 /* 2 * Copyright (c) 1982, 1986, 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_physio.c 7.16 (Berkeley) 12/05/90 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "user.h" 13 #include "buf.h" 14 #include "conf.h" 15 #include "proc.h" 16 #include "seg.h" 17 #include "trace.h" 18 #include "map.h" 19 #include "vnode.h" 20 #include "specdev.h" 21 22 /* 23 * Raw I/O. The arguments are 24 * The strategy routine for the device 25 * A buffer, which will either be a special buffer header owned 26 * exclusively by the device for this purpose, or NULL, 27 * indicating that we should use a swap buffer 28 * The device number 29 * Read/write flag 30 * Essentially all the work is computing physical addresses and 31 * validating them. 32 * If the user has the proper access privilidges, the process is 33 * marked 'delayed unlock' and the pages involved in the I/O are 34 * faulted and locked. After the completion of the I/O, the above pages 35 * are unlocked. 36 */ 37 physio(strat, bp, dev, rw, mincnt, uio) 38 int (*strat)(); 39 register struct buf *bp; 40 dev_t dev; 41 int rw; 42 u_int (*mincnt)(); 43 struct uio *uio; 44 { 45 register struct iovec *iov; 46 register int requested, done; 47 char *a; 48 int s, allocbuf = 0, error = 0; 49 struct buf *getswbuf(); 50 51 if (bp == NULL) { 52 allocbuf = 1; 53 bp = getswbuf(PRIBIO+1); 54 } 55 for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 56 iov = uio->uio_iov; 57 if (!useracc(iov->iov_base, (u_int)iov->iov_len, 58 rw == B_READ ? B_WRITE : B_READ)) { 59 error = EFAULT; 60 break; 61 } 62 if (!allocbuf) { /* only if sharing caller's buffer */ 63 s = splbio(); 64 while (bp->b_flags&B_BUSY) { 65 bp->b_flags |= B_WANTED; 66 sleep((caddr_t)bp, PRIBIO+1); 67 } 68 splx(s); 69 } 70 bp->b_error = 0; 71 bp->b_proc = u.u_procp; 72 #ifdef HPUXCOMPAT 73 if (ISHPMMADDR(iov->iov_base)) 74 bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 75 else 76 #endif 77 bp->b_un.b_addr = iov->iov_base; 78 while (iov->iov_len > 0) { 79 bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 80 bp->b_dev = dev; 81 bp->b_blkno = btodb(uio->uio_offset); 82 bp->b_bcount = iov->iov_len; 83 (*mincnt)(bp); 84 requested = bp->b_bcount; 85 u.u_procp->p_flag |= SPHYSIO; 86 vslock(a = bp->b_un.b_addr, requested); 87 #if defined(hp300) || defined(i386) 88 vmapbuf(bp); 89 #endif 90 (*strat)(bp); 91 s = splbio(); 92 while ((bp->b_flags & B_DONE) == 0) 93 sleep((caddr_t)bp, PRIBIO); 94 #if defined(hp300) || defined(i386) 95 vunmapbuf(bp); 96 #endif 97 vsunlock(a, requested, rw); 98 u.u_procp->p_flag &= ~SPHYSIO; 99 if (bp->b_flags&B_WANTED) /* rare */ 100 wakeup((caddr_t)bp); 101 splx(s); 102 done = bp->b_bcount - bp->b_resid; 103 bp->b_un.b_addr += done; 104 iov->iov_len -= done; 105 uio->uio_resid -= done; 106 uio->uio_offset += done; 107 /* temp kludge for disk drives */ 108 if (done < requested || bp->b_flags & B_ERROR) 109 break; 110 } 111 bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 112 error = biowait(bp); 113 /* temp kludge for disk drives */ 114 if (done < requested || bp->b_flags & B_ERROR) 115 break; 116 } 117 #if defined(hp300) 118 DCIU(); 119 #endif 120 if (allocbuf) 121 freeswbuf(bp); 122 return (error); 123 } 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 134 struct buf * 135 getswbuf(prio) 136 int prio; 137 { 138 int s; 139 struct buf *bp; 140 141 s = splbio(); 142 while (bswlist.av_forw == NULL) { 143 bswlist.b_flags |= B_WANTED; 144 sleep((caddr_t)&bswlist, prio); 145 } 146 bp = bswlist.av_forw; 147 bswlist.av_forw = bp->av_forw; 148 splx(s); 149 return (bp); 150 } 151 152 static 153 freeswbuf(bp) 154 struct buf *bp; 155 { 156 int s; 157 158 s = splbio(); 159 bp->av_forw = bswlist.av_forw; 160 bswlist.av_forw = bp; 161 if (bp->b_vp) 162 brelvp(bp); 163 if (bswlist.b_flags & B_WANTED) { 164 bswlist.b_flags &= ~B_WANTED; 165 wakeup((caddr_t)&bswlist); 166 wakeup((caddr_t)&proc[2]); 167 } 168 splx(s); 169 } 170 171 rawread(dev, uio) 172 dev_t dev; 173 struct uio *uio; 174 { 175 return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 176 dev, B_READ, minphys, uio)); 177 } 178 179 rawwrite(dev, uio) 180 dev_t dev; 181 struct uio *uio; 182 { 183 return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 184 dev, B_WRITE, minphys, uio)); 185 } 186