Remove man group - no longer necessary (that was quick! :). I'll let Rod
[unix-history] / sys / kern / kern_physio.c
CommitLineData
6232f830
DG
1Received: from jsdinc.root.com (uucp@localhost) by Root.COM (8.6.5/8.6.5) with UUCP id MAA09093 for implode.root.com!davidg; Sat, 19 Mar 1994 12:12:17 -0800
2Received: from localhost (root@localhost) by jsdinc.root.com (8.6.5/8.6.5) id PAA00122 for implode!davidg; Sat, 19 Mar 1994 15:09:05 -0459
3Date: Sat, 19 Mar 1994 15:09:05 -0459
4From: John Dyson <toor@jsdinc.root.com>
5Message-Id: <199403192008.PAA00122@jsdinc.root.com>
6To: davidg@implode.root.com
7Subject: new kern_physio.c
8
dd403947
DG
9/*
10 * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This software is a component of "386BSD" developed by
24 William F. Jolitz, TeleMuse.
25 * 4. Neither the name of the developer nor the name "386BSD"
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
30 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
31 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
32 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
33 * NOT MAKE USE THIS WORK.
34 *
35 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
36 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
37 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
38 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
39 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
40 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
41 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
42 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
6232f830 56 * $Id: kern_physio.c,v 1.2 1994/03/14 21:54:16 davidg Exp $
dd403947
DG
57 */
58
59#include "param.h"
60#include "systm.h"
61#include "buf.h"
62#include "conf.h"
63#include "proc.h"
64#include "malloc.h"
65#include "vnode.h"
66#include "vm/vm.h"
41aefbec 67#include "vm/vm_page.h"
dd403947
DG
68#include "specdev.h"
69
70/*
71 * Driver interface to do "raw" I/O in the address space of a
72 * user process directly for read and write operations..
73 */
74
75int
76rawread(dev, uio)
77 dev_t dev; struct uio *uio;
78{
79 return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
80 (caddr_t) (u_long) dev, uio));
81}
82
83int
84rawwrite(dev, uio)
85 dev_t dev; struct uio *uio;
86{
87 return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
88 (caddr_t) (u_long) dev, uio));
89}
90
91
92int physio(strat, dev, bp, off, rw, base, len, p)
93 d_strategy_t strat;
94 dev_t dev;
95 struct buf *bp;
96 int rw, off;
97 caddr_t base;
98 int *len;
99 struct proc *p;
100{
101 int amttodo = *len;
102 int error, amtdone;
103 vm_prot_t ftype;
41aefbec 104 vm_offset_t v, lastv, pa;
dd403947
DG
105 caddr_t adr;
106 int oldflags;
107 int s;
108
109 int bp_alloc = (bp == 0);
110
111/*
112 * keep the process from being swapped
113 */
114 oldflags = p->p_flag;
115 p->p_flag |= SPHYSIO;
116
117 rw = rw == UIO_READ ? B_READ : 0;
118
119 /* create and build a buffer header for a transfer */
120
121 if (bp_alloc) {
122 bp = (struct buf *)getpbuf();
123 bzero((char *)bp, sizeof(*bp)); /* 09 Sep 92*/
124 } else {
125 s = splbio();
126 while (bp->b_flags & B_BUSY) {
127 bp->b_flags |= B_WANTED;
128 tsleep((caddr_t)bp, PRIBIO, "physbw", 0);
129 }
130 bp->b_flags |= B_BUSY;
131 splx(s);
132 }
133
134 bp->b_flags = B_BUSY | B_PHYS | rw;
135 bp->b_proc = p;
136 bp->b_dev = dev;
137 bp->b_error = 0;
138 bp->b_blkno = off/DEV_BSIZE;
139 amtdone = 0;
140
141 /* iteratively do I/O on as large a chunk as possible */
142 do {
143 bp->b_flags &= ~B_DONE;
144 bp->b_un.b_addr = base;
145 /* XXX limit */
146 bp->b_bcount = min (256*1024, amttodo);
147
148 /* first, check if accessible */
149 if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) {
150 error = EFAULT;
151 goto errrtn;
152 }
153 if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) {
154 error = EFAULT;
155 goto errrtn;
156 }
157
158 /* update referenced and dirty bits, handle copy objects */
159 if (rw == B_READ)
160 ftype = VM_PROT_READ | VM_PROT_WRITE;
161 else
162 ftype = VM_PROT_READ;
163
164 lastv = 0;
165 for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
166 adr += NBPG) {
167
168/*
41aefbec 169 * make sure that the pde is valid and held
dd403947
DG
170 */
171 v = trunc_page(((vm_offset_t)vtopte(adr)));
172 if (v != lastv) {
41aefbec
DG
173
174 *(volatile int *)v += 0;
175 pa = pmap_extract(&p->p_vmspace->vm_pmap, v);
176 vm_page_hold(PHYS_TO_VM_PAGE(pa));
dd403947
DG
177 lastv = v;
178 }
179
180/*
181 * do the vm_fault if needed, do the copy-on-write thing when
182 * reading stuff off device into memory.
183 */
184 if (ftype & VM_PROT_WRITE) {
185 /*
186 * properly handle copy-on-write
187 */
188 *(volatile int *) adr += 0;
6232f830
DG
189 }
190#if defined(HOLD_WORKS_FOR_SHARING)
191 else {
dd403947
DG
192 *(volatile int *) adr;
193 }
41aefbec 194 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr);
dd403947 195/*
41aefbec 196 * hold the data page
dd403947 197 */
41aefbec 198 vm_page_hold(PHYS_TO_VM_PAGE(pa));
6232f830 199#endif
41aefbec 200 }
dd403947 201
6232f830
DG
202#if !defined(HOLD_WORKS_FOR_SHARING)
203 vslock(base, bp->b_bcount);
204#endif
dd403947
DG
205 /* perform transfer */
206 physstrat(bp, strat, PRIBIO);
6232f830
DG
207#if !defined(HOLD_WORKS_FOR_SHARING)
208 vsunlock(base, bp->b_bcount);
209#endif
dd403947 210
dd403947 211/*
41aefbec 212 * unhold the pde, and data pages
dd403947 213 */
41aefbec 214 lastv = 0;
dd403947
DG
215 for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
216 adr += NBPG) {
217 v = trunc_page(((vm_offset_t)vtopte(adr)));
218 if (v != lastv) {
41aefbec
DG
219 pa = pmap_extract(&p->p_vmspace->vm_pmap, v);
220 vm_page_unhold(PHYS_TO_VM_PAGE(pa));
dd403947
DG
221 lastv = v;
222 }
6232f830 223#if defined(HOLD_WORKS_FOR_SHARING)
41aefbec
DG
224 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr);
225 vm_page_unhold(PHYS_TO_VM_PAGE(pa));
6232f830 226#endif
dd403947
DG
227 }
228
229
230 amtdone = bp->b_bcount - bp->b_resid;
231 amttodo -= amtdone;
232 base += amtdone;
233 bp->b_blkno += amtdone/DEV_BSIZE;
234 } while (amttodo && (bp->b_flags & B_ERROR) == 0 && amtdone > 0);
235
236 error = bp->b_error;
237errrtn:
238 if (bp_alloc) {
239 relpbuf(bp);
240 } else {
241 bp->b_flags &= ~B_BUSY;
242 wakeup((caddr_t)bp);
243 }
244 *len = amttodo;
245
246/*
247 * allow the process to be swapped
248 */
249 p->p_flag &= ~SPHYSIO;
250 p->p_flag |= (oldflags & SPHYSIO);
251
252 return (error);
253}