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*56387Smckusick * @(#)kern_physio.c 7.27 (Berkeley) 10/02/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/vnode.h> 168Sbill 1748414Skarels #ifdef HPUXCOMPAT 1851454Sbostic #include <sys/user.h> 1948414Skarels #endif 2048414Skarels 2151454Sbostic static void freeswbuf __P((struct buf *)); 2251454Sbostic static struct buf *getswbuf __P((int)); 2348414Skarels 2491Sbill /* 2549672Smckusick * This routine does device I/O for a user process. 2649672Smckusick * 2751759Storek * If the user has the proper access privileges, the process is 288Sbill * marked 'delayed unlock' and the pages involved in the I/O are 2949672Smckusick * faulted and locked. After the completion of the I/O, the pages 308Sbill * are unlocked. 318Sbill */ 327724Swnj physio(strat, bp, dev, rw, mincnt, uio) 337724Swnj int (*strat)(); 347724Swnj register struct buf *bp; 357724Swnj dev_t dev; 367724Swnj int rw; 3734215Sbostic u_int (*mincnt)(); 387724Swnj struct uio *uio; 398Sbill { 4017313Skarels register struct iovec *iov; 4152424Storek register int requested = 0, done = 0; 4247540Skarels register struct proc *p = curproc; 438Sbill char *a; 4434215Sbostic int s, allocbuf = 0, error = 0; 458Sbill 4634215Sbostic if (bp == NULL) { 4734215Sbostic allocbuf = 1; 4834215Sbostic bp = getswbuf(PRIBIO+1); 4934215Sbostic } 5034215Sbostic for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) { 5130750Skarels iov = uio->uio_iov; 5252424Storek if (iov->iov_len == 0) 5352424Storek continue; 5434215Sbostic if (!useracc(iov->iov_base, (u_int)iov->iov_len, 5534215Sbostic rw == B_READ ? B_WRITE : B_READ)) { 5634215Sbostic error = EFAULT; 5734215Sbostic break; 5830750Skarels } 5934215Sbostic if (!allocbuf) { /* only if sharing caller's buffer */ 6034215Sbostic s = splbio(); 6134215Sbostic while (bp->b_flags&B_BUSY) { 6234215Sbostic bp->b_flags |= B_WANTED; 6334215Sbostic sleep((caddr_t)bp, PRIBIO+1); 6434215Sbostic } 6534215Sbostic splx(s); 6634215Sbostic } 6730750Skarels bp->b_error = 0; 6847540Skarels bp->b_proc = p; 6942001Smckusick #ifdef HPUXCOMPAT 7042001Smckusick if (ISHPMMADDR(iov->iov_base)) 7142001Smckusick bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base); 7242001Smckusick else 7342001Smckusick #endif 7430750Skarels bp->b_un.b_addr = iov->iov_base; 7530750Skarels while (iov->iov_len > 0) { 7634215Sbostic bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw; 7730750Skarels bp->b_dev = dev; 7830750Skarels bp->b_blkno = btodb(uio->uio_offset); 7930750Skarels bp->b_bcount = iov->iov_len; 8030750Skarels (*mincnt)(bp); 8138794Skarels requested = bp->b_bcount; 8247540Skarels p->p_flag |= SPHYSIO; 8338794Skarels vslock(a = bp->b_un.b_addr, requested); 8442001Smckusick vmapbuf(bp); 8534215Sbostic (*strat)(bp); 8634215Sbostic s = splbio(); 8734215Sbostic while ((bp->b_flags & B_DONE) == 0) 8834215Sbostic sleep((caddr_t)bp, PRIBIO); 8942001Smckusick vunmapbuf(bp); 9038794Skarels vsunlock(a, requested, rw); 9147540Skarels p->p_flag &= ~SPHYSIO; 9234215Sbostic if (bp->b_flags&B_WANTED) /* rare */ 9330750Skarels wakeup((caddr_t)bp); 9430750Skarels splx(s); 9538794Skarels done = bp->b_bcount - bp->b_resid; 9638794Skarels bp->b_un.b_addr += done; 9738794Skarels iov->iov_len -= done; 9838794Skarels uio->uio_resid -= done; 9938794Skarels uio->uio_offset += done; 10038794Skarels /* temp kludge for disk drives */ 10138794Skarels if (done < requested || bp->b_flags & B_ERROR) 10230750Skarels break; 10330750Skarels } 10434215Sbostic bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW); 10537729Smckusick error = biowait(bp); 10638794Skarels /* temp kludge for disk drives */ 10738794Skarels if (done < requested || bp->b_flags & B_ERROR) 10834215Sbostic break; 1098Sbill } 11042001Smckusick #if defined(hp300) 11142001Smckusick DCIU(); 11242001Smckusick #endif 11334215Sbostic if (allocbuf) 11434215Sbostic freeswbuf(bp); 11534215Sbostic return (error); 1168Sbill } 1178Sbill 11849672Smckusick /* 11949672Smckusick * Calculate the maximum size of I/O request that can be requested 12049672Smckusick * in a single operation. This limit is necessary to prevent a single 12149672Smckusick * process from being able to lock more than a fixed amount of memory 12249672Smckusick * in the kernel. 12349672Smckusick */ 12434215Sbostic u_int 1258Sbill minphys(bp) 1267724Swnj struct buf *bp; 1278Sbill { 12810400Ssam if (bp->b_bcount > MAXPHYS) 12910400Ssam bp->b_bcount = MAXPHYS; 1308Sbill } 13134215Sbostic 13251454Sbostic static struct buf * 13334215Sbostic getswbuf(prio) 13434215Sbostic int prio; 13534215Sbostic { 13634215Sbostic int s; 13734215Sbostic struct buf *bp; 13834215Sbostic 13934215Sbostic s = splbio(); 140*56387Smckusick while (bswlist.b_actf == NULL) { 14134215Sbostic bswlist.b_flags |= B_WANTED; 14234215Sbostic sleep((caddr_t)&bswlist, prio); 14334215Sbostic } 144*56387Smckusick bp = bswlist.b_actf; 145*56387Smckusick bswlist.b_actf = bp->b_actf; 14634215Sbostic splx(s); 14734215Sbostic return (bp); 14834215Sbostic } 14934215Sbostic 15051454Sbostic static void 15134215Sbostic freeswbuf(bp) 15234215Sbostic struct buf *bp; 15334215Sbostic { 15434215Sbostic int s; 15534215Sbostic 15634215Sbostic s = splbio(); 157*56387Smckusick bp->b_actf = bswlist.b_actf; 158*56387Smckusick bswlist.b_actf = bp; 15939148Smckusick if (bp->b_vp) 16039148Smckusick brelvp(bp); 16134215Sbostic if (bswlist.b_flags & B_WANTED) { 16234215Sbostic bswlist.b_flags &= ~B_WANTED; 16334215Sbostic wakeup((caddr_t)&bswlist); 16447540Skarels wakeup((caddr_t)pageproc); 16534215Sbostic } 16634215Sbostic splx(s); 16734215Sbostic } 16834215Sbostic 16949672Smckusick /* 17049672Smckusick * Do a read on a device for a user process. 17149672Smckusick */ 17234215Sbostic rawread(dev, uio) 17334215Sbostic dev_t dev; 17434215Sbostic struct uio *uio; 17534215Sbostic { 17634215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 17734215Sbostic dev, B_READ, minphys, uio)); 17834215Sbostic } 17934215Sbostic 18049672Smckusick /* 18149672Smckusick * Do a write on a device for a user process. 18249672Smckusick */ 18334215Sbostic rawwrite(dev, uio) 18434215Sbostic dev_t dev; 18534215Sbostic struct uio *uio; 18634215Sbostic { 18734215Sbostic return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18834215Sbostic dev, B_WRITE, minphys, uio)); 18934215Sbostic } 190