Research V5 development
authorDennis Ritchie <dmr@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
committerDennis Ritchie <dmr@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
Work on file usr/sys/dmr/bio.c

Synthesized-from: v5

usr/sys/dmr/bio.c [new file with mode: 0644]

diff --git a/usr/sys/dmr/bio.c b/usr/sys/dmr/bio.c
new file mode 100644 (file)
index 0000000..607aebb
--- /dev/null
@@ -0,0 +1,429 @@
+#
+/*
+ *     Copyright 1973 Bell Telephone Laboratories Inc
+ */
+
+#include "../param.h"
+#include "../user.h"
+#include "../buf.h"
+#include "../conf.h"
+#include "../systm.h"
+#include "../proc.h"
+#include "../seg.h"
+
+char   buffers[NBUF][514];
+struct buf     swbuf;
+
+struct { int int;};
+#define        PS      0177776
+int    tmtab;
+int    raflag  1;
+
+bread(dev, blkno)
+{
+       register struct buf *rbp;
+
+       rbp = getblk(dev, blkno);
+       if (rbp->b_flags&B_DONE)
+               return(rbp);
+       rbp->b_flags =| B_READ;
+       rbp->b_wcount = -256;
+       (*bdevsw[dev.d_major].d_strategy)(rbp);
+       iowait(rbp);
+       return(rbp);
+}
+
+breada(adev, blkno, rablkno)
+{
+       register struct buf *rbp, *rabp;
+       register int dev;
+
+       dev = adev;
+       rbp = 0;
+       if (!incore(dev, blkno)) {
+               rbp = getblk(dev, blkno);
+               if ((rbp->b_flags&B_DONE) == 0) {
+                       rbp->b_flags =| B_READ;
+                       rbp->b_wcount = -256;
+                       (*bdevsw[adev.d_major].d_strategy)(rbp);
+               }
+       }
+       if (rablkno && !incore(dev, rablkno) && raflag) {
+               rabp = getblk(dev, rablkno);
+               if (rabp->b_flags & B_DONE)
+                       brelse(rabp);
+               else {
+                       rabp->b_flags =| B_READ|B_ASYNC;
+                       rabp->b_wcount = -256;
+                       (*bdevsw[adev.d_major].d_strategy)(rabp);
+               }
+       }
+       if (rbp==0)
+               return(bread(dev, blkno));
+       iowait(rbp);
+       return(rbp);
+}
+
+bwrite(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+       register flag;
+
+       rbp = bp;
+       flag = rbp->b_flags;
+       rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
+       rbp->b_wcount = -256;
+       (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp);
+       if ((flag&B_ASYNC) == 0) {
+               iowait(rbp);
+               brelse(rbp);
+       } else if ((flag&B_DELWRI)==0)
+               geterror(rbp);
+}
+
+bdwrite(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+
+       rbp = bp;
+       if (bdevsw[rbp->b_dev.d_major].d_tab == &tmtab)
+               bawrite(rbp);
+       else {
+               rbp->b_flags =| B_DELWRI | B_DONE;
+               brelse(rbp);
+       }
+}
+
+bawrite(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+
+       rbp = bp;
+       rbp->b_flags =| B_ASYNC;
+       bwrite(rbp);
+}
+
+brelse(bp)
+struct buf *bp;
+{
+       register struct buf *rbp, **backp;
+       register int sps;
+
+       rbp = bp;
+       if (rbp->b_flags&B_WANTED)
+               wakeup(rbp);
+       if (bfreelist.b_flags&B_WANTED) {
+               bfreelist.b_flags =& ~B_WANTED;
+               wakeup(&bfreelist);
+       }
+       if (rbp->b_flags&B_ERROR)
+               rbp->b_dev.d_minor = -1;  /* no assoc. on error */
+       backp = &bfreelist.av_back;
+       sps = PS->int;
+       spl6();
+       rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC);
+       (*backp)->av_forw = rbp;
+       rbp->av_back = *backp;
+       *backp = rbp;
+       rbp->av_forw = &bfreelist;
+       PS->int = sps;
+}
+
+incore(adev, blkno)
+{
+       register int dev;
+       register struct buf *bp;
+       register struct devtab *dp;
+
+       dev = adev;
+       dp = bdevsw[adev.d_major].d_tab;
+       for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)
+               if (bp->b_blkno==blkno && bp->b_dev==dev)
+                       return(bp);
+       return(0);
+}
+
+getblk(dev, blkno)
+{
+       register struct buf *bp;
+       register struct devtab *dp;
+       extern lbolt;
+
+       if(dev.d_major >= nblkdev)
+               panic("blkdev");
+
+    loop:
+       if (dev < 0)
+               dp = &bfreelist;
+       else {
+               dp = bdevsw[dev.d_major].d_tab;
+               for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {
+                       if (bp->b_blkno!=blkno || bp->b_dev!=dev)
+                               continue;
+                       spl6();
+                       if (bp->b_flags&B_BUSY) {
+                               bp->b_flags =| B_WANTED;
+                               sleep(bp, PRIBIO);
+                               spl0();
+                               goto loop;
+                       }
+                       spl0();
+                       notavail(bp);
+                       return(bp);
+               }
+       }
+       spl6();
+       if (bfreelist.av_forw == &bfreelist) {
+               bfreelist.b_flags =| B_WANTED;
+               sleep(&bfreelist, PRIBIO);
+               spl0();
+               goto loop;
+       }
+       spl0();
+       notavail(bp = bfreelist.av_forw);
+       if (bp->b_flags & B_DELWRI) {
+               bp->b_flags =| B_ASYNC;
+               bwrite(bp);
+               goto loop;
+       }
+       bp->b_flags = B_BUSY | B_RELOC;
+       bp->b_back->b_forw = bp->b_forw;
+       bp->b_forw->b_back = bp->b_back;
+       bp->b_forw = dp->b_forw;
+       bp->b_back = dp;
+       dp->b_forw->b_back = bp;
+       dp->b_forw = bp;
+       bp->b_dev = dev;
+       bp->b_blkno = blkno;
+       return(bp);
+}
+
+iowait(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+
+       rbp = bp;
+       spl6();
+       while ((rbp->b_flags&B_DONE)==0)
+               sleep(rbp, PRIBIO);
+       spl0();
+       geterror(rbp);
+}
+
+notavail(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+       register int sps;
+
+       rbp = bp;
+       sps = PS->int;
+       spl6();
+       rbp->av_back->av_forw = rbp->av_forw;
+       rbp->av_forw->av_back = rbp->av_back;
+       rbp->b_flags =| B_BUSY;
+       PS->int = sps;
+}
+
+iodone(bp)
+struct buf *bp;
+{
+       register struct buf *rbp;
+
+       rbp = bp;
+       rbp->b_flags =| B_DONE;
+       if (rbp->b_flags&B_ASYNC)
+               brelse(rbp);
+       else {
+               rbp->b_flags =& ~B_WANTED;
+               wakeup(rbp);
+       }
+}
+
+clrbuf(bp)
+int *bp;
+{
+       register *p;
+       register c;
+
+       p = bp->b_addr;
+       c = 256;
+       do
+               *p++ = 0;
+       while (--c);
+}
+
+binit()
+{
+       register struct buf *bp;
+       register struct devtab *dp;
+       register int i;
+       struct bdevsw *bdp;
+
+       bfreelist.b_forw = bfreelist.b_back =
+           bfreelist.av_forw = bfreelist.av_back = &bfreelist;
+       for (i=0; i<NBUF; i++) {
+               bp = &buf[i];
+               bp->b_dev = -1;
+               bp->b_addr = buffers[i];
+               bp->b_back = &bfreelist;
+               bp->b_forw = bfreelist.b_forw;
+               bfreelist.b_forw->b_back = bp;
+               bfreelist.b_forw = bp;
+               bp->b_flags = B_BUSY;
+               brelse(bp);
+       }
+       i = 0;
+       for (bdp = bdevsw; bdp->d_open; bdp++) {
+               dp = bdp->d_tab;
+               dp->b_forw = dp;
+               dp->b_back = dp;
+               i++;
+       }
+       nblkdev = i;
+}
+
+/*
+ * Device start routine for disks
+ */
+#define        IENABLE 0100
+#define        WCOM    02
+#define        RCOM    04
+#define        GO      01
+devstart(bp, devloc, devblk, hbcom)
+struct buf *bp;
+int *devloc;
+{
+       register int *dp;
+       register struct buf *rbp;
+       register int com;
+
+       dp = devloc;
+       rbp = bp;
+       *dp = devblk;                   /* block address */
+       *--dp = rbp->b_addr;            /* buffer address */
+       *--dp = rbp->b_wcount;          /* word count */
+       com = (hbcom<<8) | IENABLE | GO | rbp->b_flags&B_XMEM;
+       if (rbp->b_flags&B_READ)        /* command + x-mem */
+               com =| RCOM;
+       else
+               com =| WCOM;
+       *--dp = com;
+}
+
+/*
+ * swap I/O
+ */
+swap(blkno, coreaddr, count, rdflg)
+{
+       register int *fp;
+
+       fp = &swbuf.b_flags;
+       spl6();
+       while (*fp&B_BUSY) {
+               *fp =| B_WANTED;
+               sleep(fp, PSWP);
+       }
+       *fp = B_BUSY | rdflg | (coreaddr>>6)&B_XMEM;
+       swbuf.b_dev = swapdev;
+       swbuf.b_wcount = - (count<<5);  /* 32 w/block */
+       swbuf.b_blkno = blkno;
+       swbuf.b_addr = coreaddr<<6;     /* 64 b/block */
+       (*bdevsw[swapdev>>8].d_strategy)(&swbuf);
+       spl6();
+       while((*fp&B_DONE)==0)
+               sleep(fp, PSWP);
+       if (*fp&B_WANTED)
+               wakeup(fp);
+       spl0();
+       *fp =& ~(B_BUSY|B_WANTED);
+       return(*fp&B_ERROR);
+}
+
+/*
+ * make sure all write-behind blocks
+ * on dev (or NODEV for all)
+ * are flushed out.
+ */
+bflush(dev)
+{
+       register struct buf *bp;
+
+loop:
+       spl6();
+       for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
+               if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
+                       bp->b_flags =| B_ASYNC;
+                       notavail(bp);
+                       bwrite(bp);
+                       goto loop;
+               }
+       }
+       spl0();
+}
+
+physio(strat, abp, dev, rw)
+struct buf *abp;
+int (*strat)();
+{
+       register struct buf *bp;
+       register char *base;
+       register int nb;
+       int ts;
+
+       bp = abp;
+       base = u.u_base;
+       if (base&01 || u.u_count&01 || base>=base+u.u_count)
+               goto bad;
+       ts = (u.u_tsize+127) & ~0177;
+       nb = (base>>6) & 01777;
+       if (nb < ts)
+               goto bad;
+       if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize
+           && nb < 1024-u.u_ssize)
+               goto bad;
+       spl6();
+       while (bp->b_flags&B_BUSY) {
+               bp->b_flags =| B_WANTED;
+               sleep(bp, PRIBIO);
+       }
+       bp->b_flags = B_BUSY | rw;
+       bp->b_dev = dev;
+       bp->b_addr = base&077;
+       base = UISA->r[nb>>7] + (nb&0177);
+       bp->b_flags =| (base>>6) & B_XMEM;
+       bp->b_blkno = lshift(u.u_offset, -9);
+       bp->b_addr =+ base<<6;
+       bp->b_wcount = -((u.u_count>>1) & 077777);
+       bp->b_error = 0;
+       u.u_procp->p_flag =| SLOCK;
+       (*strat)(bp);
+       spl6();
+       while ((bp->b_flags&B_DONE) == 0)
+               sleep(bp, PRIBIO);
+       u.u_procp->p_flag =& ~SLOCK;
+       if (bp->b_flags&B_WANTED)
+               wakeup(bp);
+       spl0();
+       bp->b_flags =& ~(B_BUSY|B_WANTED);
+       u.u_count = (-bp->b_resid)<<1;
+       geterror(bp);
+       return;
+    bad:
+       u.u_error = EFAULT;
+}
+
+geterror(abp)
+struct buf *abp;
+{
+       register struct buf *bp;
+
+       bp = abp;
+       if (bp->b_flags&B_ERROR)
+               if ((u.u_error = bp->b_error)==0)
+                       u.u_error = EIO;
+}