Bell 32V development
authorTom London <tbl@research.uucp>
Tue, 23 Jan 1979 10:42:14 +0000 (05:42 -0500)
committerTom London <tbl@research.uucp>
Tue, 23 Jan 1979 10:42:14 +0000 (05:42 -0500)
Work on file usr/src/sys/sys/acct.c
Work on file usr/src/sys/sys/alloc.c
Work on file usr/src/sys/sys/clock.c
Work on file usr/src/sys/sys/dkleave.c
Work on file usr/src/sys/sys/dsort.c
Work on file usr/src/sys/sys/iget.c
Work on file usr/src/sys/sys/main.c
Work on file usr/src/sys/sys/mba.c
Work on file usr/src/sys/sys/partab.c
Work on file usr/src/sys/sys/pipe.c
Work on file usr/src/sys/sys/prf.c
Work on file usr/src/sys/sys/rdwri.c
Work on file usr/src/sys/sys/subr.c
Work on file usr/src/sys/sys/sys2.c
Work on file usr/src/sys/sys/sys3.c
Work on file usr/src/sys/sys/sys4.c
Work on file usr/src/sys/sys/sysent.c
Work on file usr/src/sys/sys/tdump.c
Work on file usr/src/sys/sys/uba.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

19 files changed:
usr/src/sys/sys/acct.c [new file with mode: 0644]
usr/src/sys/sys/alloc.c [new file with mode: 0644]
usr/src/sys/sys/clock.c [new file with mode: 0644]
usr/src/sys/sys/dkleave.c [new file with mode: 0644]
usr/src/sys/sys/dsort.c [new file with mode: 0644]
usr/src/sys/sys/iget.c [new file with mode: 0644]
usr/src/sys/sys/main.c [new file with mode: 0644]
usr/src/sys/sys/mba.c [new file with mode: 0644]
usr/src/sys/sys/partab.c [new file with mode: 0644]
usr/src/sys/sys/pipe.c [new file with mode: 0644]
usr/src/sys/sys/prf.c [new file with mode: 0644]
usr/src/sys/sys/rdwri.c [new file with mode: 0644]
usr/src/sys/sys/subr.c [new file with mode: 0644]
usr/src/sys/sys/sys2.c [new file with mode: 0644]
usr/src/sys/sys/sys3.c [new file with mode: 0644]
usr/src/sys/sys/sys4.c [new file with mode: 0644]
usr/src/sys/sys/sysent.c [new file with mode: 0644]
usr/src/sys/sys/tdump.c [new file with mode: 0644]
usr/src/sys/sys/uba.c [new file with mode: 0644]

diff --git a/usr/src/sys/sys/acct.c b/usr/src/sys/sys/acct.c
new file mode 100644 (file)
index 0000000..ec3f04f
--- /dev/null
@@ -0,0 +1,127 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/acct.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/proc.h"
+#include "../h/seg.h"
+
+/*
+ * Perform process accounting functions.
+ */
+
+sysacct()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (suser()) {
+               if (uap->fname==NULL) {
+                       if (acctp) {
+                               plock(acctp);
+                               iput(acctp);
+                               acctp = NULL;
+                       }
+                       return;
+               }
+               if (acctp) {
+                       u.u_error = EBUSY;
+                       return;
+               }
+               ip = namei(uchar, 0);
+               if(ip == NULL)
+                       return;
+               if((ip->i_mode & IFMT) != IFREG) {
+                       u.u_error = EACCES;
+                       iput(ip);
+                       return;
+               }
+               acctp = ip;
+               prele(ip);
+       }
+}
+
+/*
+ * On exit, write a record on the accounting file.
+ */
+acct()
+{
+       register i;
+       register struct inode *ip;
+       off_t siz;
+
+       if ((ip=acctp)==NULL)
+               return;
+       plock(ip);
+       for (i=0; i<sizeof(acctbuf.ac_comm); i++)
+               acctbuf.ac_comm[i] = u.u_comm[i];
+       acctbuf.ac_utime = compress(u.u_utime);
+       acctbuf.ac_stime = compress(u.u_stime);
+       acctbuf.ac_etime = compress(time - u.u_start);
+       acctbuf.ac_btime = u.u_start;
+       acctbuf.ac_uid = u.u_ruid;
+       acctbuf.ac_gid = u.u_rgid;
+       acctbuf.ac_mem = 0;
+       acctbuf.ac_io = 0;
+       acctbuf.ac_tty = u.u_ttyd;
+       acctbuf.ac_flag = u.u_acflag;
+       siz = ip->i_size;
+       u.u_offset = siz;
+       u.u_base = (caddr_t)&acctbuf;
+       u.u_count = sizeof(acctbuf);
+       u.u_segflg = 1;
+       u.u_error = 0;
+       writei(ip);
+       if(u.u_error)
+               ip->i_size = siz;
+       prele(ip);
+}
+
+/*
+ * Produce a pseudo-floating point representation
+ * with 3 bits base-8 exponent, 13 bits fraction.
+ */
+compress(t)
+register time_t t;
+{
+       register exp = 0, round = 0;
+
+       while (t >= 8192) {
+               exp++;
+               round = t&04;
+               t >>= 3;
+       }
+       if (round) {
+               t++;
+               if (t >= 8192) {
+                       t >>= 3;
+                       exp++;
+               }
+       }
+       return((exp<<13) + t);
+}
+
+/*
+ * lock user into core as much
+ * as possible. swapping may still
+ * occur if core grows.
+ */
+syslock()
+{
+       register struct proc *p;
+       register struct a {
+               int     flag;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if(suser()) {
+               p = u.u_procp;
+               p->p_flag &= ~SULOCK;
+               if(uap->flag)
+                       p->p_flag |= SULOCK;
+       }
+}
diff --git a/usr/src/sys/sys/alloc.c b/usr/src/sys/sys/alloc.c
new file mode 100644 (file)
index 0000000..e3b1818
--- /dev/null
@@ -0,0 +1,317 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/filsys.h"
+#include "../h/fblk.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/inode.h"
+#include "../h/ino.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+typedef        struct fblk *FBLKP;
+
+/*
+ * alloc will obtain the next available
+ * free disk block from the free list of
+ * the specified device.
+ * The super block has up to NICFREE remembered
+ * free blocks; the last of these is read to
+ * obtain NICFREE more . . .
+ *
+ * no space on dev x/y -- when
+ * the free list is exhausted.
+ */
+struct buf *
+alloc(dev)
+dev_t dev;
+{
+       daddr_t bno;
+       register struct filsys *fp;
+       register struct buf *bp;
+
+       fp = getfs(dev);
+       while(fp->s_flock)
+               sleep((caddr_t)&fp->s_flock, PINOD);
+       do {
+               if(fp->s_nfree <= 0)
+                       goto nospace;
+               if (fp->s_nfree > NICFREE) {
+                       prdev("Bad free count", dev);
+                       goto nospace;
+               }
+               bno = fp->s_free[--fp->s_nfree];
+               if(bno == 0)
+                       goto nospace;
+       } while (badblock(fp, bno, dev));
+       if(fp->s_nfree <= 0) {
+               fp->s_flock++;
+               bp = bread(dev, bno);
+               if ((bp->b_flags&B_ERROR) == 0) {
+                       fp->s_nfree = ((FBLKP)(bp->b_un.b_addr))->df_nfree;
+                       bcopy((caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free,
+                           (caddr_t)fp->s_free, sizeof(fp->s_free));
+               }
+               brelse(bp);
+               fp->s_flock = 0;
+               wakeup((caddr_t)&fp->s_flock);
+               if (fp->s_nfree <=0)
+                       goto nospace;
+       }
+       bp = getblk(dev, bno);
+       clrbuf(bp);
+       fp->s_fmod = 1;
+       return(bp);
+
+nospace:
+       fp->s_nfree = 0;
+       prdev("no space", dev);
+       u.u_error = ENOSPC;
+       return(NULL);
+}
+
+/*
+ * place the specified disk block
+ * back on the free list of the
+ * specified device.
+ */
+free(dev, bno)
+dev_t dev;
+daddr_t bno;
+{
+       register struct filsys *fp;
+       register struct buf *bp;
+
+       fp = getfs(dev);
+       fp->s_fmod = 1;
+       while(fp->s_flock)
+               sleep((caddr_t)&fp->s_flock, PINOD);
+       if (badblock(fp, bno, dev))
+               return;
+       if(fp->s_nfree <= 0) {
+               fp->s_nfree = 1;
+               fp->s_free[0] = 0;
+       }
+       if(fp->s_nfree >= NICFREE) {
+               fp->s_flock++;
+               bp = getblk(dev, bno);
+               ((FBLKP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree;
+               bcopy((caddr_t)fp->s_free,
+                       (caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free,
+                       sizeof(fp->s_free));
+               fp->s_nfree = 0;
+               bwrite(bp);
+               fp->s_flock = 0;
+               wakeup((caddr_t)&fp->s_flock);
+       }
+       fp->s_free[fp->s_nfree++] = bno;
+       fp->s_fmod = 1;
+}
+
+/*
+ * Check that a block number is in the
+ * range between the I list and the size
+ * of the device.
+ * This is used mainly to check that a
+ * garbage file system has not been mounted.
+ *
+ * bad block on dev x/y -- not in range
+ */
+badblock(fp, bn, dev)
+register struct filsys *fp;
+daddr_t bn;
+dev_t dev;
+{
+
+       if (bn < fp->s_isize || bn >= fp->s_fsize) {
+               prdev("bad block", dev);
+               return(1);
+       }
+       return(0);
+}
+
+/*
+ * Allocate an unused I node
+ * on the specified device.
+ * Used with file creation.
+ * The algorithm keeps up to
+ * NICINOD spare I nodes in the
+ * super block. When this runs out,
+ * a linear search through the
+ * I list is instituted to pick
+ * up NICINOD more.
+ */
+struct inode *
+ialloc(dev)
+dev_t dev;
+{
+       register struct filsys *fp;
+       register struct buf *bp;
+       register struct inode *ip;
+       int i;
+       struct dinode *dp;
+       ino_t ino;
+       daddr_t adr;
+
+       fp = getfs(dev);
+       while(fp->s_ilock)
+               sleep((caddr_t)&fp->s_ilock, PINOD);
+loop:
+       if(fp->s_ninode > 0) {
+               ino = fp->s_inode[--fp->s_ninode];
+               ip = iget(dev, ino);
+               if(ip == NULL)
+                       return(NULL);
+               if(ip->i_mode == 0) {
+                       for (i=0; i<NADDR; i++)
+                               ip->i_un.i_addr[i] = 0;
+                       fp->s_fmod = 1;
+                       return(ip);
+               }
+               /*
+                * Inode was allocated after all.
+                * Look some more.
+                */
+               iput(ip);
+               goto loop;
+       }
+       fp->s_ilock++;
+       ino = 1;
+       for(adr = SUPERB+1; adr < fp->s_isize; adr++) {
+               bp = bread(dev, adr);
+               if (bp->b_flags & B_ERROR) {
+                       brelse(bp);
+                       ino += INOPB;
+                       continue;
+               }
+               dp = bp->b_un.b_dino;
+               for(i=0; i<INOPB; i++) {
+                       if(dp->di_mode != 0)
+                               goto cont;
+                       for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+                       if(dev==ip->i_dev && ino==ip->i_number)
+                               goto cont;
+                       fp->s_inode[fp->s_ninode++] = ino;
+                       if(fp->s_ninode >= NICINOD)
+                               break;
+               cont:
+                       ino++;
+                       dp++;
+               }
+               brelse(bp);
+               if(fp->s_ninode >= NICINOD)
+                       break;
+       }
+       fp->s_ilock = 0;
+       wakeup((caddr_t)&fp->s_ilock);
+       if(fp->s_ninode > 0)
+               goto loop;
+       prdev("Out of inodes", dev);
+       u.u_error = ENOSPC;
+       return(NULL);
+}
+
+/*
+ * Free the specified I node
+ * on the specified device.
+ * The algorithm stores up
+ * to NICINOD I nodes in the super
+ * block and throws away any more.
+ */
+ifree(dev, ino)
+dev_t dev;
+ino_t ino;
+{
+       register struct filsys *fp;
+
+       fp = getfs(dev);
+       if(fp->s_ilock)
+               return;
+       if(fp->s_ninode >= NICINOD)
+               return;
+       fp->s_inode[fp->s_ninode++] = ino;
+       fp->s_fmod = 1;
+}
+
+/*
+ * getfs maps a device number into
+ * a pointer to the incore super
+ * block.
+ * The algorithm is a linear
+ * search through the mount table.
+ * A consistency check of the
+ * in core free-block and i-node
+ * counts.
+ *
+ * bad count on dev x/y -- the count
+ *     check failed. At this point, all
+ *     the counts are zeroed which will
+ *     almost certainly lead to "no space"
+ *     diagnostic
+ * panic: no fs -- the device is not mounted.
+ *     this "cannot happen"
+ */
+struct filsys *
+getfs(dev)
+dev_t dev;
+{
+       register struct mount *mp;
+       register struct filsys *fp;
+
+       for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+       if(mp->m_bufp != NULL && mp->m_dev == dev) {
+               fp = mp->m_bufp->b_un.b_filsys;
+               if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) {
+                       prdev("bad count", dev);
+                       fp->s_nfree = 0;
+                       fp->s_ninode = 0;
+               }
+               return(fp);
+       }
+       panic("no fs");
+       return(NULL);
+}
+
+/*
+ * update is the internal name of
+ * 'sync'. It goes through the disk
+ * queues to initiate sandbagged IO;
+ * goes through the I nodes to write
+ * modified nodes; and it goes through
+ * the mount table to initiate modified
+ * super blocks.
+ */
+update()
+{
+       register struct inode *ip;
+       register struct mount *mp;
+       register struct buf *bp;
+       struct filsys *fp;
+
+       if(updlock)
+               return;
+       updlock++;
+       for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+               if(mp->m_bufp != NULL) {
+                       fp = mp->m_bufp->b_un.b_filsys;
+                       if(fp->s_fmod==0 || fp->s_ilock!=0 ||
+                          fp->s_flock!=0 || fp->s_ronly!=0)
+                               continue;
+                       bp = getblk(mp->m_dev, SUPERB);
+                       if (bp->b_flags & B_ERROR)
+                               continue;
+                       fp->s_fmod = 0;
+                       fp->s_time = time;
+                       bcopy((caddr_t)fp, bp->b_un.b_addr, BSIZE);
+                       bwrite(bp);
+               }
+       for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+               if((ip->i_flag&ILOCK)==0 && ip->i_count) {
+                       ip->i_flag |= ILOCK;
+                       ip->i_count++;
+                       iupdat(ip, &time, &time);
+                       iput(ip);
+               }
+       updlock = 0;
+       bflush(NODEV);
+}
diff --git a/usr/src/sys/sys/clock.c b/usr/src/sys/sys/clock.c
new file mode 100644 (file)
index 0000000..014870d
--- /dev/null
@@ -0,0 +1,180 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/callo.h"
+#include "../h/seg.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/reg.h"
+#include "../h/psl.h"
+
+#define        SCHMAG  8/10
+
+
+/*
+ * clock is called straight from
+ * the real time clock interrupt.
+ *
+ * Functions:
+ *     copy *switches to display
+ *     implement callouts
+ *     maintain user/system times
+ *     maintain date
+ *     profile
+ *     lightning bolt wakeup (every second)
+ *     alarm clock signals
+ *     jab the scheduler
+ */
+
+clock(pc, ps)
+caddr_t pc;
+{
+       register struct callo *p1, *p2;
+       register struct proc *pp;
+       int a;
+       extern caddr_t waitloc, ewaitloc;
+
+       /*
+        * reprime clock
+        */
+       clkreld();
+
+
+
+
+       /*
+        * callouts
+        * if none, just continue
+        * else update first non-zero time
+        */
+
+       if(callout[0].c_func == NULL)
+               goto out;
+       p2 = &callout[0];
+       while(p2->c_time<=0 && p2->c_func!=NULL)
+               p2++;
+       p2->c_time--;
+
+       /*
+        * if ps is high, just return
+        */
+       if (BASEPRI(ps))
+               goto out;
+
+       /*
+        * callout
+        */
+
+       if(callout[0].c_time <= 0) {
+               p1 = &callout[0];
+               while(p1->c_func != 0 && p1->c_time <= 0) {
+                       (*p1->c_func)(p1->c_arg);
+                       p1++;
+               }
+               p2 = &callout[0];
+               while(p2->c_func = p1->c_func) {
+                       p2->c_time = p1->c_time;
+                       p2->c_arg = p1->c_arg;
+                       p1++;
+                       p2++;
+               }
+       }
+
+       /*
+        * lightning bolt time-out
+        * and time of day
+        */
+out:
+       a = dk_busy&07;
+       if (USERMODE(ps)) {
+               u.u_utime++;
+               if(u.u_prof.pr_scale)
+                       addupc(pc, &u.u_prof, 1);
+               if(u.u_procp->p_nice > NZERO)
+                       a += 8;
+       } else {
+               a += 16;
+               if (pc == waitloc || pc == ewaitloc )
+                       a += 8;
+               u.u_stime++;
+       }
+       dk_time[a] += 1;
+       pp = u.u_procp;
+       if(++pp->p_cpu == 0)
+               pp->p_cpu--;
+       if(++lbolt >= HZ) {
+               if (BASEPRI(ps))
+                       return;
+               lbolt -= HZ;
+               ++time;
+               runrun++;
+               wakeup((caddr_t)&lbolt);
+               for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
+               if (pp->p_stat && pp->p_stat<SZOMB) {
+                       if(pp->p_time != 127)
+                               pp->p_time++;
+                       if(pp->p_clktim)
+                               if(--pp->p_clktim == 0)
+                                       psignal(pp, SIGCLK);
+                       a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
+                       if(a < 0)
+                               a = 0;
+                       if(a > 255)
+                               a = 255;
+                       pp->p_cpu = a;
+                       if(pp->p_pri >= PUSER)
+                               setpri(pp);
+               }
+               if(runin!=0) {
+                       runin = 0;
+                       wakeup((caddr_t)&runin);
+               }
+       }
+}
+
+/*
+ * timeout is called to arrange that
+ * fun(arg) is called in tim/HZ seconds.
+ * An entry is sorted into the callout
+ * structure. The time in each structure
+ * entry is the number of HZ's more
+ * than the previous entry.
+ * In this way, decrementing the
+ * first entry has the effect of
+ * updating all entries.
+ *
+ * The panic is there because there is nothing
+ * intelligent to be done if an entry won't fit.
+ */
+timeout(fun, arg, tim)
+int (*fun)();
+caddr_t arg;
+{
+       register struct callo *p1, *p2;
+       register int t;
+       int s;
+
+       t = tim;
+       p1 = &callout[0];
+       s = spl7();
+       while(p1->c_func != 0 && p1->c_time <= t) {
+               t -= p1->c_time;
+               p1++;
+       }
+       if (p1 >= &callout[NCALL-1])
+               panic("Timeout table overflow");
+       p1->c_time -= t;
+       p2 = p1;
+       while(p2->c_func != 0)
+               p2++;
+       while(p2 >= p1) {
+               (p2+1)->c_time = p2->c_time;
+               (p2+1)->c_func = p2->c_func;
+               (p2+1)->c_arg = p2->c_arg;
+               p2--;
+       }
+       p1->c_time = t;
+       p1->c_func = fun;
+       p1->c_arg = arg;
+       splx(s);
+}
diff --git a/usr/src/sys/sys/dkleave.c b/usr/src/sys/sys/dkleave.c
new file mode 100644 (file)
index 0000000..7cd7a7d
--- /dev/null
@@ -0,0 +1,29 @@
+#include "../h/param.h"
+#include "../h/buf.h"
+
+daddr_t
+dkblock(bp)
+register struct buf *bp;
+{
+       register int dminor;
+
+       if (((dminor=minor(bp->b_dev))&0100) == 0)
+               return(bp->b_blkno);
+       dminor >>= 3;
+       dminor &= 07;
+       dminor++;
+       return(bp->b_blkno/dminor);
+}
+
+dkunit(bp)
+register struct buf *bp;
+{
+       register int dminor;
+
+       dminor = minor(bp->b_dev) >> 3;
+       if ((dminor&010) == 0)
+               return(dminor);
+       dminor &= 07;
+       dminor++;
+       return(bp->b_blkno%dminor);
+}
diff --git a/usr/src/sys/sys/dsort.c b/usr/src/sys/sys/dsort.c
new file mode 100644 (file)
index 0000000..5a90c1e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * generalized seek sort for disk
+ */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/buf.h"
+
+#define        b_cylin b_resid
+
+disksort(dp, bp)
+register struct buf *dp, *bp;
+{
+       register struct buf *ap;
+       struct buf *tp;
+
+       ap = dp->b_actf;
+       if(ap == NULL) {
+               dp->b_actf = bp;
+               dp->b_actl = bp;
+               bp->av_forw = NULL;
+               return;
+       }
+       tp = NULL;
+       for(; ap != NULL; ap = ap->av_forw) {
+               if ((bp->b_flags&B_READ) && (ap->b_flags&B_READ) == 0) {
+                       if (tp == NULL)
+                               tp = ap;
+                       break;
+               }
+               if ((bp->b_flags&B_READ) == 0 && (ap->b_flags&B_READ))
+                       continue;
+               if(ap->b_cylin <= bp->b_cylin)
+                       if(tp == NULL || ap->b_cylin >= tp->b_cylin)
+                               tp = ap;
+       }
+       if(tp == NULL)
+               tp = dp->b_actl;
+       bp->av_forw = tp->av_forw;
+       tp->av_forw = bp;
+       if(tp == dp->b_actl)
+               dp->b_actl = bp;
+}
diff --git a/usr/src/sys/sys/iget.c b/usr/src/sys/sys/iget.c
new file mode 100644 (file)
index 0000000..09ae774
--- /dev/null
@@ -0,0 +1,316 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/ino.h"
+#include "../h/filsys.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+
+/*
+ * Look up an inode by device,inumber.
+ * If it is in core (in the inode structure),
+ * honor the locking protocol.
+ * If it is not in core, read it in from the
+ * specified device.
+ * If the inode is mounted on, perform
+ * the indicated indirection.
+ * In all cases, a pointer to a locked
+ * inode structure is returned.
+ *
+ * printf warning: no inodes -- if the inode
+ *     structure is full
+ * panic: no imt -- if the mounted file
+ *     system is not in the mount table.
+ *     "cannot happen"
+ */
+struct inode *
+iget(dev, ino)
+dev_t dev;
+ino_t ino;
+{
+       register struct inode *ip;
+       register struct mount *mp;
+       register struct inode *oip;
+       register struct buf *bp;
+       register struct dinode *dp;
+
+loop:
+       oip = NULL;
+       for(ip = &inode[0]; ip < &inode[NINODE]; ip++) {
+               if(ino == ip->i_number && dev == ip->i_dev) {
+                       if((ip->i_flag&ILOCK) != 0) {
+                               ip->i_flag |= IWANT;
+                               sleep((caddr_t)ip, PINOD);
+                               goto loop;
+                       }
+                       if((ip->i_flag&IMOUNT) != 0) {
+                               for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+                               if(mp->m_inodp == ip) {
+                                       dev = mp->m_dev;
+                                       ino = ROOTINO;
+                                       goto loop;
+                               }
+                               panic("no imt");
+                       }
+                       ip->i_count++;
+                       ip->i_flag |= ILOCK;
+                       return(ip);
+               }
+               if(oip==NULL && ip->i_count==0)
+                       oip = ip;
+       }
+       ip = oip;
+       if(ip == NULL) {
+               printf("Inode table overflow\n");
+               u.u_error = ENFILE;
+               return(NULL);
+       }
+       ip->i_dev = dev;
+       ip->i_number = ino;
+       ip->i_flag = ILOCK;
+       ip->i_count++;
+       ip->i_un.i_lastr = 0;
+       bp = bread(dev, itod(ino));
+       /*
+        * Check I/O errors
+        */
+       if((bp->b_flags&B_ERROR) != 0) {
+               brelse(bp);
+               iput(ip);
+               return(NULL);
+       }
+       dp = bp->b_un.b_dino;
+       dp += itoo(ino);
+       iexpand(ip, dp);
+       brelse(bp);
+       return(ip);
+}
+
+iexpand(ip, dp)
+register struct inode *ip;
+register struct dinode *dp;
+{
+       register char *p1;
+       char *p2;
+       int i;
+
+       ip->i_mode = dp->di_mode;
+       ip->i_nlink = dp->di_nlink;
+       ip->i_uid = dp->di_uid;
+       ip->i_gid = dp->di_gid;
+       ip->i_size = dp->di_size;
+       p1 = (char *)ip->i_un.i_addr;
+       p2 = (char *)dp->di_addr;
+       for(i=0; i<NADDR; i++) {
+               *p1++ = *p2++;
+               *p1++ = *p2++;
+               *p1++ = *p2++;
+               *p1++ = 0;
+       }
+}
+
+/*
+ * Decrement reference count of
+ * an inode structure.
+ * On the last reference,
+ * write the inode out and if necessary,
+ * truncate and deallocate the file.
+ */
+iput(ip)
+register struct inode *ip;
+{
+
+       if(ip->i_count == 1) {
+               ip->i_flag |= ILOCK;
+               if(ip->i_nlink <= 0) {
+                       itrunc(ip);
+                       ip->i_mode = 0;
+                       ip->i_flag |= IUPD|ICHG;
+                       ifree(ip->i_dev, ip->i_number);
+               }
+               iupdat(ip, &time, &time);
+               prele(ip);
+               ip->i_flag = 0;
+               ip->i_number = 0;
+       }
+       ip->i_count--;
+       prele(ip);
+}
+
+/*
+ * Check accessed and update flags on
+ * an inode structure.
+ * If any is on, update the inode
+ * with the current time.
+ */
+iupdat(ip, ta, tm)
+register struct inode *ip;
+time_t *ta, *tm;
+{
+       register struct buf *bp;
+       struct dinode *dp;
+       register char *p1;
+       char *p2;
+       int i;
+
+       if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
+               if(getfs(ip->i_dev)->s_ronly)
+                       return;
+               bp = bread(ip->i_dev, itod(ip->i_number));
+               if (bp->b_flags & B_ERROR) {
+                       brelse(bp);
+                       return;
+               }
+               dp = bp->b_un.b_dino;
+               dp += itoo(ip->i_number);
+               dp->di_mode = ip->i_mode;
+               dp->di_nlink = ip->i_nlink;
+               dp->di_uid = ip->i_uid;
+               dp->di_gid = ip->i_gid;
+               dp->di_size = ip->i_size;
+               p1 = (char *)dp->di_addr;
+               p2 = (char *)ip->i_un.i_addr;
+               for(i=0; i<NADDR; i++) {
+                       *p1++ = *p2++;
+                       *p1++ = *p2++;
+                       *p1++ = *p2++;
+                       if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC
+                          && (ip->i_mode&IFMT)!=IFMPB)
+                               printf("iaddress > 2^24\n");
+               }
+               if(ip->i_flag&IACC)
+                       dp->di_atime = *ta;
+               if(ip->i_flag&IUPD)
+                       dp->di_mtime = *tm;
+               if(ip->i_flag&ICHG)
+                       dp->di_ctime = time;
+               ip->i_flag &= ~(IUPD|IACC|ICHG);
+               bdwrite(bp);
+       }
+}
+
+/*
+ * Free all the disk blocks associated
+ * with the specified inode structure.
+ * The blocks of the file are removed
+ * in reverse order. This FILO
+ * algorithm will tend to maintain
+ * a contiguous free list much longer
+ * than FIFO.
+ */
+itrunc(ip)
+register struct inode *ip;
+{
+       register i;
+       dev_t dev;
+       daddr_t bn;
+
+       i = ip->i_mode & IFMT;
+       if (i!=IFREG && i!=IFDIR)
+               return;
+       dev = ip->i_dev;
+       for(i=NADDR-1; i>=0; i--) {
+               bn = ip->i_un.i_addr[i];
+               if(bn == (daddr_t)0)
+                       continue;
+               ip->i_un.i_addr[i] = (daddr_t)0;
+               switch(i) {
+
+               default:
+                       free(dev, bn);
+                       break;
+
+               case NADDR-3:
+                       tloop(dev, bn, 0, 0);
+                       break;
+
+               case NADDR-2:
+                       tloop(dev, bn, 1, 0);
+                       break;
+
+               case NADDR-1:
+                       tloop(dev, bn, 1, 1);
+               }
+       }
+       ip->i_size = 0;
+       ip->i_flag |= ICHG|IUPD;
+}
+
+tloop(dev, bn, f1, f2)
+dev_t dev;
+daddr_t bn;
+{
+       register i;
+       register struct buf *bp;
+       register daddr_t *bap;
+       daddr_t nb;
+
+       bp = NULL;
+       for(i=NINDIR-1; i>=0; i--) {
+               if(bp == NULL) {
+                       bp = bread(dev, bn);
+                       if (bp->b_flags & B_ERROR) {
+                               brelse(bp);
+                               return;
+                       }
+                       bap = bp->b_un.b_daddr;
+               }
+               nb = bap[i];
+               if(nb == (daddr_t)0)
+                       continue;
+               if(f1) {
+                       brelse(bp);
+                       bp = NULL;
+                       tloop(dev, nb, f2, 0);
+               } else
+                       free(dev, nb);
+       }
+       if(bp != NULL)
+               brelse(bp);
+       free(dev, bn);
+}
+
+/*
+ * Make a new file.
+ */
+struct inode *
+maknode(mode)
+{
+       register struct inode *ip;
+
+       ip = ialloc(u.u_pdir->i_dev);
+       if(ip == NULL) {
+               iput(u.u_pdir);
+               return(NULL);
+       }
+       ip->i_flag |= IACC|IUPD|ICHG;
+       if((mode&IFMT) == 0)
+               mode |= IFREG;
+       ip->i_mode = mode & ~u.u_cmask;
+       ip->i_nlink = 1;
+       ip->i_uid = u.u_uid;
+       ip->i_gid = u.u_gid;
+       wdir(ip);
+       return(ip);
+}
+
+/*
+ * Write a directory entry with
+ * parameters left as side effects
+ * to a call to namei.
+ */
+wdir(ip)
+struct inode *ip;
+{
+
+       u.u_dent.d_ino = ip->i_number;
+       bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
+       u.u_count = sizeof(struct direct);
+       u.u_segflg = 1;
+       u.u_base = (caddr_t)&u.u_dent;
+       writei(u.u_pdir);
+       iput(u.u_pdir);
+}
diff --git a/usr/src/sys/sys/main.c b/usr/src/sys/sys/main.c
new file mode 100644 (file)
index 0000000..27a9ee8
--- /dev/null
@@ -0,0 +1,169 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/filsys.h"
+#include "../h/mount.h"
+#include "../h/uba.h"
+#include "../h/map.h"
+#include "../h/proc.h"
+#include "../h/inode.h"
+#include "../h/seg.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/mtpr.h"
+#include "../h/page.h"
+# include "../h/clock.h"
+
+
+/*
+ * Initialization code.
+ * Called from cold start routine as
+ * soon as a stack and segmentation
+ * have been established.
+ * Functions:
+ *     clear and free user core
+ *     turn on clock
+ *     hand craft 0th process
+ *     call all initialization routines
+ *     fork - process 0 to schedule
+ *          - process 1 execute bootstrap
+ *
+ * loop at loc 13 (0xd) in user mode -- /etc/init
+ *     cannot be executed.
+ */
+main(firstaddr)
+{
+       int i;
+
+       startup(firstaddr);
+
+       /*
+        * set up system process
+        */
+
+       for(i=0; i<UPAGES; i++) {
+               proc[0].p_addr[i] = firstaddr + i;
+       }
+       proc[0].p_size = UPAGES;
+       proc[0].p_stat = SRUN;
+       proc[0].p_flag |= SLOAD|SSYS;
+       proc[0].p_nice = NZERO;
+       u.u_procp = &proc[0];
+       u.u_cmask = CMASK;
+       clkstart();
+
+       /*
+        * Initialize devices and
+        * set up 'known' i-nodes
+        */
+
+       cinit();
+       binit();
+       iinit();
+       rootdir = iget(rootdev, (ino_t)ROOTINO);
+       rootdir->i_flag &= ~ILOCK;
+       u.u_cdir = iget(rootdev, (ino_t)ROOTINO);
+       u.u_cdir->i_flag &= ~ILOCK;
+       u.u_rdir = NULL;
+
+       /*
+        * make init process
+        * enter scheduling loop
+        * with system process
+        */
+
+       if(newproc()) {
+               expand(btoc(szicode), P0BR);
+               u.u_dsize = btoc(szicode);
+               copyout((caddr_t)icode, (caddr_t)0, szicode);
+               /*
+                * Return goes to loc. 0 of user init
+                * code just copied out.
+                */
+               return;
+       }
+       sched();
+}
+
+/*
+ * iinit is called once (from main)
+ * very early in initialization.
+ * It reads the root's super block
+ * and initializes the current date
+ * from the last modified date.
+ *
+ * panic: iinit -- cannot read the super
+ * block. Usually because of an IO error.
+ */
+iinit()
+{
+       register struct buf *cp, *bp;
+       register struct filsys *fp;
+       register unsigned i , j ;
+
+       (*bdevsw[major(rootdev)].d_open)(rootdev, 1);
+       bp = bread(rootdev, SUPERB);
+       cp = geteblk();
+       if(u.u_error)
+               panic("iinit");
+       bcopy(bp->b_un.b_addr, cp->b_un.b_addr, sizeof(struct filsys));
+       brelse(bp);
+       mount[0].m_bufp = cp;
+       mount[0].m_dev = rootdev;
+       fp = cp->b_un.b_filsys;
+       fp->s_flock = 0;
+       fp->s_ilock = 0;
+       fp->s_ronly = 0;
+       /* on boot, read VAX TODR register (GMT 10 ms.
+       *       clicks into current year) and set software time
+       *       in 'int time' (GMT seconds since year YRREF)
+       */
+       for (i = 0 , j = YRREF ; j < YRCURR ; j++)
+               i += (SECYR + (j%4?0:SECDAY)) ;
+       time = udiv(mfpr(TODR),100) + i ;
+}
+
+/*
+ * This is the set of buffers proper, whose heads
+ * were declared in buf.h.  There can exist buffer
+ * headers not pointing here that are used purely
+ * as arguments to the I/O routines to describe
+ * I/O to be done-- e.g. swbuf for
+ * swapping.
+ */
+char   buffers[NBUF][BSIZE+BSLOP];
+
+/*
+ * Initialize the buffer I/O system by freeing
+ * all buffers and setting all device buffer lists to empty.
+ */
+binit()
+{
+       register struct buf *bp;
+       register struct buf *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 = NODEV;
+               bp->b_un.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);
+       }
+       for (bdp = bdevsw; bdp->d_open; bdp++) {
+               dp = bdp->d_tab;
+               if(dp) {
+                       dp->b_forw = dp;
+                       dp->b_back = dp;
+               }
+               nblkdev++;
+       }
+}
diff --git a/usr/src/sys/sys/mba.c b/usr/src/sys/sys/mba.c
new file mode 100644 (file)
index 0000000..f3c973c
--- /dev/null
@@ -0,0 +1,96 @@
+#
+/*
+ */
+
+#include "../h/param.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/seg.h"
+#include "../h/page.h"
+#include "../h/uba.h"
+#include "../h/map.h"
+#include "../h/mba.h"
+#include "../h/mtpr.h"
+
+/*
+ * startup routine for MBA controllers.
+ */
+#define        MBAWCOM 0x30
+#define        MBARCOM 0x38
+#define        GO      01
+
+int mbaboff;
+
+mbastart(bp, adcr)
+register struct buf *bp;
+int *adcr;
+{
+       int vaddr, com;
+       register int *io, num;
+       register struct mba_regs *mbap;
+       register int *pt, i;
+       int pf;
+       extern int mbanum[], *mbaloc[], mbautl[], Mbamap[];
+       extern char buffers[][];
+
+       mbap = (struct mba_regs *)mbaloc[mbanum[major(bp->b_dev)]];
+       if ( (bp->b_flags & B_PHYS) == 0 ) {
+               vaddr = (bp->b_un.b_addr - (char *)buffers) + mbaboff;
+       } else {
+               ptaccess(bp->b_proc, Mbamap, mbautl);   /* get to u-area & page tables */
+               io = (int *)mbap;
+               io += (MBA_MAP + 128*4)/4;
+               vaddr = (128 << 9) | ((int)bp->b_un.b_addr & 0x1ff);
+               pf = (int)bp->b_un.b_addr >> 9;
+               num = (((int)bp->b_un.b_addr + bp->b_bcount - 1) >> 9) - pf +1;
+               if ((bp -> b_flags & B_UAREA) != 0)  {  /* u-area should be part of the I/O */
+                       for(i=0; i<UPAGES; i++) {
+                           if ((*io++ = PG_V | bp->b_proc->p_addr[i])==PG_V)
+                               panic("mba, zero u-page");
+                       }
+                       num -= UPAGES;
+               }
+               if (pf & 0x200000) {    /* I/O to stack */
+                       i = ((struct user *)mbautl)->u_pcb.pcb_szpt;
+                       pf = i*128 + pf - 0x400000;
+               }
+               pt = mbautl + UPAGES*128 + pf;
+               while ( num-->0) {
+                       if ((*io++ = *pt++ | PG_V)==PG_V)
+                               panic("mba, zero entry");
+               }
+       }
+       mbap->mba_sr = -1;      /* clear status (error) bits */
+       mbap->mba_bcr = -bp->b_bcount;
+       mbap->mba_var = vaddr;
+       if (bp->b_flags & B_READ)
+               com = MBARCOM | GO;
+       else
+               com = MBAWCOM | GO;
+
+       *adcr = com;            /* set cmd in device control and status register */
+}
+
+mbainit()
+{
+       register int *io0, *io1, *b, t, j;
+       extern int Sysmap[], *mbaloc[];
+       extern char buffers[][];
+
+       io0 = mbaloc[0] + (MBA_MAP/4);
+       io1 = mbaloc[1] + (MBA_MAP/4);
+       b = Sysmap + ((((int) buffers)>>9)&PG_PFNUM);
+       j = NBUF + ((int)buffers & 0x1ff ? 1 : 0);
+       do {
+               t = PG_V | (*b++ & PG_PFNUM);
+               *io0++ = t;
+               *io1++ = t;
+       } while (--j>0);
+       *io0 = 0;               /* invalidate next entry */
+       *io1 = 0;
+       mbaboff = (int)buffers & 0x1ff;
+}
diff --git a/usr/src/sys/sys/partab.c b/usr/src/sys/sys/partab.c
new file mode 100644 (file)
index 0000000..44628c4
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ */
+
+char partab[] = {
+       0001,0201,0201,0001,0201,0001,0001,0201,
+       0202,0004,0003,0201,0005,0206,0201,0001,
+       0201,0001,0001,0201,0001,0201,0201,0001,
+       0001,0201,0201,0001,0201,0001,0001,0201,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0201
+};
diff --git a/usr/src/sys/sys/pipe.c b/usr/src/sys/sys/pipe.c
new file mode 100644 (file)
index 0000000..1ca26ba
--- /dev/null
@@ -0,0 +1,216 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/reg.h"
+
+/*
+ * Max allowable buffering per pipe.
+ * This is also the max size of the
+ * file created to implement the pipe.
+ * If this size is bigger than 5120,
+ * pipes will be implemented with large
+ * files, which is probably not good.
+ */
+#define        PIPSIZ  4096
+
+/*
+ * The sys-pipe entry.
+ * Allocate an inode on the root device.
+ * Allocate 2 file structures.
+ * Put it all together with flags.
+ */
+pipe()
+{
+       register struct inode *ip;
+       register struct file *rf, *wf;
+       int r;
+
+       ip = ialloc(pipedev);
+       if(ip == NULL)
+               return;
+       rf = falloc();
+       if(rf == NULL) {
+               iput(ip);
+               return;
+       }
+       r = u.u_r.r_val1;
+       wf = falloc();
+       if(wf == NULL) {
+               rf->f_count = 0;
+               u.u_ofile[r] = NULL;
+               iput(ip);
+               return;
+       }
+       u.u_r.r_val2 = u.u_r.r_val1;
+       u.u_r.r_val1 = r;
+       wf->f_flag = FWRITE|FPIPE;
+       wf->f_inode = ip;
+       rf->f_flag = FREAD|FPIPE;
+       rf->f_inode = ip;
+       ip->i_count = 2;
+       ip->i_mode = IFREG;
+       ip->i_flag = IACC|IUPD|ICHG;
+}
+
+/*
+ * Read call directed to a pipe.
+ */
+readp(fp)
+register struct file *fp;
+{
+       register struct inode *ip;
+
+       ip = fp->f_inode;
+
+loop:
+       /*
+        * Very conservative locking.
+        */
+
+       plock(ip);
+       /*
+        * If nothing in the pipe, wait.
+        */
+       if (ip->i_size == 0) {
+               /*
+                * If there are not both reader and
+                * writer active, return without
+                * satisfying read.
+                */
+               prele(ip);
+               if(ip->i_count < 2)
+                       return;
+               ip->i_mode |= IREAD;
+               sleep((caddr_t)ip+2, PPIPE);
+               goto loop;
+       }
+
+       /*
+        * Read and return
+        */
+
+       u.u_offset = fp->f_un.f_offset;
+       readi(ip);
+       fp->f_un.f_offset = u.u_offset;
+       /*
+        * If reader has caught up with writer, reset
+        * offset and size to 0.
+        */
+       if (fp->f_un.f_offset == ip->i_size) {
+               fp->f_un.f_offset = 0;
+               ip->i_size = 0;
+               if(ip->i_mode & IWRITE) {
+                       ip->i_mode &= ~IWRITE;
+                       wakeup((caddr_t)ip+1);
+               }
+       }
+       prele(ip);
+}
+
+/*
+ * Write call directed to a pipe.
+ */
+writep(fp)
+register struct file *fp;
+{
+       register c;
+       register struct inode *ip;
+
+       ip = fp->f_inode;
+       c = u.u_count;
+
+loop:
+
+       /*
+        * If all done, return.
+        */
+
+       plock(ip);
+       if(c == 0) {
+               prele(ip);
+               u.u_count = 0;
+               return;
+       }
+
+       /*
+        * If there are not both read and
+        * write sides of the pipe active,
+        * return error and signal too.
+        */
+
+       if(ip->i_count < 2) {
+               prele(ip);
+               u.u_error = EPIPE;
+               psignal(u.u_procp, SIGPIPE);
+               return;
+       }
+
+       /*
+        * If the pipe is full,
+        * wait for reads to deplete
+        * and truncate it.
+        */
+
+       if(ip->i_size >= PIPSIZ) {
+               ip->i_mode |= IWRITE;
+               prele(ip);
+               sleep((caddr_t)ip+1, PPIPE);
+               goto loop;
+       }
+
+       /*
+        * Write what is possible and
+        * loop back.
+        * If writing less than PIPSIZ, it always goes.
+        * One can therefore get a file > PIPSIZ if write
+        * sizes do not divide PIPSIZ.
+        */
+
+       u.u_offset = ip->i_size;
+       u.u_count = min((unsigned)c, (unsigned)PIPSIZ);
+       c -= u.u_count;
+       writei(ip);
+       prele(ip);
+       if(ip->i_mode&IREAD) {
+               ip->i_mode &= ~IREAD;
+               wakeup((caddr_t)ip+2);
+       }
+       goto loop;
+}
+
+/*
+ * Lock a pipe.
+ * If its already locked,
+ * set the WANT bit and sleep.
+ */
+plock(ip)
+register struct inode *ip;
+{
+
+       while(ip->i_flag&ILOCK) {
+               ip->i_flag |= IWANT;
+               sleep((caddr_t)ip, PINOD);
+       }
+       ip->i_flag |= ILOCK;
+}
+
+/*
+ * Unlock a pipe.
+ * If WANT bit is on,
+ * wakeup.
+ * This routine is also used
+ * to unlock inodes in general.
+ */
+prele(ip)
+register struct inode *ip;
+{
+
+       ip->i_flag &= ~ILOCK;
+       if(ip->i_flag&IWANT) {
+               ip->i_flag &= ~IWANT;
+               wakeup((caddr_t)ip);
+       }
+}
diff --git a/usr/src/sys/sys/prf.c b/usr/src/sys/sys/prf.c
new file mode 100644 (file)
index 0000000..842897d
--- /dev/null
@@ -0,0 +1,116 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/seg.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+
+/*
+ * In case console is off,
+ * panicstr contains argument to last
+ * call to panic.
+ */
+
+char   *panicstr;
+
+/*
+ * Scaled down version of C Library printf.
+ * Only %s %u %d (==%u) %o %x %D are recognized.
+ * Used to print diagnostic information
+ * directly on console tty.
+ * Since it is not interrupt driven,
+ * all system activities are pretty much
+ * suspended.
+ * Printf should not be used for chit-chat.
+ */
+/* VARARGS */
+printf(fmt, x1)
+register char *fmt;
+unsigned x1;
+{
+       register c;
+       register unsigned int *adx;
+       char *s;
+
+       adx = &x1;
+loop:
+       while((c = *fmt++) != '%') {
+               if(c == '\0')
+                       return;
+               putchar(c);
+       }
+       c = *fmt++;
+       if(c == 'd' || c == 'u' || c == 'o' || c == 'x')
+               printn((long)*adx, c=='o'? 8: (c=='x'? 16:10));
+       else if(c == 's') {
+               s = (char *)*adx;
+               while(c = *s++)
+                       putchar(c);
+       } else if (c == 'D') {
+               printn(*(long *)adx, 10);
+               adx += (sizeof(long) / sizeof(int)) - 1;
+       }
+       adx++;
+       goto loop;
+}
+
+/*
+ * Print an unsigned integer in base b.
+ */
+printn(n, b)
+long n;
+{
+       register long a;
+
+       if (n<0) {      /* shouldn't happen */
+               putchar('-');
+               n = -n;
+       }
+       if(a = n/b)
+               printn(a, b);
+       putchar("0123456789ABCDEF"[(int)(n%b)]);
+}
+
+/*
+ * Panic is called on unresolvable
+ * fatal errors.
+ * It syncs, prints "panic: mesg" and
+ * then loops.
+ */
+panic(s)
+char *s;
+{
+       panicstr = s;
+       update();
+       printf("panic: %s\n", s);
+       for(;;)
+               idle();
+}
+
+/*
+ * prdev prints a warning message of the
+ * form "mesg on dev x/y".
+ * x and y are the major and minor parts of
+ * the device argument.
+ */
+prdev(str, dev)
+char *str;
+dev_t dev;
+{
+
+       printf("%s on dev %u/%u\n", str, major(dev), minor(dev));
+}
+
+/*
+ * deverr prints a diagnostic from
+ * a device driver.
+ * It prints the device, block number,
+ * and an octal word (usually some error
+ * status register) passed as argument.
+ */
+deverror(bp, o1, o2)
+register struct buf *bp;
+{
+
+       prdev("err", bp->b_dev);
+       printf("bn=%d er=%x,%x\n", bp->b_blkno, o1,o2);
+}
diff --git a/usr/src/sys/sys/rdwri.c b/usr/src/sys/sys/rdwri.c
new file mode 100644 (file)
index 0000000..6c6deee
--- /dev/null
@@ -0,0 +1,194 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/inode.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+
+/*
+ * Read the file corresponding to
+ * the inode pointed at by the argument.
+ * The actual read arguments are found
+ * in the variables:
+ *     u_base          core address for destination
+ *     u_offset        byte offset in file
+ *     u_count         number of bytes to read
+ *     u_segflg        read to kernel/user/user I
+ */
+readi(ip)
+register struct inode *ip;
+{
+       struct buf *bp;
+       dev_t dev;
+       daddr_t lbn, bn;
+       off_t diff;
+       register on, n;
+       register type;
+       extern int mem_no;
+
+       if(u.u_count == 0)
+               return;
+       dev = (dev_t)ip->i_un.i_rdev;
+       if(u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)) ) {
+               u.u_error = EINVAL;
+               return;
+       }
+       ip->i_flag |= IACC;
+       type = ip->i_mode&IFMT;
+       if (type==IFCHR || type==IFMPC) {
+               return((*cdevsw[major(dev)].d_read)(dev));
+       }
+
+       do {
+               lbn = bn = u.u_offset >> BSHIFT;
+               on = u.u_offset & BMASK;
+               n = min((unsigned)(BSIZE-on), u.u_count);
+               if (type!=IFBLK && type!=IFMPB) {
+                       diff = ip->i_size - u.u_offset;
+                       if(diff <= 0)
+                               return;
+                       if(diff < n)
+                               n = diff;
+                       bn = bmap(ip, bn, B_READ);
+                       if(u.u_error)
+                               return;
+                       dev = ip->i_dev;
+               } else
+                       rablock = bn+1;
+               if ((long)bn<0) {
+                       bp = geteblk();
+                       clrbuf(bp);
+               } else if (ip->i_un.i_lastr+1==lbn)
+                       bp = breada(dev, bn, rablock);
+               else
+                       bp = bread(dev, bn);
+               ip->i_un.i_lastr = lbn;
+               n = min((unsigned)n, BSIZE-bp->b_resid);
+               if (n!=0)
+                       iomove(bp->b_un.b_addr+on, n, B_READ);
+               brelse(bp);
+       } while(u.u_error==0 && u.u_count!=0 && n>0);
+}
+
+/*
+ * Write the file corresponding to
+ * the inode pointed at by the argument.
+ * The actual write arguments are found
+ * in the variables:
+ *     u_base          core address for source
+ *     u_offset        byte offset in file
+ *     u_count         number of bytes to write
+ *     u_segflg        write to kernel/user/user I
+ */
+writei(ip)
+register struct inode *ip;
+{
+       struct buf *bp;
+       dev_t dev;
+       daddr_t bn;
+       register n, on;
+       register type;
+       extern int mem_no;
+
+       dev = (dev_t)ip->i_un.i_rdev;
+       if(u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)) ) {
+               u.u_error = EINVAL;
+               return;
+       }
+       type = ip->i_mode&IFMT;
+       if (type==IFCHR || type==IFMPC) {
+               ip->i_flag |= IUPD|ICHG;
+               (*cdevsw[major(dev)].d_write)(dev);
+               return;
+       }
+       if (u.u_count == 0)
+               return;
+
+       do {
+               bn = u.u_offset >> BSHIFT;
+               on = u.u_offset & BMASK;
+               n = min((unsigned)(BSIZE-on), u.u_count);
+               if (type!=IFBLK && type!=IFMPB) {
+                       bn = bmap(ip, bn, B_WRITE);
+                       if((long)bn<0)
+                               return;
+                       dev = ip->i_dev;
+               }
+               if(n == BSIZE) 
+                       bp = getblk(dev, bn);
+               else
+                       bp = bread(dev, bn);
+               iomove(bp->b_un.b_addr+on, n, B_WRITE);
+               if(u.u_error != 0)
+                       brelse(bp);
+               else
+                       bdwrite(bp);
+               if(u.u_offset > ip->i_size &&
+                  (type==IFDIR || type==IFREG))
+                       ip->i_size = u.u_offset;
+               ip->i_flag |= IUPD|ICHG;
+       } while(u.u_error==0 && u.u_count!=0);
+}
+
+/*
+ * Return the logical maximum
+ * of the 2 arguments.
+ */
+max(a, b)
+unsigned a, b;
+{
+
+       if(a > b)
+               return(a);
+       return(b);
+}
+
+/*
+ * Return the logical minimum
+ * of the 2 arguments.
+ */
+min(a, b)
+unsigned a, b;
+{
+
+       if(a < b)
+               return(a);
+       return(b);
+}
+
+/*
+ * Move n bytes at byte location
+ * &bp->b_un.b_addr[o] to/from (flag) the
+ * user/kernel (u.segflg) area starting at u.base.
+ * Update all the arguments by the number
+ * of bytes moved.
+ */
+iomove(cp, n, flag)
+register caddr_t cp;
+register n;
+{
+       register t;
+
+       if (n==0)
+               return;
+       if(u.u_segflg != 1)  {
+               if (flag==B_WRITE)
+                       t = copyin(u.u_base, (caddr_t)cp, n);
+               else
+                       t = copyout((caddr_t)cp, u.u_base, n);
+               if (t) {
+                       u.u_error = EFAULT;
+                       return;
+               }
+       }
+       else
+               if (flag == B_WRITE)
+                       bcopy(u.u_base,(caddr_t)cp,n);
+               else
+                       bcopy((caddr_t)cp,u.u_base,n);
+       u.u_base += n;
+       u.u_offset += n;
+       u.u_count -= n;
+       return;
+}
diff --git a/usr/src/sys/sys/subr.c b/usr/src/sys/sys/subr.c
new file mode 100644 (file)
index 0000000..23958ba
--- /dev/null
@@ -0,0 +1,188 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/conf.h"
+#include "../h/inode.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/buf.h"
+
+/*
+ * Bmap defines the structure of file system storage
+ * by returning the physical block number on a device given the
+ * inode and the logical block number in a file.
+ * When convenient, it also leaves the physical
+ * block number of the next block of the file in rablock
+ * for use in read-ahead.
+ */
+daddr_t
+bmap(ip, bn, rwflg)
+register struct inode *ip;
+daddr_t bn;
+{
+       register i;
+       struct buf *bp, *nbp;
+       int j, sh;
+       daddr_t nb, *bap;
+       dev_t dev;
+
+       if(bn < 0) {
+               u.u_error = EFBIG;
+               return((daddr_t)0);
+       }
+       dev = ip->i_dev;
+       rablock = 0;
+
+       /*
+        * blocks 0..NADDR-4 are direct blocks
+        */
+       if(bn < NADDR-3) {
+               i = bn;
+               nb = ip->i_un.i_addr[i];
+               if(nb == 0) {
+                       if(rwflg==B_READ || (bp = alloc(dev))==NULL)
+                               return((daddr_t)-1);
+                       nb = bp->b_blkno;
+                       bdwrite(bp);
+                       ip->i_un.i_addr[i] = nb;
+                       ip->i_flag |= IUPD|ICHG;
+               }
+               if(i < NADDR-4)
+                       rablock = ip->i_un.i_addr[i+1];
+               return(nb);
+       }
+
+       /*
+        * addresses NADDR-3, NADDR-2, and NADDR-1
+        * have single, double, triple indirect blocks.
+        * the first step is to determine
+        * how many levels of indirection.
+        */
+       sh = 0;
+       nb = 1;
+       bn -= NADDR-3;
+       for(j=3; j>0; j--) {
+               sh += NSHIFT;
+               nb <<= NSHIFT;
+               if(bn < nb)
+                       break;
+               bn -= nb;
+       }
+       if(j == 0) {
+               u.u_error = EFBIG;
+               return((daddr_t)0);
+       }
+
+       /*
+        * fetch the address from the inode
+        */
+       nb = ip->i_un.i_addr[NADDR-j];
+       if(nb == 0) {
+               if(rwflg==B_READ || (bp = alloc(dev))==NULL)
+                       return((daddr_t)-1);
+               nb = bp->b_blkno;
+               bdwrite(bp);
+               ip->i_un.i_addr[NADDR-j] = nb;
+               ip->i_flag |= IUPD|ICHG;
+       }
+
+       /*
+        * fetch through the indirect blocks
+        */
+       for(; j<=3; j++) {
+               bp = bread(dev, nb);
+               if(bp->b_flags & B_ERROR) {
+                       brelse(bp);
+                       return((daddr_t)0);
+               }
+               bap = bp->b_un.b_daddr;
+               sh -= NSHIFT;
+               i = (bn>>sh) & NMASK;
+               nb = bap[i];
+               if(nb == 0) {
+                       if(rwflg==B_READ || (nbp = alloc(dev))==NULL) {
+                               brelse(bp);
+                               return((daddr_t)-1);
+                       }
+                       nb = nbp->b_blkno;
+                       bdwrite(nbp);
+                       bap[i] = nb;
+                       bdwrite(bp);
+               } else
+                       brelse(bp);
+       }
+
+       /*
+        * calculate read-ahead.
+        */
+       if(i < NINDIR-1)
+               rablock = bap[i+1];
+       return(nb);
+}
+
+/*
+ * Pass back  c  to the user at his location u_base;
+ * update u_base, u_count, and u_offset.  Return -1
+ * on the last character of the user's read.
+ * u_base is in the user address space unless u_segflg is set.
+ */
+passc(c)
+register c;
+{
+       register id;
+
+       if((id = u.u_segflg) == 1)
+               *u.u_base = c;
+       else
+               if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
+                       u.u_error = EFAULT;
+                       return(-1);
+               }
+       u.u_count--;
+       u.u_offset++;
+       u.u_base++;
+       return(u.u_count == 0? -1: 0);
+}
+
+/*
+ * Pick up and return the next character from the user's
+ * write call at location u_base;
+ * update u_base, u_count, and u_offset.  Return -1
+ * when u_count is exhausted.  u_base is in the user's
+ * address space unless u_segflg is set.
+ */
+cpass()
+{
+       register c, id;
+
+       if(u.u_count == 0)
+               return(-1);
+       if((id = u.u_segflg) == 1)
+               c = *u.u_base;
+       else
+               if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
+                       u.u_error = EFAULT;
+                       return(-1);
+               }
+       u.u_count--;
+       u.u_offset++;
+       u.u_base++;
+       return(c&0377);
+}
+
+/*
+ * Routine which sets a user error; placed in
+ * illegal entries in the bdevsw and cdevsw tables.
+ */
+nodev()
+{
+
+       u.u_error = ENODEV;
+}
+
+/*
+ * Null routine; placed in insignificant entries
+ * in the bdevsw and cdevsw tables.
+ */
+nulldev()
+{
+}
diff --git a/usr/src/sys/sys/sys2.c b/usr/src/sys/sys/sys2.c
new file mode 100644 (file)
index 0000000..01e14c1
--- /dev/null
@@ -0,0 +1,317 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/reg.h"
+#include "../h/file.h"
+#include "../h/inode.h"
+
+/*
+ * read system call
+ */
+read()
+{
+       rdwr(FREAD);
+}
+
+/*
+ * write system call
+ */
+write()
+{
+       rdwr(FWRITE);
+}
+
+/*
+ * common code for read and write calls:
+ * check permissions, set base, count, and offset,
+ * and switch out to readi, writei, or pipe code.
+ */
+rdwr(mode)
+register mode;
+{
+       register struct file *fp;
+       register struct inode *ip;
+       register struct a {
+               int     fdes;
+               char    *cbuf;
+               unsigned count;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       fp = getf(uap->fdes);
+       if(fp == NULL)
+               return;
+       if((fp->f_flag&mode) == 0) {
+               u.u_error = EBADF;
+               return;
+       }
+       u.u_base = (caddr_t)uap->cbuf;
+       u.u_count = uap->count;
+       u.u_segflg = 0;
+       if((fp->f_flag&FPIPE) != 0) {
+               if(mode == FREAD)
+                       readp(fp);
+               else
+                       writep(fp);
+       } else {
+               ip = fp->f_inode;
+               if (fp->f_flag&FMP)
+                       u.u_offset = 0;
+               else
+                       u.u_offset = fp->f_un.f_offset;
+               if((ip->i_mode&(IFCHR&IFBLK)) == 0)
+                       plock(ip);
+               if(mode == FREAD)
+                       readi(ip);
+               else
+                       writei(ip);
+               if((ip->i_mode&(IFCHR&IFBLK)) == 0)
+                       prele(ip);
+               if ((fp->f_flag&FMP) == 0)
+                       fp->f_un.f_offset += uap->count-u.u_count;
+       }
+       u.u_r.r_val1 = uap->count-u.u_count;
+}
+
+/*
+ * open system call
+ */
+open()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     rwmode;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return;
+       open1(ip, ++uap->rwmode, 0);
+}
+
+/*
+ * creat system call
+ */
+creat()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     fmode;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       ip = namei(uchar, 1);
+       if(ip == NULL) {
+               if(u.u_error)
+                       return;
+               ip = maknode(uap->fmode&07777&(~ISVTX));
+               if (ip==NULL)
+                       return;
+               open1(ip, FWRITE, 2);
+       } else
+               open1(ip, FWRITE, 1);
+}
+
+/*
+ * common code for open and creat.
+ * Check permissions, allocate an open file structure,
+ * and call the device open routine if any.
+ */
+open1(ip, mode, trf)
+register struct inode *ip;
+register mode;
+{
+       register struct file *fp;
+       int i;
+
+       if(trf != 2) {
+               if(mode&FREAD)
+                       access(ip, IREAD);
+               if(mode&FWRITE) {
+                       access(ip, IWRITE);
+                       if((ip->i_mode&IFMT) == IFDIR)
+                               u.u_error = EISDIR;
+               }
+       }
+       if(u.u_error)
+               goto out;
+       if(trf == 1)
+               itrunc(ip);
+       prele(ip);
+       if ((fp = falloc()) == NULL)
+               goto out;
+       fp->f_flag = mode&(FREAD|FWRITE);
+       fp->f_inode = ip;
+       i = u.u_r.r_val1;
+       openi(ip, mode&FWRITE);
+       if(u.u_error == 0)
+               return;
+       u.u_ofile[i] = NULL;
+       fp->f_count--;
+
+out:
+       iput(ip);
+}
+
+/*
+ * close system call
+ */
+close()
+{
+       register struct file *fp;
+       register struct a {
+               int     fdes;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       fp = getf(uap->fdes);
+       if(fp == NULL)
+               return;
+       u.u_ofile[uap->fdes] = NULL;
+       closef(fp);
+}
+
+/*
+ * seek system call
+ */
+seek()
+{
+       register struct file *fp;
+       register struct a {
+               int     fdes;
+               off_t   off;
+               int     sbase;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       fp = getf(uap->fdes);
+       if(fp == NULL)
+               return;
+       if(fp->f_flag&(FPIPE|FMP)) {
+               u.u_error = ESPIPE;
+               return;
+       }
+       if(uap->sbase == 1)
+               uap->off += fp->f_un.f_offset;
+       else if(uap->sbase == 2)
+               uap->off += fp->f_inode->i_size;
+       fp->f_un.f_offset = uap->off;
+       u.u_r.r_off = uap->off;
+}
+
+
+/*
+ * link system call
+ */
+link()
+{
+       register struct inode *ip, *xp;
+       register struct a {
+               char    *target;
+               char    *linkname;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return;
+       if((ip->i_mode&IFMT)==IFDIR && !suser())
+               goto out;
+       /*
+        * Unlock to avoid possibly hanging the namei.
+        * Sadly, this means races. (Suppose someone
+        * deletes the file in the meantime?)
+        * Nor can it be locked again later
+        * because then there will be deadly
+        * embraces.
+        */
+       prele(ip);
+       u.u_dirp = (caddr_t)uap->linkname;
+       xp = namei(uchar, 1);
+       if(xp != NULL) {
+               u.u_error = EEXIST;
+               iput(xp);
+               goto out;
+       }
+       if (u.u_error)
+               goto out;
+       if(u.u_pdir->i_dev != ip->i_dev) {
+               iput(u.u_pdir);
+               u.u_error = EXDEV;
+               goto out;
+       }
+       wdir(ip);
+       if (u.u_error==0) {
+               ip->i_nlink++;
+               ip->i_flag |= ICHG;
+       }
+
+out:
+       iput(ip);
+}
+
+/*
+ * mknod system call
+ */
+mknod()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     fmode;
+               int     dev;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if(suser()) {
+               ip = namei(uchar, 1);
+               if(ip != NULL) {
+                       u.u_error = EEXIST;
+                       goto out;
+               }
+       }
+       if(u.u_error)
+               return;
+       ip = maknode(uap->fmode);
+       if (ip == NULL)
+               return;
+       ip->i_un.i_rdev = (dev_t)uap->dev;
+
+out:
+       iput(ip);
+}
+
+/*
+ * access system call
+ */
+saccess()
+{
+       register svuid, svgid;
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     fmode;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       svuid = u.u_uid;
+       svgid = u.u_gid;
+       u.u_uid = u.u_ruid;
+       u.u_gid = u.u_rgid;
+       ip = namei(uchar, 0);
+       if (ip != NULL) {
+               if (uap->fmode&(IREAD>>6))
+                       access(ip, IREAD);
+               if (uap->fmode&(IWRITE>>6))
+                       access(ip, IWRITE);
+               if (uap->fmode&(IEXEC>>6))
+                       access(ip, IEXEC);
+               iput(ip);
+       }
+       u.u_uid = svuid;
+       u.u_gid = svgid;
+}
diff --git a/usr/src/sys/sys/sys3.c b/usr/src/sys/sys/sys3.c
new file mode 100644 (file)
index 0000000..1523d25
--- /dev/null
@@ -0,0 +1,255 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * the fstat system call.
+ */
+fstat()
+{
+       register struct file *fp;
+       register struct a {
+               int     fdes;
+               struct stat *sb;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       fp = getf(uap->fdes);
+       if(fp == NULL)
+               return;
+       stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * the stat system call.
+ */
+stat()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               struct stat *sb;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return;
+       stat1(ip, uap->sb, (off_t)0);
+       iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+       register struct dinode *dp;
+       register struct buf *bp;
+       struct stat ds;
+
+       iupdat(ip, &time, &time);
+       /*
+        * first copy from inode table
+        */
+       ds.st_dev = ip->i_dev;
+       ds.st_ino = ip->i_number;
+       ds.st_mode = ip->i_mode;
+       ds.st_nlink = ip->i_nlink;
+       ds.st_uid = ip->i_uid;
+       ds.st_gid = ip->i_gid;
+       ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+       ds.st_size = ip->i_size - pipeadj;
+       /*
+        * next the dates in the disk
+        */
+       bp = bread(ip->i_dev, itod(ip->i_number));
+       dp = bp->b_un.b_dino;
+       dp += itoo(ip->i_number);
+       ds.st_atime = dp->di_atime;
+       ds.st_mtime = dp->di_mtime;
+       ds.st_ctime = dp->di_ctime;
+       brelse(bp);
+       if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+               u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+       register struct file *fp;
+       register struct a {
+               int     fdes;
+               int     fdes2;
+       } *uap;
+       register i, m;
+
+       uap = (struct a *)u.u_ap;
+       m = uap->fdes & ~077;
+       uap->fdes &= 077;
+       fp = getf(uap->fdes);
+       if(fp == NULL)
+               return;
+       if ((m&0100) == 0) {
+               if ((i = ufalloc()) < 0)
+                       return;
+       } else {
+               i = uap->fdes2;
+               if (i<0 || i>=NOFILE) {
+                       u.u_error = EBADF;
+                       return;
+               }
+               u.u_r.r_val1 = i;
+       }
+       if (i!=uap->fdes) {
+               if (u.u_ofile[i]!=NULL)
+                       closef(u.u_ofile[i]);
+               u.u_ofile[i] = fp;
+               fp->f_count++;
+       }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+       dev_t dev;
+       register struct inode *ip;
+       register struct mount *mp;
+       struct mount *smp;
+       register struct filsys *fp;
+       struct buf *bp;
+       register struct a {
+               char    *fspec;
+               char    *freg;
+               int     ronly;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       dev = getmdev();
+       if(u.u_error)
+               return;
+       u.u_dirp = (caddr_t)uap->freg;
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return;
+       if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+               goto out;
+       smp = NULL;
+       for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+               if(mp->m_bufp != NULL) {
+                       if(dev == mp->m_dev)
+                               goto out;
+               } else
+               if(smp == NULL)
+                       smp = mp;
+       }
+       mp = smp;
+       if(mp == NULL)
+               goto out;
+       (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+       if(u.u_error)
+               goto out;
+       bp = bread(dev, SUPERB);
+       if(u.u_error) {
+               brelse(bp);
+               goto out1;
+       }
+       mp->m_inodp = ip;
+       mp->m_dev = dev;
+       mp->m_bufp = geteblk();
+       bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+       fp = mp->m_bufp->b_un.b_filsys;
+       fp->s_ilock = 0;
+       fp->s_flock = 0;
+       fp->s_ronly = uap->ronly & 1;
+       brelse(bp);
+       ip->i_flag |= IMOUNT;
+       prele(ip);
+       return;
+
+out:
+       u.u_error = EBUSY;
+out1:
+       iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+       dev_t dev;
+       register struct inode *ip;
+       register struct mount *mp;
+       struct buf *bp;
+       register struct a {
+               char    *fspec;
+       };
+
+       dev = getmdev();
+       if(u.u_error)
+               return;
+       xumount(dev);   /* remove unused sticky files from text table */
+       update();
+       for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+               if(mp->m_bufp != NULL && dev == mp->m_dev)
+                       goto found;
+       u.u_error = EINVAL;
+       return;
+
+found:
+       for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+               if(ip->i_number != 0 && dev == ip->i_dev) {
+                       u.u_error = EBUSY;
+                       return;
+               }
+       (*bdevsw[major(dev)].d_close)(dev, 0);
+       ip = mp->m_inodp;
+       ip->i_flag &= ~IMOUNT;
+       plock(ip);
+       iput(ip);
+       bp = mp->m_bufp;
+       mp->m_bufp = NULL;
+       brelse(bp);
+}
+
+/*
+ * Common code for mount and umount.
+ * Check that the user's argument is a reasonable
+ * thing on which to mount, and return the device number if so.
+ */
+dev_t
+getmdev()
+{
+       dev_t dev;
+       register struct inode *ip;
+
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return(NODEV);
+       if((ip->i_mode&IFMT) != IFBLK)
+               u.u_error = ENOTBLK;
+       dev = (dev_t)ip->i_un.i_rdev;
+       if(major(dev) >= nblkdev)
+               u.u_error = ENXIO;
+       iput(ip);
+       return(dev);
+}
diff --git a/usr/src/sys/sys/sys4.c b/usr/src/sys/sys/sys4.c
new file mode 100644 (file)
index 0000000..cc61a78
--- /dev/null
@@ -0,0 +1,432 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/reg.h"
+#include "../h/inode.h"
+#include "../h/proc.h"
+#include "../h/clock.h"
+#include "../h/mtpr.h"
+#include "../h/timeb.h"
+
+/*
+ * Everything in this file is a routine implementing a system call.
+ */
+
+/*
+ * return the current time (old-style entry)
+ */
+gtime()
+{
+       u.u_r.r_time = time;
+}
+
+/*
+ * New time entry-- return TOD with milliseconds, timezone,
+ * DST flag
+ */
+ftime()
+{
+       register struct a {
+               struct  timeb   *tp;
+       } *uap;
+       struct timeb t;
+       register unsigned ms;
+
+       uap = (struct a *)u.u_ap;
+       spl7();
+       t.time = time;
+       ms = lbolt;
+       spl0();
+       if (ms > HZ) {
+               ms -= HZ;
+               t.time++;
+       }
+       t.millitm = (1000*ms)/HZ;
+       t.timezone = TIMEZONE;
+       t.dstflag = DSTFLAG;
+       if (copyout((caddr_t)&t, (caddr_t)uap->tp, sizeof(t)) < 0)
+               u.u_error = EFAULT;
+}
+
+/*
+ * Set the time
+ */
+stime()
+{
+       register unsigned int i , j ;
+       register struct a {
+               time_t  time;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if(suser()) {
+               time = uap->time;
+               /* In addition to setting software time (GMT seconds
+               *  since YRREF), also set VAX TODR reg (10 ms. clicks
+               *  into current year YRCURR
+               */
+               for (i = time , j = YRREF ; j < YRCURR ; j++)
+                       i -= (SECYR + (j%4?0:SECDAY)) ;
+               mtpr(TODR,i*100) ; /* 10 ms. clicks */
+       }
+}
+
+setuid()
+{
+       register uid;
+       register struct a {
+               int     uid;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       uid = uap->uid;
+       if(u.u_ruid == uid || suser()) {
+               u.u_uid = uid;
+               u.u_procp->p_uid = uid;
+               u.u_ruid = uid;
+       }
+}
+
+getuid()
+{
+
+       u.u_r.r_val1 = u.u_ruid;
+       u.u_r.r_val2 = u.u_uid;
+}
+
+setgid()
+{
+       register gid;
+       register struct a {
+               int     gid;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       gid = uap->gid;
+       if(u.u_rgid == gid || suser()) {
+               u.u_gid = gid;
+               u.u_rgid = gid;
+       }
+}
+
+getgid()
+{
+
+       u.u_r.r_val1 = u.u_rgid;
+       u.u_r.r_val2 = u.u_gid;
+}
+
+getpid()
+{
+       u.u_r.r_val1 = u.u_procp->p_pid;
+       u.u_r.r_val2 = u.u_procp->p_ppid;
+}
+
+sync()
+{
+
+       update();
+}
+
+nice()
+{
+       register n;
+       register struct a {
+               int     niceness;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       n = uap->niceness;
+       if(n < 0 && !suser())
+               n = 0;
+       n += u.u_procp->p_nice;
+       if(n >= 2*NZERO)
+               n = 2*NZERO -1;
+       if(n < 0)
+               n = 0;
+       u.u_procp->p_nice = n;
+}
+
+/*
+ * Unlink system call.
+ * Hard to avoid races here, especially
+ * in unlinking directories.
+ */
+unlink()
+{
+       register struct inode *ip, *pp;
+       struct a {
+               char    *fname;
+       };
+
+       pp = namei(uchar, 2);
+       if(pp == NULL)
+               return;
+       /*
+        * Check for unlink(".")
+        * to avoid hanging on the iget
+        */
+       if (pp->i_number == u.u_dent.d_ino) {
+               ip = pp;
+               ip->i_count++;
+       } else
+               ip = iget(pp->i_dev, u.u_dent.d_ino);
+       if(ip == NULL)
+               goto out1;
+       if((ip->i_mode&IFMT)==IFDIR && !suser())
+               goto out;
+       /*
+        * Don't unlink a mounted file.
+        */
+       if (ip->i_dev != pp->i_dev) {
+               u.u_error = EBUSY;
+               goto out;
+       }
+       if (ip->i_flag&ITEXT)
+               xrele(ip);      /* try once to free text */
+       if (ip->i_flag&ITEXT && ip->i_nlink==1) {
+               u.u_error = ETXTBSY;
+               goto out;
+       }
+       u.u_offset -= sizeof(struct direct);
+       u.u_base = (caddr_t)&u.u_dent;
+       u.u_count = sizeof(struct direct);
+       u.u_dent.d_ino = 0;
+       writei(pp);
+       ip->i_nlink--;
+       ip->i_flag |= ICHG;
+
+out:
+       iput(ip);
+out1:
+       iput(pp);
+}
+chdir()
+{
+       chdirec(&u.u_cdir);
+}
+
+chroot()
+{
+       chdirec(&u.u_rdir);
+}
+
+chdirec(ipp)
+register struct inode **ipp;
+{
+       register struct inode *ip;
+       struct a {
+               char    *fname;
+       };
+
+       ip = namei(uchar, 0);
+       if(ip == NULL)
+               return;
+       if((ip->i_mode&IFMT) != IFDIR) {
+               u.u_error = ENOTDIR;
+               goto bad;
+       }
+       if(access(ip, IEXEC))
+               goto bad;
+       prele(ip);
+       if (*ipp) {
+               plock(*ipp);
+               iput(*ipp);
+       }
+       *ipp = ip;
+       return;
+
+bad:
+       iput(ip);
+}
+
+chmod()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     fmode;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if ((ip = owner()) == NULL)
+               return;
+       ip->i_mode &= ~07777;
+       if (u.u_uid)
+               uap->fmode &= ~ISVTX;
+       ip->i_mode |= uap->fmode&07777;
+       ip->i_flag |= ICHG;
+       if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
+               xrele(ip);
+       iput(ip);
+}
+
+chown()
+{
+       register struct inode *ip;
+       register struct a {
+               char    *fname;
+               int     uid;
+               int     gid;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (!suser() || (ip = owner()) == NULL)
+               return;
+       ip->i_uid = uap->uid;
+       ip->i_gid = uap->gid;
+       ip->i_flag |= ICHG;
+       iput(ip);
+}
+
+ssig()
+{
+       register a;
+       struct a {
+               int     signo;
+               int     fun;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       a = uap->signo;
+       if(a<=0 || a>=NSIG || a==SIGKIL) {
+               u.u_error = EINVAL;
+               return;
+       }
+       u.u_r.r_val1 = u.u_signal[a];
+       u.u_signal[a] = uap->fun;
+       u.u_procp->p_sig &= ~(1<<(a-1));
+}
+
+kill()
+{
+       register struct proc *p, *q;
+       register a;
+       register struct a {
+               int     pid;
+               int     signo;
+       } *uap;
+       int f, priv;
+
+       uap = (struct a *)u.u_ap;
+       f = 0;
+       a = uap->pid;
+       priv = 0;
+       if (a==-1 && u.u_uid==0) {
+               priv++;
+               a = 0;
+       }
+       q = u.u_procp;
+       for(p = &proc[0]; p < &proc[NPROC]; p++) {
+               if(p->p_stat == NULL)
+                       continue;
+               if(a != 0 && p->p_pid != a)
+                       continue;
+               if(a==0 && ((p->p_pgrp!=q->p_pgrp&&priv==0) || p<=&proc[1]))
+                       continue;
+               if(u.u_uid != 0 && u.u_uid != p->p_uid)
+                       continue;
+               f++;
+               psignal(p, uap->signo);
+       }
+       if(f == 0)
+               u.u_error = ESRCH;
+}
+
+times()
+{
+       register struct a {
+               time_t  (*times)[4];
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (copyout((caddr_t)&u.u_utime, (caddr_t)uap->times, sizeof(*uap->times)) < 0)
+               u.u_error = EFAULT;
+}
+
+profil()
+{
+       register struct a {
+               short   *bufbase;
+               unsigned bufsize;
+               unsigned pcoffset;
+               unsigned pcscale;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       u.u_prof.pr_base = uap->bufbase;
+       u.u_prof.pr_size = uap->bufsize;
+       u.u_prof.pr_off = uap->pcoffset;
+       u.u_prof.pr_scale = uap->pcscale;
+}
+
+/*
+ * alarm clock signal
+ */
+alarm()
+{
+       register struct proc *p;
+       register c;
+       register struct a {
+               int     deltat;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       p = u.u_procp;
+       c = p->p_clktim;
+       p->p_clktim = uap->deltat;
+       u.u_r.r_val1 = c;
+}
+
+/*
+ * indefinite wait.
+ * no one should wakeup(&u)
+ */
+pause()
+{
+
+       for(;;)
+               sleep((caddr_t)&u, PSLEP);
+}
+
+/*
+ * mode mask for creation of files
+ */
+umask()
+{
+       register struct a {
+               int     mask;
+       } *uap;
+       register t;
+
+       uap = (struct a *)u.u_ap;
+       t = u.u_cmask;
+       u.u_cmask = uap->mask & 0777;
+       u.u_r.r_val1 = t;
+}
+
+/*
+ * Set IUPD and IACC times on file.
+ * Can't set ICHG.
+ */
+utime()
+{
+       register struct a {
+               char    *fname;
+               time_t  *tptr;
+       } *uap;
+       register struct inode *ip;
+       time_t tv[2];
+
+       uap = (struct a *)u.u_ap;
+       if ((ip = owner()) == NULL)
+               return;
+       if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
+               u.u_error = EFAULT;
+               return;
+       }
+       ip->i_flag |= IACC|IUPD|ICHG;
+       iupdat(ip, &tv[0], &tv[1]);
+       iput(ip);
+}
diff --git a/usr/src/sys/sys/sysent.c b/usr/src/sys/sys/sysent.c
new file mode 100644 (file)
index 0000000..b62ca3f
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * This table is the switch used to transfer
+ * to the appropriate routine for processing a system call.
+ * Each row contains the number of arguments expected
+ * and a pointer to the routine.
+ */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+
+int    alarm();
+int    chdir();
+int    chmod();
+int    chown();
+int    chroot();
+int    close();
+int    creat();
+int    dup();
+int    exec();
+int    exece();
+int    fork();
+int    fstat();
+int    getgid();
+int    getpid();
+int    getuid();
+int    gtime();
+int    gtty();
+int    ioctl();
+int    kill();
+int    link();
+int    mknod();
+int    mpxchan();
+int    nice();
+int    ftime();
+int    nosys();
+int    nullsys();
+int    open();
+int    pause();
+int    pipe();
+int    profil();
+int    ptrace();
+int    read();
+int    rexit();
+int    saccess();
+int    sbreak();
+int    seek();
+int    setgid();
+int    setuid();
+int    smount();
+int    ssig();
+int    stat();
+int    stime();
+int    stty();
+int    sumount();
+int    sync();
+int    sysacct();
+int    syslock();
+int    sysphys();
+int    times();
+int    umask();
+int    unlink();
+int    utime();
+int    wait();
+int    write();
+
+struct sysent sysent[64] =
+{
+       0, 0, nosys,                    /* 0 = indir */
+       1, 0, rexit,                    /*  1 = exit */
+       0, 0, fork,                     /*  2 = fork */
+       3, 0, read,                     /*  3 = read */
+       3, 0, write,                    /*  4 = write */
+       2, 0, open,                     /*  5 = open */
+       1, 0, close,                    /*  6 = close */
+       0, 0, wait,                     /*  7 = wait */
+       2, 0, creat,                    /*  8 = creat */
+       2, 0, link,                     /*  9 = link */
+       1, 0, unlink,                   /* 10 = unlink */
+       2, 0, exec,                     /* 11 = exec */
+       1, 0, chdir,                    /* 12 = chdir */
+       0, 0, gtime,                    /* 13 = time */
+       3, 0, mknod,                    /* 14 = mknod */
+       2, 0, chmod,                    /* 15 = chmod */
+       3, 0, chown,                    /* 16 = chown; now 3 args */
+       1, 0, sbreak,                   /* 17 = break */
+       2, 0, stat,                     /* 18 = stat */
+       3, 0, seek,                     /* 19 = seek */
+       0, 0, getpid,                   /* 20 = getpid */
+       3, 0, smount,                   /* 21 = mount */
+       1, 0, sumount,                  /* 22 = umount */
+       1, 0, setuid,                   /* 23 = setuid */
+       0, 0, getuid,                   /* 24 = getuid */
+       1, 0, stime,                    /* 25 = stime */
+       4, 0, ptrace,                   /* 26 = ptrace */
+       1, 0, alarm,                    /* 27 = alarm */
+       2, 0, fstat,                    /* 28 = fstat */
+       0, 0, pause,                    /* 29 = pause */
+       2, 0, utime,                    /* 30 = utime */
+       2, 0, stty,                     /* 31 = stty */
+       2, 0, gtty,                     /* 32 = gtty */
+       2, 0, saccess,                  /* 33 = access */
+       1, 0, nice,                     /* 34 = nice */
+       1, 0, ftime,                    /* 35 = ftime; formally sleep;  */
+       0, 0, sync,                     /* 36 = sync */
+       2, 0, kill,                     /* 37 = kill */
+       0, 0, nullsys,                  /* 38 = switch; inoperative */
+       0, 0, nullsys,                  /* 39 = setpgrp (not in yet) */
+       0, 0, nosys,                    /* 40 = tell - obsolete */
+       2, 0, dup,                              /* 41 = dup */
+       0, 0, pipe,                     /* 42 = pipe */
+       1, 0, times,                    /* 43 = times */
+       4, 0, profil,                   /* 44 = prof */
+       0, 0, nosys,                    /* 45 = tiu */
+       1, 0, setgid,                   /* 46 = setgid */
+       0, 0, getgid,                   /* 47 = getgid */
+       2, 0, ssig,                     /* 48 = sig */
+       0, 0, nosys,                    /* 49 = reserved for USG */
+       0, 0, nosys,                    /* 50 = reserved for USG */
+       1, 0, sysacct,                  /* 51 = turn acct off/on */
+       3, 0, sysphys,                  /* 52 = set user physical addresses */
+       1, 0, syslock,                  /* 53 = lock user in core */
+       3, 0, ioctl,                    /* 54 = ioctl */
+       0, 0, nosys,                    /* 55 = reboot */
+       4, 0, mpxchan,                  /* 56 = creat mpx comm channel */
+       0, 0, nosys,                    /* 57 = reserved for USG */
+       0, 0, nosys,                    /* 58 = reserved for USG */
+       3, 0, exece,                    /* 59 = exece */
+       1, 0, umask,                    /* 60 = umask */
+       1, 0, chroot,                   /* 61 = chroot */
+       1, 0, nosys,            /* 62 = unused */
+       0, 0, nosys                     /* 63 = used internally */
+};
diff --git a/usr/src/sys/sys/tdump.c b/usr/src/sys/sys/tdump.c
new file mode 100644 (file)
index 0000000..2bf0330
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Dump core to magtape
+ * Assumes memory mapping has been disabled
+ * and IPL has be set high ( > 0x15 )
+ */
+
+
+#define PHYSPAGES 1024
+#define UBA 0x20006000
+#define mba0 0x20010000
+#define mba1 0x20012000
+
+struct mba_regs {
+       int mba_csr,
+           mba_cr,
+           mba_sr,
+           mba_var,
+           mba_bcr;
+};
+
+struct device
+{
+       int     htcs1;
+       int     htds;
+       int     hter;
+       int     htmr;
+       int     htas;
+       int     htfc;
+       int     htdt;
+       int     htck;
+       int     htsn;
+       int     httc;
+};
+
+#define        HTADDR  ((struct device *)(mba1 + 0x400))
+#define HTMAP ((int *) (mba1 + 0x800))
+
+#define        GO      01
+#define        WCOM    060
+#define        RCOM    070
+#define        NOP     0
+#define        WEOF    026
+#define        SFORW   030
+#define        SREV    032
+#define        ERASE   024
+#define        REW     06
+#define        DCLR    010
+#define P800   01300           /* 800 + pdp11 mode */
+#define        P1600   02300           /* 1600 + pdp11 mode */
+#define        IENABLE 0100
+#define        RDY     0200
+#define        TM      04
+#define        DRY     0200
+#define EOT    02000
+#define CS     02000
+#define COR    0100000
+#define PES    040
+#define WRL    04000
+#define MOL    010000
+#define ERR    040000
+#define FCE    01000
+#define        TRE     040000
+#define HARD   064023  /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */
+
+#define        SIO     1
+#define        SSFOR   2
+#define        SSREV   3
+#define SRETRY 4
+#define SCOM   5
+#define SOK    6
+
+dump()
+{
+
+       HTADDR->httc = P800;    /* set 800 bpi mode */
+
+       twall((char *)0, PHYSPAGES);    /* write out memory */
+
+       teof();
+       teof();
+       rewind();
+       twait();
+}
+
+twall(start, num)
+       char *start;
+       int num;
+{
+       HTADDR->htcs1 = DCLR | GO;
+       while (num--) {
+               twrite(start);
+               start += 512;
+               }
+}
+
+twrite(buf)
+char *buf;
+{
+
+       twait();
+       HTADDR->htfc = -512;
+       *HTMAP = (((int)buf)>>9) | 0x80000000;  /* map entry */
+       ((struct mba_regs *)mba1)->mba_sr = -1;
+       ((struct mba_regs *)mba1)->mba_bcr = -512;
+       ((struct mba_regs *)mba1)->mba_var = 0;
+       HTADDR->htcs1 = WCOM | GO;
+       return;
+}
+
+twait()
+{
+       register s;
+
+       do
+               s = HTADDR->htds;
+       while ((s & RDY) == 0);
+}
+
+rewind()
+{
+       twait();
+       HTADDR->htcs1 = REW | GO;
+}
+
+teof()
+{
+       twait();
+       HTADDR->htcs1 = WEOF | GO;
+}
diff --git a/usr/src/sys/sys/uba.c b/usr/src/sys/sys/uba.c
new file mode 100644 (file)
index 0000000..e93e39a
--- /dev/null
@@ -0,0 +1,107 @@
+# include "../h/param.h"
+#include "../h/uba.h"
+# include "../h/map.h"
+int uballoc(baddr,bcnt,bdpflg)
+char  bdpflg ;
+char * baddr ;
+unsigned short bcnt;
+{
+/*
+*  Allocate as many contiguous UBA mapping registers
+*  as are necessary to do transfer of 'bcnt' bytes
+*  to/from location 'baddr'.
+*  Wait for enough map registers.
+*  'bdpflg' is non-zero if a "buffered data path" (BDP) is
+*  to be used, else 0 -> use direct data path (DDP) .
+*  Return
+*
+*    |31 - - 28|27 - - 18|17 - - - 9|8 - - 0|
+*    |         |         |          |       |
+*    |  BDP    |   no.   |  start   | byte  |
+*    |   no.   | mapping |   map    | offset|
+*    |         |  reg's  | reg. no. |       |
+*    |         |         |          |       |
+*
+*/
+register regnum , nmreg , bdp , pfn , j ;
+/* calculate no. of mapping reg's required */
+nmreg = btoc(bcnt) + 2;
+pfn = ((int)baddr>>9) & 0xfff ; /* start page frame no. */
+spl6() ;
+while ((regnum = malloc(ubamap,nmreg) - 1) < 0) {
+       /* wait for no. of mapping reg's requested */
+       umrwant++ ;
+       sleep(ubamap,PSWP) ;
+       }
+if (bdpflg)  /* buffered data path BDP 1-15 */
+       while ( (bdp=malloc(bdpmap,1)) == NULL)
+               {
+               bdpwant++;
+               sleep(bdpmap, PSWP);
+               }
+else { /* BDP 0 = DDP */
+       bdp = 0 ;
+       }
+spl0() ;
+j = (bdp<<28) | (nmreg<<18) | (regnum<<9) | ((int)baddr & 0x01ff) ;
+pfn |= (MRV | (bdp<<21)) ; /* map reg entry */
+if (bdp && ((int)baddr & 01)) pfn |= BO ; /* byte offset */
+while (--nmreg)  /* fill the memory mapping reg's */
+       ((struct uba_regs *)UBA0)->uba_map[regnum++] = pfn++ ;
+((struct uba_regs *)UBA0)->uba_map[regnum] = 0 ; /* last entry is invalid */
+return(j) ;
+}
+/*                                                     */
+ubafree(mr)
+int mr ;
+{
+/*
+*  Free UBA memory mapping reg's and a BDP no..
+*    mr :
+*              bits 0 - 3 :  bdp no.
+*               4 - 15 : start map reg. no.
+*                      16 - 31 : no. of mapping reg's
+*
+*/
+register bdp , nmreg , regnum ;
+spl6();
+bdp = (mr>>28) & 0x0f ;  /* BDP no. */
+if (bdp)
+       {
+       ((struct uba_regs *)UBA0)->uba_dpr[bdp] |= BNE ; /* purge */
+       mfree(bdpmap, 1, bdp);
+       if (bdpwant) {
+               bdpwant = 0;
+               wakeup(bdpmap);
+       }
+}
+
+nmreg = (mr>>18) & 0x3ff ; /* no. of mapping reg's */
+regnum = (mr>>9) & 0x1ff ; /* 1st map reg. no. */
+/* free mapping reg's */
+mfree(ubamap,nmreg,regnum+1) ;
+if (umrwant) {
+       umrwant = 0;
+       wakeup(ubamap);
+}
+spl0() ;
+}
+
+ubainit()
+{
+       mfree(ubamap, 496, 1);
+       mfree(bdpmap, 15, 1);
+}