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*51759Storek * @(#)kern_physio.c 7.23 (Berkeley) 11/19/91 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 * 30*51759Storek * 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; 4438794Skarels register int requested, done; 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; 5534215Sbostic if (!useracc(iov->iov_base, (u_int)iov->iov_len, 5634215Sbostic rw == B_READ ? B_WRITE : B_READ)) { 5734215Sbostic error = EFAULT; 5834215Sbostic break; 5930750Skarels } 6034215Sbostic if (!allocbuf) { /* only if sharing caller's buffer */ 6134215Sbostic s = splbio(); 6234215Sbostic while (bp->b_flags&B_BUSY) { 6334215Sbostic bp->b_flags |= B_WANTED; 6434215Sbostic sleep((caddr_t)bp, PRIBIO+1); 6534215Sbostic } 6634215Sbostic splx(s); 6734215Sbostic } 6830750Skarels bp->b_error = 0; 6947540Skarels bp->b_proc = p; 7042001Smckusick #ifdef HPUXCOMPAT 7142001Smckusick if (ISHPMMADDR(iov->iov_base)) 7242001Smckusick bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 7342001Smckusick else 7442001Smckusick #endif 7530750Skarels bp->b_un.b_addr = iov->iov_base; 7630750Skarels while (iov->iov_len > 0) { 7734215Sbostic bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 7830750Skarels bp->b_dev = dev; 7930750Skarels bp->b_blkno = btodb(uio->uio_offset); 8030750Skarels bp->b_bcount = iov->iov_len; 8130750Skarels (*mincnt)(bp); 8238794Skarels requested = bp->b_bcount; 8347540Skarels p->p_flag |= SPHYSIO; 8438794Skarels vslock(a = bp->b_un.b_addr, requested); 8542001Smckusick vmapbuf(bp); 8634215Sbostic (*strat)(bp); 8734215Sbostic s = splbio(); 8834215Sbostic while ((bp->b_flags & B_DONE) == 0) 8934215Sbostic sleep((caddr_t)bp, PRIBIO); 9042001Smckusick vunmapbuf(bp); 9138794Skarels vsunlock(a, requested, rw); 9247540Skarels p->p_flag &= ~SPHYSIO; 9334215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 9430750Skarels wakeup((caddr_t)bp); 9530750Skarels splx(s); 9638794Skarels done = bp->b_bcount - bp->b_resid; 9738794Skarels bp->b_un.b_addr += done; 9838794Skarels iov->iov_len -= done; 9938794Skarels uio->uio_resid -= done; 10038794Skarels uio->uio_offset += done; 10138794Skarels /* temp kludge for disk drives */ 10238794Skarels if (done < requested || bp->b_flags & B_ERROR) 10330750Skarels break; 10430750Skarels } 10534215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 10637729Smckusick error = biowait(bp); 10738794Skarels /* temp kludge for disk drives */ 10838794Skarels if (done < requested || bp->b_flags & B_ERROR) 10934215Sbostic break; 1108Sbill } 11142001Smckusick #if defined(hp300) 11242001Smckusick DCIU(); 11342001Smckusick #endif 11434215Sbostic if (allocbuf) 11534215Sbostic freeswbuf(bp); 11634215Sbostic return (error); 1178Sbill } 1188Sbill 11949672Smckusick /* 12049672Smckusick * Calculate the maximum size of I/O request that can be requested 12149672Smckusick * in a single operation. This limit is necessary to prevent a single 12249672Smckusick * process from being able to lock more than a fixed amount of memory 12349672Smckusick * in the kernel. 12449672Smckusick */ 12534215Sbostic u_int 1268Sbill minphys(bp) 1277724Swnj struct buf *bp; 1288Sbill { 12910400Ssam if (bp->b_bcount > MAXPHYS) 13010400Ssam bp->b_bcount = MAXPHYS; 1318Sbill } 13234215Sbostic 13351454Sbostic static struct buf * 13434215Sbostic getswbuf(prio) 13534215Sbostic int prio; 13634215Sbostic { 13734215Sbostic int s; 13834215Sbostic struct buf *bp; 13934215Sbostic 14034215Sbostic s = splbio(); 14134215Sbostic while (bswlist.av_forw == NULL) { 14234215Sbostic bswlist.b_flags |= B_WANTED; 14334215Sbostic sleep((caddr_t)&bswlist, prio); 14434215Sbostic } 14534215Sbostic bp = bswlist.av_forw; 14634215Sbostic bswlist.av_forw = bp->av_forw; 14734215Sbostic splx(s); 14834215Sbostic return (bp); 14934215Sbostic } 15034215Sbostic 15151454Sbostic static void 15234215Sbostic freeswbuf(bp) 15334215Sbostic struct buf *bp; 15434215Sbostic { 15534215Sbostic int s; 15634215Sbostic 15734215Sbostic s = splbio(); 15834215Sbostic bp->av_forw = bswlist.av_forw; 15934215Sbostic bswlist.av_forw = bp; 16039148Smckusick if (bp->b_vp) 16139148Smckusick brelvp(bp); 16234215Sbostic if (bswlist.b_flags & B_WANTED) { 16334215Sbostic bswlist.b_flags &= ~B_WANTED; 16434215Sbostic wakeup((caddr_t)&bswlist); 16547540Skarels wakeup((caddr_t)pageproc); 16634215Sbostic } 16734215Sbostic splx(s); 16834215Sbostic } 16934215Sbostic 17049672Smckusick /* 17149672Smckusick * Do a read on a device for a user process. 17249672Smckusick */ 17334215Sbostic rawread(dev, uio) 17434215Sbostic dev_t dev; 17534215Sbostic struct uio *uio; 17634215Sbostic { 17734215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 17834215Sbostic dev, B_READ, minphys, uio)); 17934215Sbostic } 18034215Sbostic 18149672Smckusick /* 18249672Smckusick * Do a write on a device for a user process. 18349672Smckusick */ 18434215Sbostic rawwrite(dev, uio) 18534215Sbostic dev_t dev; 18634215Sbostic struct uio *uio; 18734215Sbostic { 18834215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18934215Sbostic dev, B_WRITE, minphys, uio)); 19034215Sbostic } 191