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*52424Storek * @(#)kern_physio.c 7.24 (Berkeley) 02/05/92 823461Smckusick */ 98Sbill 1051454Sbostic #include <sys/param.h> 1151454Sbostic #include <sys/systm.h> 1251454Sbostic #include <sys/buf.h> 1351454Sbostic #include <sys/conf.h> 1451454Sbostic #include <sys/proc.h> 1551454Sbostic #include <sys/trace.h> 1651454Sbostic #include <sys/map.h> 1751454Sbostic #include <sys/vnode.h> 1851454Sbostic #include <sys/specdev.h> 198Sbill 2048414Skarels #ifdef HPUXCOMPAT 2151454Sbostic #include <sys/user.h> 2248414Skarels #endif 2348414Skarels 2451454Sbostic static void freeswbuf __P((struct buf *)); 2551454Sbostic static struct buf *getswbuf __P((int)); 2648414Skarels 2791Sbill /* 2849672Smckusick * This routine does device I/O for a user process. 2949672Smckusick * 3051759Storek * If the user has the proper access privileges, the process is 318Sbill * marked 'delayed unlock' and the pages involved in the I/O are 3249672Smckusick * faulted and locked. After the completion of the I/O, the pages 338Sbill * are unlocked. 348Sbill */ 357724Swnj physio(strat, bp, dev, rw, mincnt, uio) 367724Swnj int (*strat)(); 377724Swnj register struct buf *bp; 387724Swnj dev_t dev; 397724Swnj int rw; 4034215Sbostic u_int (*mincnt)(); 417724Swnj struct uio *uio; 428Sbill { 4317313Skarels register struct iovec *iov; 44*52424Storek register int requested = 0, done = 0; 4547540Skarels register struct proc *p = curproc; 468Sbill char *a; 4734215Sbostic int s, allocbuf = 0, error = 0; 488Sbill 4934215Sbostic if (bp == NULL) { 5034215Sbostic allocbuf = 1; 5134215Sbostic bp = getswbuf(PRIBIO+1); 5234215Sbostic } 5334215Sbostic for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 5430750Skarels iov = uio->uio_iov; 55*52424Storek if (iov->iov_len == 0) 56*52424Storek continue; 5734215Sbostic if (!useracc(iov->iov_base, (u_int)iov->iov_len, 5834215Sbostic rw == B_READ ? B_WRITE : B_READ)) { 5934215Sbostic error = EFAULT; 6034215Sbostic break; 6130750Skarels } 6234215Sbostic if (!allocbuf) { /* only if sharing caller's buffer */ 6334215Sbostic s = splbio(); 6434215Sbostic while (bp->b_flags&B_BUSY) { 6534215Sbostic bp->b_flags |= B_WANTED; 6634215Sbostic sleep((caddr_t)bp, PRIBIO+1); 6734215Sbostic } 6834215Sbostic splx(s); 6934215Sbostic } 7030750Skarels bp->b_error = 0; 7147540Skarels bp->b_proc = p; 7242001Smckusick #ifdef HPUXCOMPAT 7342001Smckusick if (ISHPMMADDR(iov->iov_base)) 7442001Smckusick bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 7542001Smckusick else 7642001Smckusick #endif 7730750Skarels bp->b_un.b_addr = iov->iov_base; 7830750Skarels while (iov->iov_len > 0) { 7934215Sbostic bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 8030750Skarels bp->b_dev = dev; 8130750Skarels bp->b_blkno = btodb(uio->uio_offset); 8230750Skarels bp->b_bcount = iov->iov_len; 8330750Skarels (*mincnt)(bp); 8438794Skarels requested = bp->b_bcount; 8547540Skarels p->p_flag |= SPHYSIO; 8638794Skarels vslock(a = bp->b_un.b_addr, requested); 8742001Smckusick vmapbuf(bp); 8834215Sbostic (*strat)(bp); 8934215Sbostic s = splbio(); 9034215Sbostic while ((bp->b_flags & B_DONE) == 0) 9134215Sbostic sleep((caddr_t)bp, PRIBIO); 9242001Smckusick vunmapbuf(bp); 9338794Skarels vsunlock(a, requested, rw); 9447540Skarels p->p_flag &= ~SPHYSIO; 9534215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 9630750Skarels wakeup((caddr_t)bp); 9730750Skarels splx(s); 9838794Skarels done = bp->b_bcount - bp->b_resid; 9938794Skarels bp->b_un.b_addr += done; 10038794Skarels iov->iov_len -= done; 10138794Skarels uio->uio_resid -= done; 10238794Skarels uio->uio_offset += done; 10338794Skarels /* temp kludge for disk drives */ 10438794Skarels if (done < requested || bp->b_flags & B_ERROR) 10530750Skarels break; 10630750Skarels } 10734215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 10837729Smckusick error = biowait(bp); 10938794Skarels /* temp kludge for disk drives */ 11038794Skarels if (done < requested || bp->b_flags & B_ERROR) 11134215Sbostic break; 1128Sbill } 11342001Smckusick #if defined(hp300) 11442001Smckusick DCIU(); 11542001Smckusick #endif 11634215Sbostic if (allocbuf) 11734215Sbostic freeswbuf(bp); 11834215Sbostic return (error); 1198Sbill } 1208Sbill 12149672Smckusick /* 12249672Smckusick * Calculate the maximum size of I/O request that can be requested 12349672Smckusick * in a single operation. This limit is necessary to prevent a single 12449672Smckusick * process from being able to lock more than a fixed amount of memory 12549672Smckusick * in the kernel. 12649672Smckusick */ 12734215Sbostic u_int 1288Sbill minphys(bp) 1297724Swnj struct buf *bp; 1308Sbill { 13110400Ssam if (bp->b_bcount > MAXPHYS) 13210400Ssam bp->b_bcount = MAXPHYS; 1338Sbill } 13434215Sbostic 13551454Sbostic static struct buf * 13634215Sbostic getswbuf(prio) 13734215Sbostic int prio; 13834215Sbostic { 13934215Sbostic int s; 14034215Sbostic struct buf *bp; 14134215Sbostic 14234215Sbostic s = splbio(); 14334215Sbostic while (bswlist.av_forw == NULL) { 14434215Sbostic bswlist.b_flags |= B_WANTED; 14534215Sbostic sleep((caddr_t)&bswlist, prio); 14634215Sbostic } 14734215Sbostic bp = bswlist.av_forw; 14834215Sbostic bswlist.av_forw = bp->av_forw; 14934215Sbostic splx(s); 15034215Sbostic return (bp); 15134215Sbostic } 15234215Sbostic 15351454Sbostic static void 15434215Sbostic freeswbuf(bp) 15534215Sbostic struct buf *bp; 15634215Sbostic { 15734215Sbostic int s; 15834215Sbostic 15934215Sbostic s = splbio(); 16034215Sbostic bp->av_forw = bswlist.av_forw; 16134215Sbostic bswlist.av_forw = bp; 16239148Smckusick if (bp->b_vp) 16339148Smckusick brelvp(bp); 16434215Sbostic if (bswlist.b_flags & B_WANTED) { 16534215Sbostic bswlist.b_flags &= ~B_WANTED; 16634215Sbostic wakeup((caddr_t)&bswlist); 16747540Skarels wakeup((caddr_t)pageproc); 16834215Sbostic } 16934215Sbostic splx(s); 17034215Sbostic } 17134215Sbostic 17249672Smckusick /* 17349672Smckusick * Do a read on a device for a user process. 17449672Smckusick */ 17534215Sbostic rawread(dev, uio) 17634215Sbostic dev_t dev; 17734215Sbostic struct uio *uio; 17834215Sbostic { 17934215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18034215Sbostic dev, B_READ, minphys, uio)); 18134215Sbostic } 18234215Sbostic 18349672Smckusick /* 18449672Smckusick * Do a write on a device for a user process. 18549672Smckusick */ 18634215Sbostic rawwrite(dev, uio) 18734215Sbostic dev_t dev; 18834215Sbostic struct uio *uio; 18934215Sbostic { 19034215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 19134215Sbostic dev, B_WRITE, minphys, uio)); 19234215Sbostic } 193