149589Sbostic /*- 249589Sbostic * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 349589Sbostic * All rights reserved. 423461Smckusick * 549589Sbostic * %sccs.include.proprietary.c% 649589Sbostic * 7*49672Smckusick * @(#)kern_physio.c 7.20 (Berkeley) 05/11/91 823461Smckusick */ 98Sbill 1017108Sbloom #include "param.h" 1117108Sbloom #include "systm.h" 1217108Sbloom #include "buf.h" 1317108Sbloom #include "conf.h" 1417108Sbloom #include "proc.h" 1517108Sbloom #include "seg.h" 1617108Sbloom #include "trace.h" 1717108Sbloom #include "map.h" 1837729Smckusick #include "vnode.h" 1940652Smckusick #include "specdev.h" 208Sbill 2148414Skarels #ifdef HPUXCOMPAT 2248414Skarels #include "user.h" 2348414Skarels #endif 2448414Skarels 2548414Skarels static struct buf *getswbuf(); 2648414Skarels static freeswbuf(); 2748414Skarels 2891Sbill /* 29*49672Smckusick * This routine does device I/O for a user process. 30*49672Smckusick * 318Sbill * If the user has the proper access privilidges, the process is 328Sbill * marked 'delayed unlock' and the pages involved in the I/O are 33*49672Smckusick * faulted and locked. After the completion of the I/O, the pages 348Sbill * are unlocked. 358Sbill */ 367724Swnj physio(strat, bp, dev, rw, mincnt, uio) 377724Swnj int (*strat)(); 387724Swnj register struct buf *bp; 397724Swnj dev_t dev; 407724Swnj int rw; 4134215Sbostic u_int (*mincnt)(); 427724Swnj struct uio *uio; 438Sbill { 4417313Skarels register struct iovec *iov; 4538794Skarels register int requested, done; 4647540Skarels register struct proc *p = curproc; 478Sbill char *a; 4834215Sbostic int s, allocbuf = 0, error = 0; 498Sbill 5034215Sbostic if (bp == NULL) { 5134215Sbostic allocbuf = 1; 5234215Sbostic bp = getswbuf(PRIBIO+1); 5334215Sbostic } 5434215Sbostic for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 5530750Skarels iov = uio->uio_iov; 5634215Sbostic if (!useracc(iov->iov_base, (u_int)iov->iov_len, 5734215Sbostic rw == B_READ ? B_WRITE : B_READ)) { 5834215Sbostic error = EFAULT; 5934215Sbostic break; 6030750Skarels } 6134215Sbostic if (!allocbuf) { /* only if sharing caller's buffer */ 6234215Sbostic s = splbio(); 6334215Sbostic while (bp->b_flags&B_BUSY) { 6434215Sbostic bp->b_flags |= B_WANTED; 6534215Sbostic sleep((caddr_t)bp, PRIBIO+1); 6634215Sbostic } 6734215Sbostic splx(s); 6834215Sbostic } 6930750Skarels bp->b_error = 0; 7047540Skarels bp->b_proc = p; 7142001Smckusick #ifdef HPUXCOMPAT 7242001Smckusick if (ISHPMMADDR(iov->iov_base)) 7342001Smckusick bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 7442001Smckusick else 7542001Smckusick #endif 7630750Skarels bp->b_un.b_addr = iov->iov_base; 7730750Skarels while (iov->iov_len > 0) { 7834215Sbostic bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 7930750Skarels bp->b_dev = dev; 8030750Skarels bp->b_blkno = btodb(uio->uio_offset); 8130750Skarels bp->b_bcount = iov->iov_len; 8230750Skarels (*mincnt)(bp); 8338794Skarels requested = bp->b_bcount; 8447540Skarels p->p_flag |= SPHYSIO; 8538794Skarels vslock(a = bp->b_un.b_addr, requested); 8644773Swilliam #if defined(hp300) || defined(i386) 8742001Smckusick vmapbuf(bp); 8842001Smckusick #endif 8934215Sbostic (*strat)(bp); 9034215Sbostic s = splbio(); 9134215Sbostic while ((bp->b_flags & B_DONE) == 0) 9234215Sbostic sleep((caddr_t)bp, PRIBIO); 9344773Swilliam #if defined(hp300) || defined(i386) 9442001Smckusick vunmapbuf(bp); 9542001Smckusick #endif 9638794Skarels vsunlock(a, requested, rw); 9747540Skarels p->p_flag &= ~SPHYSIO; 9834215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 9930750Skarels wakeup((caddr_t)bp); 10030750Skarels splx(s); 10138794Skarels done = bp->b_bcount - bp->b_resid; 10238794Skarels bp->b_un.b_addr += done; 10338794Skarels iov->iov_len -= done; 10438794Skarels uio->uio_resid -= done; 10538794Skarels uio->uio_offset += done; 10638794Skarels /* temp kludge for disk drives */ 10738794Skarels if (done < requested || bp->b_flags & B_ERROR) 10830750Skarels break; 10930750Skarels } 11034215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 11137729Smckusick error = biowait(bp); 11238794Skarels /* temp kludge for disk drives */ 11338794Skarels if (done < requested || bp->b_flags & B_ERROR) 11434215Sbostic break; 1158Sbill } 11642001Smckusick #if defined(hp300) 11742001Smckusick DCIU(); 11842001Smckusick #endif 11934215Sbostic if (allocbuf) 12034215Sbostic freeswbuf(bp); 12134215Sbostic return (error); 1228Sbill } 1238Sbill 124*49672Smckusick /* 125*49672Smckusick * Calculate the maximum size of I/O request that can be requested 126*49672Smckusick * in a single operation. This limit is necessary to prevent a single 127*49672Smckusick * process from being able to lock more than a fixed amount of memory 128*49672Smckusick * in the kernel. 129*49672Smckusick */ 13034215Sbostic u_int 1318Sbill minphys(bp) 1327724Swnj struct buf *bp; 1338Sbill { 13410400Ssam if (bp->b_bcount > MAXPHYS) 13510400Ssam bp->b_bcount = MAXPHYS; 1368Sbill } 13734215Sbostic 13834215Sbostic static 13934215Sbostic struct buf * 14034215Sbostic getswbuf(prio) 14134215Sbostic int prio; 14234215Sbostic { 14334215Sbostic int s; 14434215Sbostic struct buf *bp; 14534215Sbostic 14634215Sbostic s = splbio(); 14734215Sbostic while (bswlist.av_forw == NULL) { 14834215Sbostic bswlist.b_flags |= B_WANTED; 14934215Sbostic sleep((caddr_t)&bswlist, prio); 15034215Sbostic } 15134215Sbostic bp = bswlist.av_forw; 15234215Sbostic bswlist.av_forw = bp->av_forw; 15334215Sbostic splx(s); 15434215Sbostic return (bp); 15534215Sbostic } 15634215Sbostic 15734215Sbostic static 15834215Sbostic freeswbuf(bp) 15934215Sbostic struct buf *bp; 16034215Sbostic { 16134215Sbostic int s; 16234215Sbostic 16334215Sbostic s = splbio(); 16434215Sbostic bp->av_forw = bswlist.av_forw; 16534215Sbostic bswlist.av_forw = bp; 16639148Smckusick if (bp->b_vp) 16739148Smckusick brelvp(bp); 16834215Sbostic if (bswlist.b_flags & B_WANTED) { 16934215Sbostic bswlist.b_flags &= ~B_WANTED; 17034215Sbostic wakeup((caddr_t)&bswlist); 17147540Skarels wakeup((caddr_t)pageproc); 17234215Sbostic } 17334215Sbostic splx(s); 17434215Sbostic } 17534215Sbostic 176*49672Smckusick /* 177*49672Smckusick * Do a read on a device for a user process. 178*49672Smckusick */ 17934215Sbostic rawread(dev, uio) 18034215Sbostic dev_t dev; 18134215Sbostic struct uio *uio; 18234215Sbostic { 18334215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18434215Sbostic dev, B_READ, minphys, uio)); 18534215Sbostic } 18634215Sbostic 187*49672Smckusick /* 188*49672Smckusick * Do a write on a device for a user process. 189*49672Smckusick */ 19034215Sbostic rawwrite(dev, uio) 19134215Sbostic dev_t dev; 19234215Sbostic struct uio *uio; 19334215Sbostic { 19434215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 19534215Sbostic dev, B_WRITE, minphys, uio)); 19634215Sbostic } 197