more-or-less working with new proc & user structs
[unix-history] / usr / src / sys / kern / kern_physio.c
CommitLineData
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
37physio(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 134u_int
663dbc72 135minphys(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
142static
143struct buf *
144getswbuf(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
161static
162freeswbuf(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
180rawread(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
188rawwrite(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}