Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
cef7aa7d KM |
2 | * Copyright (c) 1982, 1986, 1990 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
cef7aa7d KM |
5 | * %sccs.include.redist.c% |
6 | * | |
8429d022 | 7 | * @(#)kern_physio.c 7.17 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
961945a8 | 9 | |
94368568 JB |
10 | #include "param.h" |
11 | #include "systm.h" | |
94368568 JB |
12 | #include "user.h" |
13 | #include "buf.h" | |
14 | #include "conf.h" | |
15 | #include "proc.h" | |
16 | #include "seg.h" | |
94368568 JB |
17 | #include "trace.h" |
18 | #include "map.h" | |
c4ec2128 | 19 | #include "vnode.h" |
0f93ba7b | 20 | #include "specdev.h" |
d301d150 | 21 | |
663dbc72 BJ |
22 | /* |
23 | * Raw I/O. The arguments are | |
24 | * The strategy routine for the device | |
c5648f55 KB |
25 | * A buffer, which will either be a special buffer header owned |
26 | * exclusively by the device for this purpose, or NULL, | |
27 | * indicating that we should use a swap buffer | |
663dbc72 BJ |
28 | * The device number |
29 | * Read/write flag | |
30 | * Essentially all the work is computing physical addresses and | |
31 | * validating them. | |
32 | * If the user has the proper access privilidges, the process is | |
33 | * marked 'delayed unlock' and the pages involved in the I/O are | |
34 | * faulted and locked. After the completion of the I/O, the above pages | |
35 | * are unlocked. | |
36 | */ | |
d6d7360b BJ |
37 | physio(strat, bp, dev, rw, mincnt, uio) |
38 | int (*strat)(); | |
39 | register struct buf *bp; | |
40 | dev_t dev; | |
41 | int rw; | |
c5648f55 | 42 | u_int (*mincnt)(); |
d6d7360b | 43 | struct uio *uio; |
663dbc72 | 44 | { |
a196746e | 45 | register struct iovec *iov; |
58c3cad7 | 46 | register int requested, done; |
8429d022 | 47 | register struct proc *p = curproc; |
663dbc72 | 48 | char *a; |
c5648f55 KB |
49 | int s, allocbuf = 0, error = 0; |
50 | struct buf *getswbuf(); | |
ec67a3ce MK |
51 | #ifdef SECSIZE |
52 | int bsize; | |
53 | struct partinfo dpart; | |
54 | #endif SECSIZE | |
663dbc72 | 55 | |
ec67a3ce MK |
56 | #ifdef SECSIZE |
57 | if ((unsigned)major(dev) < nchrdev && | |
58 | (*cdevsw[major(dev)].d_ioctl)(dev, DIOCGPART, (caddr_t)&dpart, | |
59 | FREAD) == 0) | |
60 | bsize = dpart.disklab->d_secsize; | |
61 | else | |
62 | bsize = DEV_BSIZE; | |
63 | #endif SECSIZE | |
64 | for (;;) { | |
65 | if (uio->uio_iovcnt == 0) | |
66 | return (0); | |
67 | iov = uio->uio_iov; | |
68 | if (useracc(iov->iov_base, (u_int)iov->iov_len, | |
69 | rw==B_READ? B_WRITE : B_READ) == NULL) | |
70 | return (EFAULT); | |
71 | s = splbio(); | |
72 | while (bp->b_flags&B_BUSY) { | |
73 | bp->b_flags |= B_WANTED; | |
74 | sleep((caddr_t)bp, PRIBIO+1); | |
75 | } | |
c5648f55 KB |
76 | if (!allocbuf) { /* only if sharing caller's buffer */ |
77 | s = splbio(); | |
78 | while (bp->b_flags&B_BUSY) { | |
79 | bp->b_flags |= B_WANTED; | |
80 | sleep((caddr_t)bp, PRIBIO+1); | |
81 | } | |
82 | splx(s); | |
83 | } | |
ec67a3ce MK |
84 | bp->b_error = 0; |
85 | bp->b_proc = u.u_procp; | |
86 | #ifdef SECSIZE | |
87 | bp->b_blksize = bsize; | |
88 | #endif SECSIZE | |
89 | bp->b_un.b_addr = iov->iov_base; | |
90 | while (iov->iov_len > 0) { | |
91 | bp->b_flags = B_BUSY | B_PHYS | rw; | |
92 | bp->b_dev = dev; | |
93 | #ifdef SECSIZE | |
94 | bp->b_blkno = uio->uio_offset / bsize; | |
95 | #else SECSIZE | |
96 | bp->b_blkno = btodb(uio->uio_offset); | |
97 | #endif SECSIZE | |
98 | bp->b_bcount = iov->iov_len; | |
99 | (*mincnt)(bp); | |
100 | c = bp->b_bcount; | |
101 | u.u_procp->p_flag |= SPHYSIO; | |
102 | vslock(a = bp->b_un.b_addr, c); | |
103 | physstrat(bp, strat, PRIBIO); | |
104 | (void) splbio(); | |
105 | vsunlock(a, c, rw); | |
106 | u.u_procp->p_flag &= ~SPHYSIO; | |
107 | if (bp->b_flags&B_WANTED) | |
108 | wakeup((caddr_t)bp); | |
109 | splx(s); | |
110 | c -= bp->b_resid; | |
111 | bp->b_un.b_addr += c; | |
112 | iov->iov_len -= c; | |
113 | uio->uio_resid -= c; | |
114 | uio->uio_offset += c; | |
115 | /* temp kludge for tape drives */ | |
116 | if (bp->b_resid || (bp->b_flags&B_ERROR)) | |
117 | break; | |
118 | } | |
119 | bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS); | |
120 | error = geterror(bp); | |
ec67a3ce MK |
121 | if (bp->b_resid || error) |
122 | return (error); | |
123 | uio->uio_iov++; | |
124 | uio->uio_iovcnt--; | |
663dbc72 | 125 | } |
cd682858 KM |
126 | #if defined(hp300) |
127 | DCIU(); | |
128 | #endif | |
c5648f55 KB |
129 | if (allocbuf) |
130 | freeswbuf(bp); | |
131 | return (error); | |
663dbc72 BJ |
132 | } |
133 | ||
c5648f55 | 134 | u_int |
663dbc72 | 135 | minphys(bp) |
d6d7360b | 136 | struct buf *bp; |
663dbc72 | 137 | { |
35a494b8 SL |
138 | if (bp->b_bcount > MAXPHYS) |
139 | bp->b_bcount = MAXPHYS; | |
663dbc72 | 140 | } |
c5648f55 KB |
141 | |
142 | static | |
143 | struct buf * | |
144 | getswbuf(prio) | |
145 | int prio; | |
146 | { | |
147 | int s; | |
148 | struct buf *bp; | |
149 | ||
150 | s = splbio(); | |
151 | while (bswlist.av_forw == NULL) { | |
152 | bswlist.b_flags |= B_WANTED; | |
153 | sleep((caddr_t)&bswlist, prio); | |
154 | } | |
155 | bp = bswlist.av_forw; | |
156 | bswlist.av_forw = bp->av_forw; | |
157 | splx(s); | |
158 | return (bp); | |
159 | } | |
160 | ||
161 | static | |
162 | freeswbuf(bp) | |
163 | struct buf *bp; | |
164 | { | |
165 | int s; | |
166 | ||
167 | s = splbio(); | |
168 | bp->av_forw = bswlist.av_forw; | |
169 | bswlist.av_forw = bp; | |
343a57bd KM |
170 | if (bp->b_vp) |
171 | brelvp(bp); | |
c5648f55 KB |
172 | if (bswlist.b_flags & B_WANTED) { |
173 | bswlist.b_flags &= ~B_WANTED; | |
174 | wakeup((caddr_t)&bswlist); | |
8429d022 | 175 | wakeup((caddr_t)pageproc); |
c5648f55 KB |
176 | } |
177 | splx(s); | |
178 | } | |
179 | ||
180 | rawread(dev, uio) | |
181 | dev_t dev; | |
182 | struct uio *uio; | |
183 | { | |
184 | return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, | |
185 | dev, B_READ, minphys, uio)); | |
186 | } | |
187 | ||
188 | rawwrite(dev, uio) | |
189 | dev_t dev; | |
190 | struct uio *uio; | |
191 | { | |
192 | return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, | |
193 | dev, B_WRITE, minphys, uio)); | |
194 | } |