1*49589Sbostic /*- 2*49589Sbostic * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 3*49589Sbostic * All rights reserved. 423461Smckusick * 5*49589Sbostic * %sccs.include.proprietary.c% 6*49589Sbostic * 7*49589Sbostic * @(#)kern_physio.c 7.19 (Berkeley) 05/09/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 /* 298Sbill * Raw I/O. The arguments are 308Sbill * The strategy routine for the device 3134215Sbostic * A buffer, which will either be a special buffer header owned 3234215Sbostic * exclusively by the device for this purpose, or NULL, 3334215Sbostic * indicating that we should use a swap buffer 348Sbill * The device number 358Sbill * Read/write flag 368Sbill * Essentially all the work is computing physical addresses and 378Sbill * validating them. 388Sbill * If the user has the proper access privilidges, the process is 398Sbill * marked 'delayed unlock' and the pages involved in the I/O are 408Sbill * faulted and locked. After the completion of the I/O, the above pages 418Sbill * are unlocked. 428Sbill */ 437724Swnj physio(strat, bp, dev, rw, mincnt, uio) 447724Swnj int (*strat)(); 457724Swnj register struct buf *bp; 467724Swnj dev_t dev; 477724Swnj int rw; 4834215Sbostic u_int (*mincnt)(); 497724Swnj struct uio *uio; 508Sbill { 5117313Skarels register struct iovec *iov; 5238794Skarels register int requested, done; 5347540Skarels register struct proc *p = curproc; 548Sbill char *a; 5534215Sbostic int s, allocbuf = 0, error = 0; 568Sbill 5734215Sbostic if (bp == NULL) { 5834215Sbostic allocbuf = 1; 5934215Sbostic bp = getswbuf(PRIBIO+1); 6034215Sbostic } 6134215Sbostic for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 6230750Skarels iov = uio->uio_iov; 6334215Sbostic if (!useracc(iov->iov_base, (u_int)iov->iov_len, 6434215Sbostic rw == B_READ ? B_WRITE : B_READ)) { 6534215Sbostic error = EFAULT; 6634215Sbostic break; 6730750Skarels } 6834215Sbostic if (!allocbuf) { /* only if sharing caller's buffer */ 6934215Sbostic s = splbio(); 7034215Sbostic while (bp->b_flags&B_BUSY) { 7134215Sbostic bp->b_flags |= B_WANTED; 7234215Sbostic sleep((caddr_t)bp, PRIBIO+1); 7334215Sbostic } 7434215Sbostic splx(s); 7534215Sbostic } 7630750Skarels bp->b_error = 0; 7747540Skarels bp->b_proc = p; 7842001Smckusick #ifdef HPUXCOMPAT 7942001Smckusick if (ISHPMMADDR(iov->iov_base)) 8042001Smckusick bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 8142001Smckusick else 8242001Smckusick #endif 8330750Skarels bp->b_un.b_addr = iov->iov_base; 8430750Skarels while (iov->iov_len > 0) { 8534215Sbostic bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 8630750Skarels bp->b_dev = dev; 8730750Skarels bp->b_blkno = btodb(uio->uio_offset); 8830750Skarels bp->b_bcount = iov->iov_len; 8930750Skarels (*mincnt)(bp); 9038794Skarels requested = bp->b_bcount; 9147540Skarels p->p_flag |= SPHYSIO; 9238794Skarels vslock(a = bp->b_un.b_addr, requested); 9344773Swilliam #if defined(hp300) || defined(i386) 9442001Smckusick vmapbuf(bp); 9542001Smckusick #endif 9634215Sbostic (*strat)(bp); 9734215Sbostic s = splbio(); 9834215Sbostic while ((bp->b_flags & B_DONE) == 0) 9934215Sbostic sleep((caddr_t)bp, PRIBIO); 10044773Swilliam #if defined(hp300) || defined(i386) 10142001Smckusick vunmapbuf(bp); 10242001Smckusick #endif 10338794Skarels vsunlock(a, requested, rw); 10447540Skarels p->p_flag &= ~SPHYSIO; 10534215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 10630750Skarels wakeup((caddr_t)bp); 10730750Skarels splx(s); 10838794Skarels done = bp->b_bcount - bp->b_resid; 10938794Skarels bp->b_un.b_addr += done; 11038794Skarels iov->iov_len -= done; 11138794Skarels uio->uio_resid -= done; 11238794Skarels uio->uio_offset += done; 11338794Skarels /* temp kludge for disk drives */ 11438794Skarels if (done < requested || bp->b_flags & B_ERROR) 11530750Skarels break; 11630750Skarels } 11734215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 11837729Smckusick error = biowait(bp); 11938794Skarels /* temp kludge for disk drives */ 12038794Skarels if (done < requested || bp->b_flags & B_ERROR) 12134215Sbostic break; 1228Sbill } 12342001Smckusick #if defined(hp300) 12442001Smckusick DCIU(); 12542001Smckusick #endif 12634215Sbostic if (allocbuf) 12734215Sbostic freeswbuf(bp); 12834215Sbostic return (error); 1298Sbill } 1308Sbill 13134215Sbostic u_int 1328Sbill minphys(bp) 1337724Swnj struct buf *bp; 1348Sbill { 13510400Ssam if (bp->b_bcount > MAXPHYS) 13610400Ssam bp->b_bcount = MAXPHYS; 1378Sbill } 13834215Sbostic 13934215Sbostic static 14034215Sbostic struct buf * 14134215Sbostic getswbuf(prio) 14234215Sbostic int prio; 14334215Sbostic { 14434215Sbostic int s; 14534215Sbostic struct buf *bp; 14634215Sbostic 14734215Sbostic s = splbio(); 14834215Sbostic while (bswlist.av_forw == NULL) { 14934215Sbostic bswlist.b_flags |= B_WANTED; 15034215Sbostic sleep((caddr_t)&bswlist, prio); 15134215Sbostic } 15234215Sbostic bp = bswlist.av_forw; 15334215Sbostic bswlist.av_forw = bp->av_forw; 15434215Sbostic splx(s); 15534215Sbostic return (bp); 15634215Sbostic } 15734215Sbostic 15834215Sbostic static 15934215Sbostic freeswbuf(bp) 16034215Sbostic struct buf *bp; 16134215Sbostic { 16234215Sbostic int s; 16334215Sbostic 16434215Sbostic s = splbio(); 16534215Sbostic bp->av_forw = bswlist.av_forw; 16634215Sbostic bswlist.av_forw = bp; 16739148Smckusick if (bp->b_vp) 16839148Smckusick brelvp(bp); 16934215Sbostic if (bswlist.b_flags & B_WANTED) { 17034215Sbostic bswlist.b_flags &= ~B_WANTED; 17134215Sbostic wakeup((caddr_t)&bswlist); 17247540Skarels wakeup((caddr_t)pageproc); 17334215Sbostic } 17434215Sbostic splx(s); 17534215Sbostic } 17634215Sbostic 17734215Sbostic rawread(dev, uio) 17834215Sbostic dev_t dev; 17934215Sbostic struct uio *uio; 18034215Sbostic { 18134215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18234215Sbostic dev, B_READ, minphys, uio)); 18334215Sbostic } 18434215Sbostic 18534215Sbostic rawwrite(dev, uio) 18634215Sbostic dev_t dev; 18734215Sbostic struct uio *uio; 18834215Sbostic { 18934215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 19034215Sbostic dev, B_WRITE, minphys, uio)); 19134215Sbostic } 192