From: Tom London Date: Tue, 23 Jan 1979 10:42:14 +0000 (-0500) Subject: Bell 32V development X-Git-Tag: Bell-32V~300 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/848f4c12b3277ae906662c0c3cf5ab31d78f6f61 Bell 32V development 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 Synthesized-from: 32v --- diff --git a/usr/src/sys/sys/acct.c b/usr/src/sys/sys/acct.c new file mode 100644 index 0000000000..ec3f04f93a --- /dev/null +++ b/usr/src/sys/sys/acct.c @@ -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; ii_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 index 0000000000..e3b1818ea4 --- /dev/null +++ b/usr/src/sys/sys/alloc.c @@ -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; ii_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; idi_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 index 0000000000..014870d1ad --- /dev/null +++ b/usr/src/sys/sys/clock.c @@ -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_statp_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 index 0000000000..7cd7a7da77 --- /dev/null +++ b/usr/src/sys/sys/dkleave.c @@ -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 index 0000000000..5a90c1eac9 --- /dev/null +++ b/usr/src/sys/sys/dsort.c @@ -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 index 0000000000..09ae774d86 --- /dev/null +++ b/usr/src/sys/sys/iget.c @@ -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; ii_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; ii_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 index 0000000000..27a9ee8966 --- /dev/null +++ b/usr/src/sys/sys/main.c @@ -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; ii_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; ib_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 index 0000000000..f3c973cd1e --- /dev/null +++ b/usr/src/sys/sys/mba.c @@ -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; ib_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 index 0000000000..44628c43ca --- /dev/null +++ b/usr/src/sys/sys/partab.c @@ -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 index 0000000000..1ca26baa9a --- /dev/null +++ b/usr/src/sys/sys/pipe.c @@ -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 index 0000000000..842897dae5 --- /dev/null +++ b/usr/src/sys/sys/prf.c @@ -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 index 0000000000..6c6deee9ff --- /dev/null +++ b/usr/src/sys/sys/rdwri.c @@ -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 index 0000000000..23958badea --- /dev/null +++ b/usr/src/sys/sys/subr.c @@ -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 index 0000000000..01e14c166a --- /dev/null +++ b/usr/src/sys/sys/sys2.c @@ -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 index 0000000000..1523d2565e --- /dev/null +++ b/usr/src/sys/sys/sys3.c @@ -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 index 0000000000..cc61a784d5 --- /dev/null +++ b/usr/src/sys/sys/sys4.c @@ -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 index 0000000000..b62ca3fe40 --- /dev/null +++ b/usr/src/sys/sys/sysent.c @@ -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 index 0000000000..2bf03303e8 --- /dev/null +++ b/usr/src/sys/sys/tdump.c @@ -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 index 0000000000..e93e39a91f --- /dev/null +++ b/usr/src/sys/sys/uba.c @@ -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); +}