123461Smckusick /* 2*45730Smckusick * Copyright (c) 1982, 1986, 1990 Regents of the University of California. 3*45730Smckusick * All rights reserved. 423461Smckusick * 5*45730Smckusick * %sccs.include.redist.c% 6*45730Smckusick * 7*45730Smckusick * @(#)kern_physio.c 7.16 (Berkeley) 12/05/90 823461Smckusick */ 98Sbill 1017108Sbloom #include "param.h" 1117108Sbloom #include "systm.h" 1217108Sbloom #include "user.h" 1317108Sbloom #include "buf.h" 1417108Sbloom #include "conf.h" 1517108Sbloom #include "proc.h" 1617108Sbloom #include "seg.h" 1717108Sbloom #include "trace.h" 1817108Sbloom #include "map.h" 1937729Smckusick #include "vnode.h" 2040652Smckusick #include "specdev.h" 218Sbill 2291Sbill /* 238Sbill * Raw I/O. The arguments are 248Sbill * The strategy routine for the device 2534215Sbostic * A buffer, which will either be a special buffer header owned 2634215Sbostic * exclusively by the device for this purpose, or NULL, 2734215Sbostic * indicating that we should use a swap buffer 288Sbill * The device number 298Sbill * Read/write flag 308Sbill * Essentially all the work is computing physical addresses and 318Sbill * validating them. 328Sbill * If the user has the proper access privilidges, the process is 338Sbill * marked 'delayed unlock' and the pages involved in the I/O are 348Sbill * faulted and locked. After the completion of the I/O, the above pages 358Sbill * are unlocked. 368Sbill */ 377724Swnj physio(strat, bp, dev, rw, mincnt, uio) 387724Swnj int (*strat)(); 397724Swnj register struct buf *bp; 407724Swnj dev_t dev; 417724Swnj int rw; 4234215Sbostic u_int (*mincnt)(); 437724Swnj struct uio *uio; 448Sbill { 4517313Skarels register struct iovec *iov; 4638794Skarels register int requested, done; 478Sbill char *a; 4834215Sbostic int s, allocbuf = 0, error = 0; 4934215Sbostic struct buf *getswbuf(); 508Sbill 5134215Sbostic if (bp == NULL) { 5234215Sbostic allocbuf = 1; 5334215Sbostic bp = getswbuf(PRIBIO+1); 5434215Sbostic } 5534215Sbostic for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 5630750Skarels iov = uio->uio_iov; 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; 7130750Skarels bp->b_proc = u.u_procp; 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; 8530750Skarels u.u_procp->p_flag |= SPHYSIO; 8638794Skarels vslock(a = bp->b_un.b_addr, requested); 8744773Swilliam #if defined(hp300) || defined(i386) 8842001Smckusick vmapbuf(bp); 8942001Smckusick #endif 9034215Sbostic (*strat)(bp); 9134215Sbostic s = splbio(); 9234215Sbostic while ((bp->b_flags & B_DONE) == 0) 9334215Sbostic sleep((caddr_t)bp, PRIBIO); 9444773Swilliam #if defined(hp300) || defined(i386) 9542001Smckusick vunmapbuf(bp); 9642001Smckusick #endif 9738794Skarels vsunlock(a, requested, rw); 9830750Skarels u.u_procp->p_flag &= ~SPHYSIO; 9934215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 10030750Skarels wakeup((caddr_t)bp); 10130750Skarels splx(s); 10238794Skarels done = bp->b_bcount - bp->b_resid; 10338794Skarels bp->b_un.b_addr += done; 10438794Skarels iov->iov_len -= done; 10538794Skarels uio->uio_resid -= done; 10638794Skarels uio->uio_offset += done; 10738794Skarels /* temp kludge for disk drives */ 10838794Skarels if (done < requested || bp->b_flags & B_ERROR) 10930750Skarels break; 11030750Skarels } 11134215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 11237729Smckusick error = biowait(bp); 11338794Skarels /* temp kludge for disk drives */ 11438794Skarels if (done < requested || bp->b_flags & B_ERROR) 11534215Sbostic break; 1168Sbill } 11742001Smckusick #if defined(hp300) 11842001Smckusick DCIU(); 11942001Smckusick #endif 12034215Sbostic if (allocbuf) 12134215Sbostic freeswbuf(bp); 12234215Sbostic return (error); 1238Sbill } 1248Sbill 12534215Sbostic u_int 1268Sbill minphys(bp) 1277724Swnj struct buf *bp; 1288Sbill { 12910400Ssam if (bp->b_bcount > MAXPHYS) 13010400Ssam bp->b_bcount = MAXPHYS; 1318Sbill } 13234215Sbostic 13334215Sbostic static 13434215Sbostic struct buf * 13534215Sbostic getswbuf(prio) 13634215Sbostic int prio; 13734215Sbostic { 13834215Sbostic int s; 13934215Sbostic struct buf *bp; 14034215Sbostic 14134215Sbostic s = splbio(); 14234215Sbostic while (bswlist.av_forw == NULL) { 14334215Sbostic bswlist.b_flags |= B_WANTED; 14434215Sbostic sleep((caddr_t)&bswlist, prio); 14534215Sbostic } 14634215Sbostic bp = bswlist.av_forw; 14734215Sbostic bswlist.av_forw = bp->av_forw; 14834215Sbostic splx(s); 14934215Sbostic return (bp); 15034215Sbostic } 15134215Sbostic 15234215Sbostic static 15334215Sbostic freeswbuf(bp) 15434215Sbostic struct buf *bp; 15534215Sbostic { 15634215Sbostic int s; 15734215Sbostic 15834215Sbostic s = splbio(); 15934215Sbostic bp->av_forw = bswlist.av_forw; 16034215Sbostic bswlist.av_forw = bp; 16139148Smckusick if (bp->b_vp) 16239148Smckusick brelvp(bp); 16334215Sbostic if (bswlist.b_flags & B_WANTED) { 16434215Sbostic bswlist.b_flags &= ~B_WANTED; 16534215Sbostic wakeup((caddr_t)&bswlist); 16634215Sbostic wakeup((caddr_t)&proc[2]); 16734215Sbostic } 16834215Sbostic splx(s); 16934215Sbostic } 17034215Sbostic 17134215Sbostic rawread(dev, uio) 17234215Sbostic dev_t dev; 17334215Sbostic struct uio *uio; 17434215Sbostic { 17534215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 17634215Sbostic dev, B_READ, minphys, uio)); 17734215Sbostic } 17834215Sbostic 17934215Sbostic rawwrite(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_WRITE, minphys, uio)); 18534215Sbostic } 186