Research V5 development
[unix-history] / usr / sys / dmr / bio.c
CommitLineData
21477931
DR
1#
2/*
3 * Copyright 1973 Bell Telephone Laboratories Inc
4 */
5
6#include "../param.h"
7#include "../user.h"
8#include "../buf.h"
9#include "../conf.h"
10#include "../systm.h"
11#include "../proc.h"
12#include "../seg.h"
13
14char buffers[NBUF][514];
15struct buf swbuf;
16
17struct { int int;};
18#define PS 0177776
19int tmtab;
20int raflag 1;
21
22bread(dev, blkno)
23{
24 register struct buf *rbp;
25
26 rbp = getblk(dev, blkno);
27 if (rbp->b_flags&B_DONE)
28 return(rbp);
29 rbp->b_flags =| B_READ;
30 rbp->b_wcount = -256;
31 (*bdevsw[dev.d_major].d_strategy)(rbp);
32 iowait(rbp);
33 return(rbp);
34}
35
36breada(adev, blkno, rablkno)
37{
38 register struct buf *rbp, *rabp;
39 register int dev;
40
41 dev = adev;
42 rbp = 0;
43 if (!incore(dev, blkno)) {
44 rbp = getblk(dev, blkno);
45 if ((rbp->b_flags&B_DONE) == 0) {
46 rbp->b_flags =| B_READ;
47 rbp->b_wcount = -256;
48 (*bdevsw[adev.d_major].d_strategy)(rbp);
49 }
50 }
51 if (rablkno && !incore(dev, rablkno) && raflag) {
52 rabp = getblk(dev, rablkno);
53 if (rabp->b_flags & B_DONE)
54 brelse(rabp);
55 else {
56 rabp->b_flags =| B_READ|B_ASYNC;
57 rabp->b_wcount = -256;
58 (*bdevsw[adev.d_major].d_strategy)(rabp);
59 }
60 }
61 if (rbp==0)
62 return(bread(dev, blkno));
63 iowait(rbp);
64 return(rbp);
65}
66
67bwrite(bp)
68struct buf *bp;
69{
70 register struct buf *rbp;
71 register flag;
72
73 rbp = bp;
74 flag = rbp->b_flags;
75 rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
76 rbp->b_wcount = -256;
77 (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp);
78 if ((flag&B_ASYNC) == 0) {
79 iowait(rbp);
80 brelse(rbp);
81 } else if ((flag&B_DELWRI)==0)
82 geterror(rbp);
83}
84
85bdwrite(bp)
86struct buf *bp;
87{
88 register struct buf *rbp;
89
90 rbp = bp;
91 if (bdevsw[rbp->b_dev.d_major].d_tab == &tmtab)
92 bawrite(rbp);
93 else {
94 rbp->b_flags =| B_DELWRI | B_DONE;
95 brelse(rbp);
96 }
97}
98
99bawrite(bp)
100struct buf *bp;
101{
102 register struct buf *rbp;
103
104 rbp = bp;
105 rbp->b_flags =| B_ASYNC;
106 bwrite(rbp);
107}
108
109brelse(bp)
110struct buf *bp;
111{
112 register struct buf *rbp, **backp;
113 register int sps;
114
115 rbp = bp;
116 if (rbp->b_flags&B_WANTED)
117 wakeup(rbp);
118 if (bfreelist.b_flags&B_WANTED) {
119 bfreelist.b_flags =& ~B_WANTED;
120 wakeup(&bfreelist);
121 }
122 if (rbp->b_flags&B_ERROR)
123 rbp->b_dev.d_minor = -1; /* no assoc. on error */
124 backp = &bfreelist.av_back;
125 sps = PS->int;
126 spl6();
127 rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC);
128 (*backp)->av_forw = rbp;
129 rbp->av_back = *backp;
130 *backp = rbp;
131 rbp->av_forw = &bfreelist;
132 PS->int = sps;
133}
134
135incore(adev, blkno)
136{
137 register int dev;
138 register struct buf *bp;
139 register struct devtab *dp;
140
141 dev = adev;
142 dp = bdevsw[adev.d_major].d_tab;
143 for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)
144 if (bp->b_blkno==blkno && bp->b_dev==dev)
145 return(bp);
146 return(0);
147}
148
149getblk(dev, blkno)
150{
151 register struct buf *bp;
152 register struct devtab *dp;
153 extern lbolt;
154
155 if(dev.d_major >= nblkdev)
156 panic("blkdev");
157
158 loop:
159 if (dev < 0)
160 dp = &bfreelist;
161 else {
162 dp = bdevsw[dev.d_major].d_tab;
163 for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {
164 if (bp->b_blkno!=blkno || bp->b_dev!=dev)
165 continue;
166 spl6();
167 if (bp->b_flags&B_BUSY) {
168 bp->b_flags =| B_WANTED;
169 sleep(bp, PRIBIO);
170 spl0();
171 goto loop;
172 }
173 spl0();
174 notavail(bp);
175 return(bp);
176 }
177 }
178 spl6();
179 if (bfreelist.av_forw == &bfreelist) {
180 bfreelist.b_flags =| B_WANTED;
181 sleep(&bfreelist, PRIBIO);
182 spl0();
183 goto loop;
184 }
185 spl0();
186 notavail(bp = bfreelist.av_forw);
187 if (bp->b_flags & B_DELWRI) {
188 bp->b_flags =| B_ASYNC;
189 bwrite(bp);
190 goto loop;
191 }
192 bp->b_flags = B_BUSY | B_RELOC;
193 bp->b_back->b_forw = bp->b_forw;
194 bp->b_forw->b_back = bp->b_back;
195 bp->b_forw = dp->b_forw;
196 bp->b_back = dp;
197 dp->b_forw->b_back = bp;
198 dp->b_forw = bp;
199 bp->b_dev = dev;
200 bp->b_blkno = blkno;
201 return(bp);
202}
203
204iowait(bp)
205struct buf *bp;
206{
207 register struct buf *rbp;
208
209 rbp = bp;
210 spl6();
211 while ((rbp->b_flags&B_DONE)==0)
212 sleep(rbp, PRIBIO);
213 spl0();
214 geterror(rbp);
215}
216
217notavail(bp)
218struct buf *bp;
219{
220 register struct buf *rbp;
221 register int sps;
222
223 rbp = bp;
224 sps = PS->int;
225 spl6();
226 rbp->av_back->av_forw = rbp->av_forw;
227 rbp->av_forw->av_back = rbp->av_back;
228 rbp->b_flags =| B_BUSY;
229 PS->int = sps;
230}
231
232iodone(bp)
233struct buf *bp;
234{
235 register struct buf *rbp;
236
237 rbp = bp;
238 rbp->b_flags =| B_DONE;
239 if (rbp->b_flags&B_ASYNC)
240 brelse(rbp);
241 else {
242 rbp->b_flags =& ~B_WANTED;
243 wakeup(rbp);
244 }
245}
246
247clrbuf(bp)
248int *bp;
249{
250 register *p;
251 register c;
252
253 p = bp->b_addr;
254 c = 256;
255 do
256 *p++ = 0;
257 while (--c);
258}
259
260binit()
261{
262 register struct buf *bp;
263 register struct devtab *dp;
264 register int i;
265 struct bdevsw *bdp;
266
267 bfreelist.b_forw = bfreelist.b_back =
268 bfreelist.av_forw = bfreelist.av_back = &bfreelist;
269 for (i=0; i<NBUF; i++) {
270 bp = &buf[i];
271 bp->b_dev = -1;
272 bp->b_addr = buffers[i];
273 bp->b_back = &bfreelist;
274 bp->b_forw = bfreelist.b_forw;
275 bfreelist.b_forw->b_back = bp;
276 bfreelist.b_forw = bp;
277 bp->b_flags = B_BUSY;
278 brelse(bp);
279 }
280 i = 0;
281 for (bdp = bdevsw; bdp->d_open; bdp++) {
282 dp = bdp->d_tab;
283 dp->b_forw = dp;
284 dp->b_back = dp;
285 i++;
286 }
287 nblkdev = i;
288}
289
290/*
291 * Device start routine for disks
292 */
293#define IENABLE 0100
294#define WCOM 02
295#define RCOM 04
296#define GO 01
297devstart(bp, devloc, devblk, hbcom)
298struct buf *bp;
299int *devloc;
300{
301 register int *dp;
302 register struct buf *rbp;
303 register int com;
304
305 dp = devloc;
306 rbp = bp;
307 *dp = devblk; /* block address */
308 *--dp = rbp->b_addr; /* buffer address */
309 *--dp = rbp->b_wcount; /* word count */
310 com = (hbcom<<8) | IENABLE | GO | rbp->b_flags&B_XMEM;
311 if (rbp->b_flags&B_READ) /* command + x-mem */
312 com =| RCOM;
313 else
314 com =| WCOM;
315 *--dp = com;
316}
317
318/*
319 * swap I/O
320 */
321swap(blkno, coreaddr, count, rdflg)
322{
323 register int *fp;
324
325 fp = &swbuf.b_flags;
326 spl6();
327 while (*fp&B_BUSY) {
328 *fp =| B_WANTED;
329 sleep(fp, PSWP);
330 }
331 *fp = B_BUSY | rdflg | (coreaddr>>6)&B_XMEM;
332 swbuf.b_dev = swapdev;
333 swbuf.b_wcount = - (count<<5); /* 32 w/block */
334 swbuf.b_blkno = blkno;
335 swbuf.b_addr = coreaddr<<6; /* 64 b/block */
336 (*bdevsw[swapdev>>8].d_strategy)(&swbuf);
337 spl6();
338 while((*fp&B_DONE)==0)
339 sleep(fp, PSWP);
340 if (*fp&B_WANTED)
341 wakeup(fp);
342 spl0();
343 *fp =& ~(B_BUSY|B_WANTED);
344 return(*fp&B_ERROR);
345}
346
347/*
348 * make sure all write-behind blocks
349 * on dev (or NODEV for all)
350 * are flushed out.
351 */
352bflush(dev)
353{
354 register struct buf *bp;
355
356loop:
357 spl6();
358 for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
359 if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
360 bp->b_flags =| B_ASYNC;
361 notavail(bp);
362 bwrite(bp);
363 goto loop;
364 }
365 }
366 spl0();
367}
368
369physio(strat, abp, dev, rw)
370struct buf *abp;
371int (*strat)();
372{
373 register struct buf *bp;
374 register char *base;
375 register int nb;
376 int ts;
377
378 bp = abp;
379 base = u.u_base;
380 if (base&01 || u.u_count&01 || base>=base+u.u_count)
381 goto bad;
382 ts = (u.u_tsize+127) & ~0177;
383 nb = (base>>6) & 01777;
384 if (nb < ts)
385 goto bad;
386 if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize
387 && nb < 1024-u.u_ssize)
388 goto bad;
389 spl6();
390 while (bp->b_flags&B_BUSY) {
391 bp->b_flags =| B_WANTED;
392 sleep(bp, PRIBIO);
393 }
394 bp->b_flags = B_BUSY | rw;
395 bp->b_dev = dev;
396 bp->b_addr = base&077;
397 base = UISA->r[nb>>7] + (nb&0177);
398 bp->b_flags =| (base>>6) & B_XMEM;
399 bp->b_blkno = lshift(u.u_offset, -9);
400 bp->b_addr =+ base<<6;
401 bp->b_wcount = -((u.u_count>>1) & 077777);
402 bp->b_error = 0;
403 u.u_procp->p_flag =| SLOCK;
404 (*strat)(bp);
405 spl6();
406 while ((bp->b_flags&B_DONE) == 0)
407 sleep(bp, PRIBIO);
408 u.u_procp->p_flag =& ~SLOCK;
409 if (bp->b_flags&B_WANTED)
410 wakeup(bp);
411 spl0();
412 bp->b_flags =& ~(B_BUSY|B_WANTED);
413 u.u_count = (-bp->b_resid)<<1;
414 geterror(bp);
415 return;
416 bad:
417 u.u_error = EFAULT;
418}
419
420geterror(abp)
421struct buf *abp;
422{
423 register struct buf *bp;
424
425 bp = abp;
426 if (bp->b_flags&B_ERROR)
427 if ((u.u_error = bp->b_error)==0)
428 u.u_error = EIO;
429}