xref: /csrg-svn/sys/kern/kern_physio.c (revision 49589)
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