BSD 4 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 09:55:57 +0000 (01:55 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 09:55:57 +0000 (01:55 -0800)
Work on file usr/src/sys/dev/dhfdm.c
Work on file usr/src/sys/dev/dkleave.c
Work on file usr/src/sys/dev/dsort.c
Work on file usr/src/sys/dev/flp.c
Work on file usr/src/sys/dev/mx1.c
Work on file usr/src/sys/dev/tdump.c
Work on file usr/src/sys/dev/va.c
Work on file usr/src/sys/dev/vp.c
Work on file usr/src/sys/dev/mem.c
Work on file usr/src/sys/dev/hp.c
Work on file usr/src/sys/dev/ttyold.c

Synthesized-from: CSRG//cd1/4.0

usr/src/sys/dev/dhfdm.c [new file with mode: 0644]
usr/src/sys/dev/dkleave.c [new file with mode: 0644]
usr/src/sys/dev/dsort.c [new file with mode: 0644]
usr/src/sys/dev/flp.c [new file with mode: 0644]
usr/src/sys/dev/hp.c [new file with mode: 0644]
usr/src/sys/dev/mem.c [new file with mode: 0644]
usr/src/sys/dev/mx1.c [new file with mode: 0644]
usr/src/sys/dev/tdump.c [new file with mode: 0644]
usr/src/sys/dev/ttyold.c [new file with mode: 0644]
usr/src/sys/dev/va.c [new file with mode: 0644]
usr/src/sys/dev/vp.c [new file with mode: 0644]

diff --git a/usr/src/sys/dev/dhfdm.c b/usr/src/sys/dev/dhfdm.c
new file mode 100644 (file)
index 0000000..e55acf6
--- /dev/null
@@ -0,0 +1,28 @@
+/*     dhfdm.c 4.1     11/9/80 */
+
+#include "../conf/dh.h"
+#if NDH11 > 0
+/*
+ * DM-BB fake driver
+ */
+#include "../h/param.h"
+#include "../h/tty.h"
+#include "../h/conf.h"
+
+struct tty     dh11[];
+
+/*ARGSUSED*/
+dmopen(dev)
+{
+       register struct tty *tp;
+
+       tp = &dh11[minor(dev)];
+       tp->t_state |= CARR_ON;
+}
+
+/*ARGSUSED*/
+dmctl(dev, bits, how)
+{
+
+}
+#endif
diff --git a/usr/src/sys/dev/dkleave.c b/usr/src/sys/dev/dkleave.c
new file mode 100644 (file)
index 0000000..45c5343
--- /dev/null
@@ -0,0 +1,33 @@
+/*     dkleave.c       4.1     11/9/80 */
+
+#ifdef INTRLVE
+#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);
+}
+#endif
diff --git a/usr/src/sys/dev/dsort.c b/usr/src/sys/dev/dsort.c
new file mode 100644 (file)
index 0000000..ec0fabd
--- /dev/null
@@ -0,0 +1,45 @@
+/*     dsort.c 4.1     11/9/80 */
+
+/*
+ * 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/dev/flp.c b/usr/src/sys/dev/flp.c
new file mode 100644 (file)
index 0000000..5939283
--- /dev/null
@@ -0,0 +1,258 @@
+/*     flp.c   4.1     11/9/80 */
+
+#include "../h/flp.h"
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/conf.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/mtpr.h"
+#include "../h/buf.h"
+#include "../h/cons.h"
+
+struct {
+       short   fl_state;               /* open and busy flags */
+       short   fl_active;              /* driver state flag */
+       struct  buf *fl_buf;            /* buffer we're using */
+       unsigned char *fl_xaddr;        /* transfer address */
+       short   fl_errcnt;
+} fltab;
+
+/*ARGSUSED*/
+flopen(dev, flag)
+       dev_t dev;
+       int flag;
+{
+       struct buf *geteblk();
+
+       if (fltab.fl_state != 0) {
+               u.u_error = ENXIO;
+               return;
+       }
+       fltab.fl_state = FL_OPEN;
+       fltab.fl_buf = geteblk();
+       fltab.fl_active = FL_IDLE;
+}
+
+/*ARGSUSED*/
+flclose(dev, flag)
+       dev_t dev;
+       int flag;
+{
+
+       brelse(fltab.fl_buf);
+       fltab.fl_state = 0;
+}
+
+flstrategy(rw)
+       int rw;
+{
+       register struct buf *bp;
+       register unsigned i;
+
+       /*
+        * Assume one block read/written for each call - 
+        * and enforce this by checking for block size of 128.
+        * Use the b_blkno field to address
+        * physical, 128-byte blocks (u.u_offset/128).
+        * This is checked for validity, and is further interpreted as:
+        *
+        *      track# * (sectors/track) + sector #
+        */
+       if (u.u_count == 0) 
+               return;
+       (void) spl4();
+       while (fltab.fl_state & FL_BUSY)
+               sleep((caddr_t)&fltab, PRIBIO);
+       fltab.fl_state |= FL_BUSY;
+       (void) spl0();
+
+       bp = fltab.fl_buf;
+       while ((i = min(RXBYSEC, u.u_count)) != 0) {
+               bp->b_blkno = u.u_offset>>7;
+               if (bp->b_blkno >= MAXSEC || (u.u_offset & 0177) != 0) {
+                       /* block number out of range */
+                       /* or offset in middle of block */
+                       u.u_error = ENXIO;
+                       break;  
+               }
+               if (rw == B_WRITE) {
+                       iomove(bp->b_un.b_addr, i, B_WRITE);
+                       if (u.u_error != 0)
+                               break;
+               }
+               bp->b_flags = rw;
+               (void) spl4(); 
+               flstart();
+               while ((bp->b_flags & B_DONE) == 0)
+                       sleep((caddr_t)bp, PRIBIO);     
+               (void) spl0();
+               if (bp->b_flags & B_ERROR) {
+                       u.u_error = EIO;
+                       break;
+               }
+               if (rw == B_READ) {
+                       iomove(bp->b_un.b_addr, i, B_READ);
+                       if (u.u_error != 0)
+                               break;
+               }
+       }
+       u.u_count = bp->b_resid;
+       fltab.fl_state &= ~FL_BUSY;
+       wakeup((caddr_t)&fltab);
+}
+
+/*ARGSUSED*/
+flread(dev)
+       dev_t dev;
+{
+
+       flstrategy(B_READ);
+}
+
+/*ARGSUSED*/
+flwrite(dev)
+       dev_t dev;
+{
+
+       flstrategy(B_WRITE);
+}
+
+flstart()
+{
+       register struct buf *bp;
+
+       bp = fltab.fl_buf;
+       fltab.fl_active = FL_MAND;
+       fltab.fl_errcnt = 0;
+       fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
+       bp->b_resid = 0;
+       bp->b_bcount = RXBYSEC; /* always transfer a full sector */
+
+       if ((mfpr(TXCS) & TXCS_RDY) == 0)
+               /* not ready to receive order */
+               return;
+       /*
+        * Wake up floppy LSI software with command
+        */
+       fltab.fl_active = FL_SEC;
+       if ((bp->b_flags&B_READ) == B_READ)
+               mtpr(TXDB, FL_RS);
+       else
+               mtpr(TXDB, FL_WS);
+}
+
+/*
+ * See if we want to transmit something
+ * to the floppy - and do it
+ */
+conxfl()
+{
+       register int databyte;
+       register struct buf *bp;
+
+       bp = fltab.fl_buf;
+       switch (fltab.fl_active) {
+
+       case FL_MAND:           /* send command */
+               if ((bp->b_flags&B_READ) == B_READ)
+                       mtpr(TXDB,FL_RS);
+               else
+                       mtpr(TXDB,  FL_WS);
+               fltab.fl_active = FL_SEC;
+               break;
+
+       case FL_SEC:            /* send sector address */
+               databyte = (int)bp->b_blkno % RXSTRK + 1;
+               mtpr(TXDB, FL_DATA | databyte);
+               fltab.fl_active = FL_TRACK;
+               break;
+
+       case FL_TRACK:          /* send track address */
+               databyte = (int)bp->b_blkno / RXSTRK;
+               mtpr(TXDB , FL_DATA | databyte);
+               if ((bp->b_flags&B_READ) == B_READ)
+                       /* prepare to receive complete */
+                       fltab.fl_active = FL_COM;
+               else
+                       /* prepare to send data */
+                       fltab.fl_active = FL_DAX;
+               break;
+
+       case FL_DAX:
+               databyte = *(fltab.fl_xaddr++);
+               mtpr(TXDB, FL_DATA | databyte);
+               if (--bp->b_bcount == 0)
+                       fltab.fl_active = FL_COM;
+               break;
+
+       case FL_CAN:            /* give cancel order */
+               mtpr(TXDB, FL_CANCEL);
+               if (++fltab.fl_errcnt <= FLERRS) {
+                       /* If error count permits, retry order */
+                       fltab.fl_active = FL_MAND;
+                       bp->b_bcount = RXBYSEC;
+                       fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
+               } else {
+                       /*
+                        * We're really stupid today - call it an
+                        * error and give up
+                        */
+                       bp->b_flags |= B_ERROR | B_DONE;
+                       bp->b_resid = -RXBYSEC;
+                       fltab.fl_active = FL_IDLE;
+                       wakeup((caddr_t)bp);
+               }
+       }
+}
+
+cnrfl(c)
+       int c;
+{
+       register int datum;
+       register struct buf *bp;
+
+       datum = c;
+       bp = fltab.fl_buf;
+       if (datum == FL_PERR) {
+               /*
+                * Got a protocol error - cancel the
+                * current function and try again if error count isn't
+                * too great.  First, though, make sure that an actual
+                * transaction is in progress (so a spurious error from
+                * the LSI won't screw us up too much!
+                */
+               if (fltab.fl_active != FL_IDLE)
+                       fltab.fl_active = FL_CAN;
+       } else switch(fltab.fl_active ) {
+
+       case FL_DAR:            /* expecting a datum */
+               if ((c&RXDB_ID) != FL_DATA)
+                       goto error;
+               *(fltab.fl_xaddr++) = (c & RXDB_DATA);
+               if (--bp->b_bcount==0) {
+                       fltab.fl_active = FL_IDLE;
+                       bp->b_flags |= B_DONE;
+                       wakeup((caddr_t)bp);
+               }
+               break;
+
+       case FL_COM:            /* expecting a "function complete" */
+               if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){
+error:
+                       bp->b_flags |= B_ERROR | B_DONE;
+                       bp->b_resid = -bp->b_bcount;
+                       fltab.fl_active = FL_IDLE;
+                       wakeup((caddr_t)bp);
+               } else if ((bp->b_flags&B_READ) == B_READ)
+                       /* got function complete, now get data */
+                       fltab.fl_active = FL_DAR;
+               else {
+                       /* got function complete on write - finish up */
+                       fltab.fl_active = FL_IDLE;
+                       bp->b_flags |= B_DONE;
+                               wakeup((caddr_t)bp);
+               }
+               break;
+       }
+}
diff --git a/usr/src/sys/dev/hp.c b/usr/src/sys/dev/hp.c
new file mode 100644 (file)
index 0000000..055859e
--- /dev/null
@@ -0,0 +1,534 @@
+/*     hp.c    4.1     11/9/80 */
+
+#include "../conf/hp.h"
+#if NHP > 0
+/*
+ * RP06/RM03/RM05 disk driver
+ */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dk.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/map.h"
+#include "../h/pte.h"
+#include "../h/mba.h"
+#include "../h/mtpr.h"
+#include "../h/vm.h"
+
+struct device
+{
+       int     hpcs1;          /* control and Status register 1 */
+       int     hpds;           /* Drive Status */
+       int     hper1;          /* Error register 1 */
+       int     hpmr;           /* Maintenance */ 
+       int     hpas;           /* Attention Summary */
+       int     hpda;           /* Desired address register */
+       int     hpdt;           /* Drive type */
+       int     hpla;           /* Look ahead */
+       int     hpsn;           /* serial number */
+       int     hpof;           /* Offset register */
+       int     hpdc;           /* Desired Cylinder address register */
+       int     hpcc;           /* Current Cylinder */
+       int     hper2;          /* Error register 2 */
+       int     hper3;          /* Error register 3 */
+       int     hpec1;          /* Burst error bit position */
+       int     hpec2;          /* Burst error bit pattern */
+};
+
+#define        RP      022
+#define        RM      024
+#define        RM5     027
+#define        NSECT   22
+#define        NTRAC   19
+#define        NRMSECT 32
+#define        NRMTRAC 5
+
+#define        _hpSDIST        2
+#define        _hpRDIST        3
+
+int    hpSDIST = _hpSDIST;
+int    hpRDIST = _hpRDIST;
+int    hpseek;
+
+struct size
+{
+       daddr_t nblocks;
+       int     cyloff;
+} hp_sizes[8] =
+{
+       15884,  0,              /* A=cyl 0 thru 37 */
+       33440,  38,             /* B=cyl 38 thru 117 */
+       340670, 0,              /* C=cyl 0 thru 814 */
+       0,      0,
+       0,      0,
+       0,      0,
+       291346, 118,            /* G=cyl 118 thru 814 */
+       0,      0,
+}, rm_sizes[8] = {
+       15884,  0,              /* A=cyl 0 thru 99 */
+       33440,  100,            /* B=cyl 100 thru 309 */
+       131680, 0,              /* C=cyl 0 thru 822 */
+       0,      0,
+       0,      0,
+       0,      0,
+       82080,  310,            /* G=cyl 310 thru 822 */
+       0,      0,
+}, rm5_sizes[8] = {
+       15884,  0,              /* A=cyl 0 thru 26 */
+       33440,  27,             /* B=cyl 27 thru 81 */
+       500992, 0,              /* C=cyl 0 thru 823 */
+       15884,  562,            /* D=cyl 562 thru 588 */
+       55936,  589,            /* E=cyl 589 thru 680 */
+       86944,  681,            /* F=cyl 681 thru 823 */
+       159296, 562,            /* G=cyl 562 thru 823 */
+       291346, 82,             /* H=cyl 82 thru 561 */
+};
+
+#define        P400    020
+#define        M400    0220
+#define        P800    040
+#define        M800    0240
+#define        P1200   060
+#define        M1200   0260
+int    hp_offset[16] =
+{
+       P400, M400, P400, M400,
+       P800, M800, P800, M800,
+       P1200, M1200, P1200, M1200,
+       0, 0, 0, 0,
+};
+
+struct buf     hptab;
+struct buf     rhpbuf;
+struct buf     hputab[NHP];
+char   hp_type[NHP];   /* drive type */
+
+#define        GO      01
+#define        PRESET  020
+#define        RTC     016
+#define        OFFSET  014
+#define        SEEK    04
+#define        SEARCH  030
+#define        RECAL   06
+#define        DCLR    010
+#define        WCOM    060
+#define        RCOM    070
+
+#define        IE      0100
+#define        PIP     020000
+#define        DRY     0200
+#define        ERR     040000
+#define        TRE     040000
+#define        DCK     0100000
+#define        WLE     04000
+#define        ECH     0100
+#define        VV      0100
+#define        DPR     0400
+#define        MOL     010000
+#define        FMT22   010000
+
+#define        b_cylin b_resid
+#ifdef INTRLVE
+daddr_t dkblock();
+#endif
+hpstrategy(bp)
+register struct buf *bp;
+{
+       register struct buf *dp;
+       register unit, xunit, nspc;
+       long sz, bn;
+       struct size *sizes;
+
+       if ((mbaact&(1<<HPMBANUM)) == 0)
+               mbainit(HPMBANUM);
+       xunit = minor(bp->b_dev) & 077;
+       sz = bp->b_bcount;
+       sz = (sz+511) >> 9;
+       unit = dkunit(bp);
+       if (hp_type[unit] == 0) {
+               struct device *hpaddr;
+               double mspw;
+
+               /* determine device type */
+               hpaddr = mbadev(HPMBA, unit);
+
+               /* record transfer rate (these are guesstimates secs/word) */
+               switch (hp_type[unit] = hpaddr->hpdt) {
+               case RM:        mspw = .0000019728; break;
+               case RM5:       mspw = .0000020345; break;
+               case RP:        mspw = .0000029592; break;
+               }
+               if (DK_N + unit <= DK_NMAX)
+                       dk_mspw[DK_N+unit] = mspw;
+       }
+       switch (hp_type[unit]) {
+
+       case RM:
+               sizes = rm_sizes;
+               nspc = NRMSECT*NRMTRAC;
+               break;
+       case RM5:
+               sizes = rm5_sizes;
+               nspc = NRMSECT*NTRAC;
+               break;
+       case RP:
+               sizes = hp_sizes;
+               nspc = NSECT*NTRAC;
+               break;
+       default:
+               printf("hp: unknown device type 0%o\n", hp_type[unit]);
+               u.u_error = ENXIO;
+               unit = NHP+1;   /* force error */
+       }
+       if (unit >= NHP ||
+           bp->b_blkno < 0 ||
+           (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
+               bp->b_flags |= B_ERROR;
+               iodone(bp);
+               return;
+       }
+       bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
+       dp = &hputab[unit];
+       (void) spl5();
+       disksort(dp, bp);
+       if (dp->b_active == 0) {
+               hpustart(unit);
+               if(hptab.b_active == 0)
+                       hpstart();
+       }
+       (void) spl0();
+}
+
+hpustart(unit)
+register unit;
+{
+       register struct buf *bp, *dp;
+       register struct device *hpaddr;
+       daddr_t bn;
+       int sn, cn, csn;
+
+       ((struct mba_regs *)HPMBA)->mba_cr |= MBAIE;
+       hpaddr = mbadev(HPMBA, 0);
+       hpaddr->hpas = 1<<unit;
+
+       if(unit >= NHP)
+               return;
+       if (unit+DK_N <= DK_NMAX)
+               dk_busy &= ~(1<<(unit+DK_N));
+       dp = &hputab[unit];
+       if((bp=dp->b_actf) == NULL)
+               return;
+       hpaddr = mbadev(HPMBA, unit);
+       if((hpaddr->hpds & VV) == 0) {
+               hpaddr->hpcs1 = PRESET|GO;
+               hpaddr->hpof = FMT22;
+       }
+       if(dp->b_active)
+               goto done;
+       dp->b_active++;
+       if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
+               goto done;
+
+       bn = dkblock(bp);
+       cn = bp->b_cylin;
+       switch (hp_type[unit]) {
+
+       case RM:
+               sn = bn%(NRMSECT*NRMTRAC);
+               sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
+               break;
+       case RM5:
+               sn = bn%(NRMSECT*NTRAC);
+               sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
+               break;
+       case RP:
+               sn = bn%(NSECT*NTRAC);
+               sn = (sn+NSECT-hpSDIST)%NSECT;
+               break;
+       default:
+               panic("hpustart");
+       }
+
+       if(cn - (hpaddr->hpdc & 0xffff))
+               goto search;
+       else if (hpseek)
+               goto done;
+       csn = ((hpaddr->hpla & 0xffff)>>6) - sn + 1;
+       if(csn < 0)
+               csn += NSECT;
+       if(csn > NSECT-hpRDIST)
+               goto done;
+
+search:
+       hpaddr->hpdc = cn;
+       if (hpseek)
+               hpaddr->hpcs1 = SEEK|GO;
+       else {
+               hpaddr->hpda = sn;
+               hpaddr->hpcs1 = SEARCH|GO;
+       }
+       unit += DK_N;
+       if (unit <= DK_NMAX) {
+               dk_busy |= 1<<unit;
+               dk_seek[unit]++;
+       }
+       return;
+
+done:
+       dp->b_forw = NULL;
+       if(hptab.b_actf == NULL)
+               hptab.b_actf = dp;
+       else
+               hptab.b_actl->b_forw = dp;
+       hptab.b_actl = dp;
+}
+
+hpstart()
+{
+       register struct buf *bp, *dp;
+       register unit;
+       register struct device *hpaddr;
+       daddr_t bn;
+       int dn, sn, tn, cn, nspc, ns;
+
+loop:
+       if ((dp = hptab.b_actf) == NULL)
+               return;
+       if ((bp = dp->b_actf) == NULL) {
+               hptab.b_actf = dp->b_forw;
+               goto loop;
+       }
+       hptab.b_active++;
+       unit = minor(bp->b_dev) & 077;
+       dn = dkunit(bp);
+       bn = dkblock(bp);
+       switch (hp_type[dn]) {
+       case RM:
+               nspc = NRMSECT*NRMTRAC;
+               ns = NRMSECT;
+               cn = rm_sizes[unit&07].cyloff;
+               break;
+       case RM5:
+               nspc = NRMSECT*NTRAC;
+               ns = NRMSECT;
+               cn = rm5_sizes[unit&07].cyloff;
+               break;
+       case RP:
+               nspc = NSECT*NTRAC;
+               ns = NSECT;
+               cn = hp_sizes[unit&07].cyloff;
+               break;
+       default:
+               panic("hpstart");
+       }
+       cn += bn/nspc;
+       sn = bn%nspc;
+       tn = sn/ns;
+       sn = sn%ns;
+
+       hpaddr = mbadev(HPMBA, dn);
+       if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
+               hptab.b_active = 0;
+               hptab.b_errcnt = 0;
+               dp->b_actf = bp->av_forw;
+               bp->b_flags |= B_ERROR;
+               iodone(bp);
+               goto loop;
+       }
+       if(hptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
+               hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
+               HPMBA->mba_cr &= ~MBAIE;
+               hpaddr->hpcs1 = OFFSET|GO;
+               while(hpaddr->hpds & PIP)
+                       ;
+               HPMBA->mba_cr |= MBAIE;
+       }
+       hpaddr->hpdc = cn;
+       hpaddr->hpda = (tn << 8) + sn;
+       mbastart(bp, (int *)hpaddr);
+
+       unit = dn+DK_N;
+       if (unit <= DK_NMAX) {
+               dk_busy |= 1<<unit;
+               dk_xfer[unit]++;
+               dk_wds[unit] += bp->b_bcount>>6;
+       }
+}
+
+hpintr(mbastat, as)
+{
+       register struct buf *bp, *dp;
+       register unit;
+       register struct device *hpaddr;
+
+       if(hptab.b_active) {
+               dp = hptab.b_actf;
+               bp = dp->b_actf;
+               unit = dkunit(bp);
+               if (DK_N+unit <= DK_NMAX)
+                       dk_busy &= ~(1<<(DK_N+unit));
+               hpaddr = mbadev(HPMBA, unit);
+               if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {
+                       while((hpaddr->hpds & DRY) == 0)
+                               ;
+                       if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
+                               bp->b_flags |= B_ERROR;
+                       else
+                               hptab.b_active = 0;
+                       if(hptab.b_errcnt > 27)
+                               deverror(bp, mbastat, hpaddr->hper1);
+                       if ((hpaddr->hper1&0xffff) == DCK) {
+                               if (hpecc(hpaddr, bp))
+                                       return;
+                       }
+                       hpaddr->hpcs1 = DCLR|GO;
+                       if((hptab.b_errcnt&07) == 4) {
+                               HPMBA->mba_cr &= ~MBAIE;
+                               hpaddr->hpcs1 = RECAL|GO;
+                               while(hpaddr->hpds & PIP)
+                                       ;
+                               HPMBA->mba_cr |= MBAIE;
+                       }
+               }
+               if(hptab.b_active) {
+                       if(hptab.b_errcnt) {
+                               HPMBA->mba_cr &= ~MBAIE;
+                               hpaddr->hpcs1 = RTC|GO;
+                               while(hpaddr->hpds & PIP)
+                                       ;
+                               HPMBA->mba_cr |= MBAIE;
+                       }
+                       hptab.b_active = 0;
+                       hptab.b_errcnt = 0;
+                       hptab.b_actf = dp->b_forw;
+                       dp->b_active = 0;
+                       dp->b_errcnt = 0;
+                       dp->b_actf = bp->av_forw;
+                       bp->b_resid = -HPMBA->mba_bcr & 0xffff;
+                       iodone(bp);
+                       if(dp->b_actf)
+                               hpustart(unit);
+               }
+               as &= ~(1<<unit);
+       } else {
+               if(as == 0)
+                       HPMBA->mba_cr |= MBAIE;
+       }
+       for(unit=0; unit<NHP; unit++)
+               if(as & (1<<unit))
+                       hpustart(unit);
+       hpstart();
+}
+
+hpread(dev)
+{
+
+       physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
+}
+
+hpwrite(dev)
+{
+
+       physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
+}
+
+hpecc(rp, bp)
+register struct device *rp;
+register struct buf *bp;
+{
+       struct mba_regs *mbp = HPMBA;
+       register int i;
+       caddr_t addr;
+       int reg, bit, byte, npf, mask, o;
+       int dn, bn, cn, tn, sn, ns, nt;
+       extern char buffers[NBUF][BSIZE];
+       struct pte mpte;
+       int bcr;
+
+       /*
+        * Npf is the number of sectors transferred before the sector
+        * containing the ECC error, and reg is the MBA register
+        * mapping (the first part of)the transfer.
+        * O is offset within a memory page of the first byte transferred.
+        */
+       bcr = mbp->mba_bcr & 0xffff;
+       if (bcr)
+               bcr |= 0xffff0000;              /* sxt */
+       npf = btop(bcr + bp->b_bcount) - 1;
+       reg = npf;
+       o = (int)bp->b_un.b_addr & PGOFSET;
+       printf("%D ", bp->b_blkno + npf);
+       prdev("ECC", bp->b_dev);
+       mask = rp->hpec2&0xffff;
+       if (mask == 0) {
+               rp->hpof = FMT22;
+               return (0);
+       }
+
+       /*
+        * Compute the byte and bit position of the error.
+        * The variable i is the byte offset in the transfer,
+        * the variable byte is the offset from a page boundary
+        * in main memory.
+        */
+       i = (rp->hpec1&0xffff) - 1;             /* -1 makes 0 origin */
+       bit = i&07;
+       i = (i&~07)>>3;
+       byte = i + o;
+       /*
+        * Correct while possible bits remain of mask.  Since mask
+        * contains 11 bits, we continue while the bit offset is > -11.
+        * Also watch out for end of this block and the end of the whole
+        * transfer.
+        */
+       while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
+               mpte = mbp->mba_map[reg+btop(byte)];
+               addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
+               putmemc(addr, getmemc(addr)^(mask<<bit));
+               byte++;
+               i++;
+               bit -= 8;
+       }
+       hptab.b_active++;               /* Either complete or continuing */
+       if (bcr == 0)
+               return (0);
+       /*
+        * Have to continue the transfer... clear the drive,
+        * and compute the position where the transfer is to continue.
+        * We have completed npf+1 sectores of the transfer already;
+        * restart at offset o of next sector (i.e. in MBA register reg+1).
+        */
+       rp->hpcs1 = DCLR|GO;
+       dn = dkunit(bp);
+       bn = dkblock(bp);
+       switch (hp_type[dn]) {
+
+       case RM:
+               ns = NRMSECT; nt = NRMTRAC; break;
+       case RM5:
+               ns = NRMSECT; nt = NTRAC; break;
+       case RP:
+               ns = NSECT; nt = NTRAC; break;
+       default:
+               panic("hpecc");
+       }
+       cn = bp->b_cylin;
+       sn = bn%(ns*nt) + npf + 1;
+       tn = sn/ns;
+       sn %= ns;
+       cn += tn/nt;
+       tn %= nt;
+       rp->hpdc = cn;
+       rp->hpda = (tn<<8) + sn;
+       mbp->mba_sr = -1;
+       mbp->mba_var = (int)ptob(reg+1) + o;
+       rp->hpcs1 = RCOM|GO;
+       return (1);
+}
+#endif
diff --git a/usr/src/sys/dev/mem.c b/usr/src/sys/dev/mem.c
new file mode 100644 (file)
index 0000000..7153f1a
--- /dev/null
@@ -0,0 +1,165 @@
+/*     mem.c   4.1     11/9/80 */
+
+/*
+ * Memory special file
+ *     minor device 0 is physical memory
+ *     minor device 1 is kernel memory 
+ *     minor device 2 is EOF/RATHOLE
+ *     minor device 3 is unibus memory (addressed by shorts)
+ */
+
+#include "../h/param.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/systm.h"
+#include "../h/pte.h"
+#include "../h/mtpr.h"
+#include "../h/vm.h"
+#include "../h/cmap.h"
+
+mmread(dev)
+{
+       register int o;
+       register unsigned c, v;
+
+       switch (minor(dev)) {
+
+       case 0:
+               while (u.u_count != 0 && u.u_error == 0) {
+                       if (fubyte(u.u_base) == -1)
+                               goto fault;
+                       v = btop(u.u_offset);
+                       if (v >= physmem)
+                               goto fault;
+                       *(int *)mmap = v | (PG_V | PG_KR);
+                       mtpr(TBIS, vmmap);
+                       o = (int)u.u_offset & PGOFSET;
+                       c = min((unsigned)(NBPG - o), u.u_count);
+                       c = min(c, (unsigned)(NBPG - ((int)u.u_base&PGOFSET)));
+                       if (copyout((caddr_t)&vmmap[o], u.u_base, c))
+                               goto fault;
+                       u.u_count -= c;
+                       u.u_base += c;
+                       u.u_offset += c;
+               }
+               return;
+
+       case 1:
+               if (u.u_uid != 0) {
+                       if ((caddr_t)u.u_offset < (caddr_t)&umbabeg &&
+                           (caddr_t)u.u_offset + u.u_count >= (caddr_t)&umbabeg)
+                               goto fault;
+                       if ((caddr_t)u.u_offset >= (caddr_t)&umbabeg &&
+                           (caddr_t)u.u_offset < (caddr_t)&umbaend)
+                               goto fault;
+               }
+               if (!kernacc((caddr_t)u.u_offset, u.u_count, B_READ))
+                       goto fault;
+               if (copyout((caddr_t)u.u_offset, u.u_base, u.u_count))
+                       goto fault;
+               c = u.u_count;
+               u.u_count = 0;
+               u.u_base += c;
+               u.u_offset += c;
+               return;
+
+       case 2:
+               return;
+
+       case 3:
+               if (!kernacc((caddr_t)u.u_offset, u.u_count, B_READ))
+                       goto fault;
+               if (!useracc(u.u_base, u.u_count, B_WRITE))
+                       goto fault;
+               UNIcpy((caddr_t)u.u_offset, u.u_base, u.u_count, B_READ);
+               c = u.u_count;
+               u.u_count = 0;
+               u.u_base += c;
+               u.u_offset += c;
+               return;
+       }
+fault:
+       u.u_error = EFAULT;
+       return;
+}
+
+mmwrite(dev)
+{
+       register int o;
+       register unsigned c, v;
+
+       switch (minor(dev)) {
+
+       case 0:
+               while (u.u_count != 0 && u.u_error == 0) {
+                       if (fubyte(u.u_base) == -1)
+                               goto fault;
+                       v = btop(u.u_offset);
+                       if (v >= physmem)
+                               goto fault;
+                       *(int *)mmap = v | (PG_V | PG_KW);
+                       mtpr(TBIS, vmmap);
+                       o = (int)u.u_offset & PGOFSET;
+                       c = min((unsigned)(NBPG - o), u.u_count);
+                       c = min(c, (unsigned)(NBPG - ((int)u.u_base&PGOFSET)));
+                       if (copyin(u.u_base, (caddr_t)&vmmap[o], c))
+                               goto fault;
+                       u.u_count -= c;
+                       u.u_base += c;
+                       u.u_offset += c;
+               }
+               return;
+
+       case 1:
+               if (!kernacc((caddr_t)u.u_offset, u.u_count, B_WRITE))
+                       goto fault;
+               if (copyin(u.u_base, (caddr_t)u.u_offset, u.u_count))
+                       goto fault;
+               u.u_base += u.u_count;
+               u.u_offset += u.u_count;
+               u.u_count = 0;
+               return;
+
+       case 2:
+               u.u_offset += u.u_count;
+               u.u_count = 0;
+               return;
+
+       case 3:
+               if (!kernacc((caddr_t)u.u_offset, u.u_count, B_WRITE))
+                       goto fault;
+               if (!useracc(u.u_base, u.u_count, B_READ))
+                       goto fault;
+               UNIcpy((caddr_t)u.u_offset, u.u_base, u.u_count, B_WRITE);
+               u.u_base += u.u_count;
+               u.u_offset += u.u_count;
+               u.u_count = 0;
+               return;
+       }
+fault:
+       u.u_error = EFAULT;
+       return;
+}
+
+/*
+ * UNIBUS Address Space <--> User Space transfer
+ */
+UNIcpy(uniadd, usradd, bknt, direct)
+       caddr_t uniadd, usradd;
+       unsigned bknt;
+{
+       register short *from, *to;
+       register int i;
+       if (direct == B_READ) {
+               from = (short *) uniadd;
+               to = (short *) usradd;
+       } else {
+               from = (short *) usradd;
+               to = (short *) uniadd;
+       }
+       for (i = (bknt>>1); i > 0; i--)
+               *to++ = *from++;
+}
diff --git a/usr/src/sys/dev/mx1.c b/usr/src/sys/dev/mx1.c
new file mode 100644 (file)
index 0000000..43ec89c
--- /dev/null
@@ -0,0 +1,586 @@
+/*     mx1.c   4.1     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/reg.h"
+#include "../h/proc.h"
+#include "../h/tty.h"
+#include "../h/inode.h"
+#include "../h/mx.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+
+/*
+ * Multiplexor:   clist version
+ *
+ * installation:
+ *     requires a line in cdevsw -
+ *             mxopen, mxclose, mxread, mxwrite, mxioctl, 0,
+ *
+ *     also requires a line in linesw -
+ *             mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev,
+ *
+ *     The linesw entry for mpx should be the last one in the table.
+ *     'nldisp' (number of line disciplines) should not include the
+ *     mpx line.  This is to prevent mpx from being enabled by an ioctl.
+
+ *     mxtty.c must be loaded instead of tty.c so that certain
+ *     sleeps will not be done if a typewriter is connected to
+ *     a channel and so that sdata will be called from ttyinput.
+ *     
+ */
+struct chan    chans[NCHANS];
+struct schan   schans[NPORTS];
+struct group   *groups[NGROUPS];
+int    mpxline;
+struct chan *xcp();
+dev_t  mpxdev  = -1;
+
+
+char   mcdebugs[NDEBUGS];
+
+
+/*
+ * Allocate a channel, set c_index to index.
+ */
+struct chan *
+challoc(index, isport)
+{
+register s,i;
+register struct chan *cp;
+
+       s = spl6();
+       for(i=0;i<((isport)?NPORTS:NCHANS);i++) {
+               cp = (isport)? (struct chan *)(schans+i): chans+i;
+               if(cp->c_group == NULL) {
+                       cp->c_index = index;
+                       cp->c_pgrp = 0;
+                       cp->c_flags = 0;
+                       splx(s);
+                       return(cp);
+               }
+       }
+       splx(s);
+       return(NULL);
+}
+
+
+
+/*
+ * Allocate a group table cell.
+ */
+gpalloc()
+{
+       register i;
+
+       for (i=NGROUPS-1; i>=0; i--)
+               if (groups[i]==NULL) {
+                       groups[i]++;
+                       return(i);
+               }
+       u.u_error = ENXIO;
+       return(i);
+}
+
+
+/*
+ * Add a channel to the group in
+ * inode ip.
+ */
+struct chan *
+addch(ip, isport)
+struct inode *ip;
+{
+register struct chan *cp;
+register struct group *gp;
+register i;
+
+       plock(ip);
+       gp = &ip->i_un.i_group;
+       for(i=0;i<NINDEX;i++) {
+               cp = (struct chan *)gp->g_chans[i];
+               if (cp == NULL) {
+                       if ((cp=challoc(i, isport)) != NULL) {
+                               gp->g_chans[i] = cp;
+                               cp->c_group = gp;
+                       }
+                       break;
+               }
+               cp = NULL;
+       }
+       prele(ip);
+       return(cp);
+}
+
+/*
+ * Mpxchan system call.
+ */
+
+mpxchan()
+{
+       extern  mxopen(), mcread(), sdata(), scontrol();
+       struct  inode   *ip, *gip;
+       struct  tty     *tp;
+       struct  file    *fp, *chfp, *gfp;
+       struct  chan    *cp;
+       struct  group   *gp, *ngp;
+       struct  mx_args vec;
+       struct  a       {
+               int     cmd;
+               int     *argvec;
+       } *uap;
+       dev_t   dev;
+       register int i;
+
+       /*
+        * Common setup code.
+        */
+
+       uap = (struct a *)u.u_ap;
+       (void) copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec);
+       gp = NULL; gfp = NULL; cp = NULL;
+
+       switch(uap->cmd) {
+
+       case NPGRP:
+               if (vec.m_arg[1] < 0)
+                       break;
+       case CHAN:
+       case JOIN:
+       case EXTR:
+       case ATTACH:
+       case DETACH:
+       case CSIG:
+               gfp = getf(vec.m_arg[1]);
+               if (gfp==NULL)
+                       return;
+               gip = gfp->f_inode;
+               gp = &gip->i_un.i_group;
+               if (gp->g_inode != gip) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+       }
+
+       switch(uap->cmd) {
+
+       /*
+        * Create an MPX file.
+        */
+
+       case MPX:
+       case MPXN:
+               if (mpxdev < 0) {
+                       for (i=0; linesw[i].l_open; i++) {
+                               if (linesw[i].l_read==mcread) {
+                                       mpxline = i;
+                                       for (i=0; cdevsw[i].d_open; i++) {
+                                               if (cdevsw[i].d_open==mxopen) {
+                                                       mpxdev = (dev_t)(i<<8);
+                                               }
+                                       }
+                               }
+                       }
+                       if (mpxdev < 0) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+               }
+               if (uap->cmd==MPXN) {
+                       if ((ip=ialloc(pipedev))==NULL)
+                               return;
+                       ip->i_mode = ((vec.m_arg[1]&0777)+IFMPC) & ~u.u_cmask;
+                       ip->i_flag = IACC|IUPD|ICHG;
+               } else {
+                       u.u_dirp = vec.m_name;
+                       ip = namei(uchar,1);
+                       if (ip != NULL) {
+                               i = ip->i_mode&IFMT;
+                               u.u_error = EEXIST;
+                               if (i==IFMPC || i==IFMPB) {
+                                       i = minor(ip->i_un.i_rdev);
+                                       gp = groups[i];
+                                       if (gp && gp->g_inode==ip)
+                                               u.u_error = EBUSY;
+                               }
+                               iput(ip);
+                               return;
+                       }
+                       if (u.u_error)
+                               return;
+                       ip = maknode((vec.m_arg[1]&0777)+IFMPC);
+                       if (ip == NULL)
+                               return;
+               }
+               if ((i=gpalloc()) < 0) {
+                       iput(ip);
+                       return;
+               }
+               if ((fp=falloc()) == NULL) {
+                       iput(ip);
+                       groups[i] = NULL;
+                       return;
+               }
+               ip->i_un.i_rdev = (daddr_t)(mpxdev+i);
+               ip->i_count++;
+               prele(ip);
+
+               gp = &ip->i_un.i_group;
+               groups[i] = gp;
+               gp->g_inode = ip;
+               gp->g_state = INUSE|ISGRP;
+               gp->g_group = NULL;
+               gp->g_file = fp;
+               gp->g_index = 0;
+               gp->g_rotmask = 1;
+               gp->g_rot = 0;
+               gp->g_datq = 0;
+               for(i=0;i<NINDEX;)
+                       gp->g_chans[i++] = NULL;
+
+               fp->f_flag = FREAD|FWRITE|FMP;
+               fp->f_inode = ip;
+               fp->f_un.f_chan = NULL;
+               return;
+
+       /*
+        * join file descriptor (arg 0) to group (arg 1)
+        * return channel number
+        */
+
+       case JOIN:
+               if ((fp=getf(vec.m_arg[0]))==NULL)
+                       return;
+               ip = fp->f_inode;
+               switch (ip->i_mode & IFMT) {
+
+               case IFMPC:
+                       if ((fp->f_flag&FMP) != FMP) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+                       ngp = &ip->i_un.i_group;
+                       if (mtree(ngp, gp) == NULL)
+                               return;
+                       fp->f_count++;
+                       u.u_r.r_val1 = cpx((struct chan *)ngp);
+                       return;
+
+               case IFCHR:
+                       dev = (dev_t)ip->i_un.i_rdev;
+                       tp = cdevsw[major(dev)].d_ttys;
+                       if (tp==NULL) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+                       tp = &tp[minor(dev)];
+                       if (tp->t_chan) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+                       if ((cp=addch(gip, 1))==NULL) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+                       tp->t_chan = cp;
+                       cp->c_fy = fp;
+                       fp->f_count++;
+                       cp->c_ttyp = tp;
+                       cp->c_line = tp->t_line;
+                       cp->c_flags = XGRP+PORT;
+                       u.u_r.r_val1 = cpx(cp);
+                       return;
+
+               default:
+                       u.u_error = ENXIO;
+                       return;
+
+               }
+
+       /*
+        * Attach channel (arg 0) to group (arg 1).
+        */
+
+       case ATTACH:
+               cp = xcp(gp, vec.m_arg[0]);
+               if (cp==NULL || cp->c_flags&ISGRP) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               u.u_r.r_val1 = cpx(cp);
+               wakeup((caddr_t)cp);
+               return;
+
+       case DETACH:
+               cp = xcp(gp, vec.m_arg[0]);
+               if (cp==NULL) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               (void) detach(cp);
+               return;
+
+       /*
+        * Extract channel (arg 0) from group (arg 1).
+        */
+
+       case EXTR:
+               cp = xcp(gp, vec.m_arg[0]);
+               if (cp==NULL) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               if (cp->c_flags & ISGRP) {
+                       (void) mxfalloc(((struct group *)cp)->g_file);
+                       return;
+               }
+               if ((fp=cp->c_fy) != NULL) {
+                       (void) mxfalloc(fp);
+                       return;
+               }
+               if ((fp=falloc()) == NULL)
+                       return;
+               fp->f_inode = gip;
+               gip->i_count++;
+               fp->f_un.f_chan = cp;
+               fp->f_flag = (vec.m_arg[2]) ?
+                               (FREAD|FWRITE|FMPY) : (FREAD|FWRITE|FMPX);
+               cp->c_fy = fp;
+               return;
+
+       /*
+        * Make new chan on group (arg 1).
+        */
+
+       case CHAN:
+               if((gfp->f_flag&FMP)==FMP)cp = addch(gip, 0);
+                       if(cp == NULL){
+                       u.u_error = ENXIO;
+                       return;
+                       }
+               cp->c_flags = XGRP;
+               cp->c_fy = NULL;
+               cp->c_ttyp = cp->c_ottyp = (struct tty *)cp;
+               cp->c_line = cp->c_oline = mpxline;
+               u.u_r.r_val1 = cpx(cp);
+               return;
+
+       /*
+        * Connect fd (arg 0) to channel fd (arg 1).
+        * (arg 2 <  0) => fd to chan only
+        * (arg 2 >  0) => chan to fd only
+        * (arg 2 == 0) => both directions
+        */
+
+       case CONNECT:
+               if ((fp=getf(vec.m_arg[0]))==NULL)
+                       return;
+               if ((chfp=getf(vec.m_arg[1]))==NULL)
+                       return;
+               ip = fp->f_inode;
+               i = ip->i_mode&IFMT;
+               if (i!=IFCHR) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               dev = (dev_t)ip->i_un.i_rdev;
+               tp = cdevsw[major(dev)].d_ttys;
+               if (tp==NULL) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               tp = &tp[minor(dev)];
+               if (!(chfp->f_flag&FMPY)) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               cp = chfp->f_un.f_chan;
+               if (cp==NULL || cp->c_flags&PORT) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               i = vec.m_arg[2];
+               if (i>=0) {
+                       cp->c_ottyp = tp;
+                       cp->c_oline = tp->t_line;
+               }
+               if (i<=0)  {
+                       tp->t_chan = cp;
+                       cp->c_ttyp = tp;
+                       cp->c_line = tp->t_line;
+               }
+               u.u_r.r_val1 = 0;
+               return;
+
+       case NPGRP: {
+               register struct proc *pp;
+
+               if (gp != NULL) {
+                       cp = xcp(gp, vec.m_arg[0]);
+                       if (cp==NULL) {
+                               u.u_error = ENXIO;
+                               return;
+                       }
+               }
+               pp = u.u_procp;
+               pp->p_pgrp = pp->p_pid;
+               if (vec.m_arg[2])
+                       pp->p_pgrp = vec.m_arg[2];
+               if (gp != NULL)
+                       cp->c_pgrp = pp->p_pgrp;
+               u.u_r.r_val1 = pp->p_pgrp;
+               return;
+       }
+
+       case CSIG:
+               cp = xcp(gp, vec.m_arg[0]);
+               if (cp==NULL) {
+                       u.u_error = ENXIO;
+                       return;
+               }
+               gsignal(cp->c_pgrp, vec.m_arg[2]);
+               u.u_r.r_val1 = vec.m_arg[2];
+               return;
+
+       case DEBUG:
+               i = vec.m_arg[0];
+               if (i<0 || i>NDEBUGS)
+                       return;
+               mcdebugs[i] = vec.m_arg[1];
+               if (i==ALL)
+                       for(i=0;i<NDEBUGS;i++)
+                               mcdebugs[i] = vec.m_arg[1];
+               return;
+
+       default:
+               u.u_error = ENXIO;
+               return;
+       }
+
+}
+detach(cp)
+register struct chan *cp;
+{
+       register struct group *master,*sub;
+       register index;
+
+       if (cp==NULL)
+               return(0);
+       if (cp->c_flags&ISGRP) {
+               sub = (struct group *)cp;
+               master = sub->g_group;  index = sub->g_index;
+               closef(sub->g_file);
+               master->g_chans[index] = NULL;
+               return(0);
+       } else if (cp->c_flags&PORT && cp->c_ttyp != NULL) {
+               closef(cp->c_fy);
+               chdrain(cp);
+               chfree(cp);
+               return(0);
+       }
+       if (cp->c_flags & WCLOSE) {
+               if (cp->c_fy) {
+                       if (cp->c_fy->f_count)
+                               return(1);
+                       chfree(cp);
+                       return(0);
+               }
+       }
+       cp->c_flags |= WCLOSE;
+       chwake(cp);
+       return(1);
+}
+
+
+mxfalloc(fp)
+register struct file *fp;
+{
+register i;
+
+       if (fp==NULL) {
+               u.u_error = ENXIO;
+               return(-1);
+       }
+       i = ufalloc();
+       if (i < 0)
+               return(i);
+       u.u_ofile[i] = fp;
+       fp->f_count++;
+       u.u_r.r_val1 = i;
+       return(i);
+}
+
+/*
+ * Grow a branch on a tree.
+ */
+
+mtree(sub,master)
+register struct group *sub, *master;
+{
+       register i;
+       int mtresiz, stresiz;
+
+       if ((mtresiz=mup(master,sub)) == NULL) {
+               u.u_error = ENXIO;
+               return(NULL);
+       }
+       if ((stresiz=mdown(sub,master)) <= 0) {
+               u.u_error = ENXIO;
+               return(NULL);
+       }
+       if (sub->g_group != NULL) {
+               u.u_error = ENXIO;
+               return(NULL);
+       }
+       if (stresiz+mtresiz > NLEVELS) {
+               u.u_error = ENXIO;
+               return(NULL);
+       }
+       for (i=0;i<NINDEX;i++) {
+               if (master->g_chans[i] != NULL)
+                       continue;
+               master->g_chans[i] = (struct chan *)sub;
+               sub->g_group = master;
+               sub->g_index = i;
+               return(1);
+       }
+       u.u_error = ENXIO;
+       return(NULL);
+}
+
+mup(master,sub)
+struct group *master, *sub;
+{
+       register struct group *top;
+       register int depth;
+
+       depth = 1;  top = master;
+       while (top->g_group) {
+               depth++;
+               top = top->g_group;
+       }
+       if(top == sub)
+               return(NULL);
+       return(depth);
+}
+
+
+mdown(sub,master)
+struct group *sub, *master;
+{
+       register int maxdepth, i, depth;
+
+       if(sub == (struct group *)NULL || (sub->g_state&ISGRP) == 0)
+               return(0);
+       if(sub == master)
+               return(-1);
+       maxdepth = 0;
+       for(i=0; i<NINDEX; i++) {
+               if((depth=mdown((struct group *)sub->g_chans[i],master)) == -1)
+                       return(-1);
+               maxdepth = (depth>maxdepth) ? depth: maxdepth;
+       }
+       return(maxdepth+1);
+}
diff --git a/usr/src/sys/dev/tdump.c b/usr/src/sys/dev/tdump.c
new file mode 100644 (file)
index 0000000..6569619
--- /dev/null
@@ -0,0 +1,145 @@
+/*     tdump.c 4.1     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/vm.h"
+#include "../h/pte.h"
+#include "../h/systm.h"
+#include "../h/cmap.h"
+
+/*
+ * Dump core to magtape.
+ * Assumes memory mapping has been disabled
+ * and IPL has been set high ( > 0x15 )
+ */
+
+#define        UBA     0x20006000
+#define        mba0    0x20010000
+#define        mba1    0x20012000
+
+struct mba_regs {
+       int     mba_csr;
+       int     mba_cr;
+       int     mba_sr;
+       int     mba_var;
+       int     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 ((struct pte *) (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
+
+#define        DBSIZE  20
+
+dump()
+{
+
+       HTADDR->httc = P800;    /* set 800 bpi mode */
+
+       twall((char *)0, maxfree);      /* write out memory */
+
+       teof();
+       teof();
+       rewind();
+       twait();
+}
+
+twall(start, num)
+       char *start;
+       int num;
+{
+       int blk;
+
+       HTADDR->htcs1 = DCLR | GO;
+       while (num > 0) {
+               blk = num > DBSIZE ? DBSIZE : num;
+               twrite(start, blk);
+               start += blk*NBPG;
+               num -= blk;
+       }
+}
+
+twrite(buf, num)
+char *buf;
+{
+       register struct pte *hpte = HTMAP;
+       register int i;
+
+       twait();
+       HTADDR->htfc = -(num*NBPG);
+       for (i = 0; i < num; i++)
+               *(int *)hpte++ = (btop(buf)+i) | PG_V;
+       ((struct mba_regs *)mba1)->mba_sr = -1;
+       ((struct mba_regs *)mba1)->mba_bcr = -(num*NBPG);
+       ((struct mba_regs *)mba1)->mba_var = 0;
+       HTADDR->htcs1 = WCOM | GO;
+}
+
+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/dev/ttyold.c b/usr/src/sys/dev/ttyold.c
new file mode 100644 (file)
index 0000000..84cfb76
--- /dev/null
@@ -0,0 +1,498 @@
+/*     ttyold.c        4.1     11/9/80 */
+
+/*
+ * general TTY subroutines
+ */
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/tty.h"
+#include "../h/proc.h"
+#include "../h/mx.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/reg.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/dk.h"
+
+char   partab[];
+
+/*
+ * When running dz's using only SAE (silo alarm) on input
+ * it is necessary to call dzrint() at clock interrupt time.
+ * This is unsafe unless spl5()s in tty code are changed to
+ * spl6()s to block clock interrupts.  Note that the dh driver
+ * currently in use works the same way as the dz, even though
+ * we could try to more intelligently manage its silo.
+ * Thus don't take this out if you have no dz's unless you
+ * change clock.c and dhtimer().
+ */
+#define        spl5    spl6
+
+/*
+ * Input mapping table-- if an entry is non-zero, when the
+ * corresponding character is typed preceded by "\" the escape
+ * sequence is replaced by the table value.  Mostly used for
+ * upper-case only terminals.
+ */
+char   maptab[];
+
+#define        OBUFSIZ 100
+
+/*
+ * routine called on first teletype open.
+ * establishes a process group for distribution
+ * of quits and interrupts from the tty.
+ */
+ttyopen(dev, tp)
+dev_t dev;
+register struct tty *tp;
+{
+       register struct proc *pp;
+
+       pp = u.u_procp;
+       tp->t_dev = dev;
+       if(pp->p_pgrp == 0) {
+               u.u_ttyp = tp;
+               u.u_ttyd = dev;
+               if (tp->t_pgrp == 0)
+                       tp->t_pgrp = pp->p_pid;
+               pp->p_pgrp = tp->t_pgrp;
+       }
+       tp->t_state &= ~WOPEN;
+       tp->t_state |= ISOPEN;
+       tp->t_line = 0;         /* conservative */
+}
+
+/*
+ * clean tp on last close
+ */
+ttyclose(tp)
+register struct tty *tp;
+{
+
+       tp->t_pgrp = 0;
+       wflushtty(tp);
+       tp->t_state = 0;
+       tp->t_line = 0;
+}
+
+/*
+ * transfer raw input list to canonical list,
+ * doing erase-kill processing and handling escapes.
+ * It waits until a full line has been typed in cooked mode,
+ * or until any character has been typed in raw mode.
+ */
+canon(tp)
+register struct tty *tp;
+{
+       register char *bp;
+       char *bp1;
+       register int c;
+       int mc;
+       int s;
+
+       if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0
+           || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) {
+               return(-1);
+       }
+       s = spl0();
+loop:
+       bp = &canonb[2];
+       while ((c=getc(&tp->t_rawq)) >= 0) {
+               if ((tp->t_flags&(RAW|CBREAK))==0) {
+                       if (c==0377) {
+                               tp->t_delct--;
+                               break;
+                       }
+                       if (bp[-1]!='\\') {
+                               if (c==tp->t_erase) {
+                                       if (bp > &canonb[2])
+                                               bp--;
+                                       continue;
+                               }
+                               if (c==tp->t_kill)
+                                       goto loop;
+                               if (c==tun.t_eofc)
+                                       continue;
+                       } else {
+                               mc = maptab[c];
+                               if (c==tp->t_erase || c==tp->t_kill)
+                                       mc = c;
+                               if (mc && (mc==c || (tp->t_flags&LCASE))) {
+                                       if (bp[-2] != '\\')
+                                               c = mc;
+                                       bp--;
+                               }
+                       }
+               }
+               *bp++ = c;
+               if (bp>=canonb+CANBSIZ)
+                       break;
+       }
+       bp1 = &canonb[2];
+       (void) b_to_q(bp1, bp-bp1, &tp->t_canq);
+
+       if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
+               if (putc(tun.t_startc, &tp->t_outq)==0) {
+                       tp->t_state &= ~TBLOCK;
+                       ttstart(tp);
+               }
+               tp->t_char = 0;
+       }
+
+       splx(s);
+       return(0);
+}
+
+
+/*
+ * block transfer input handler.
+ */
+ttyrend(tp, pb, pe)
+register struct tty *tp;
+register char *pb, *pe;
+{
+       int     tandem;
+
+       tandem = tp->t_flags&TANDEM;
+       if (tp->t_flags&RAW) {
+               (void) b_to_q(pb, pe-pb, &tp->t_rawq);
+               if (tp->t_chan)
+                       (void) sdata(tp->t_chan); else
+                       wakeup((caddr_t)&tp->t_rawq);
+       } else {
+               tp->t_flags &= ~TANDEM;
+               while (pb < pe)
+                       ttyinput(*pb++, tp);
+               tp->t_flags |= tandem;
+       }
+       if (tandem)
+               ttyblock(tp);
+}
+
+/*
+ * Place a character on raw TTY input queue, putting in delimiters
+ * and waking up top half as needed.
+ * Also echo if required.
+ * The arguments are the character and the appropriate
+ * tty structure.
+ */
+ttyinput(c, tp)
+register c;
+register struct tty *tp;
+{
+       register int t_flags;
+       register struct chan *cp;
+
+       tk_nin += 1;
+       c &= 0377;
+       t_flags = tp->t_flags;
+       if (t_flags&TANDEM)
+               ttyblock(tp);
+       if ((t_flags&RAW)==0) {
+               c &= 0177;
+               if (tp->t_state&TTSTOP) {
+                       if (c==tun.t_startc) {
+                               tp->t_state &= ~TTSTOP;
+                               ttstart(tp);
+                               return;
+                       }
+                       if (c==tun.t_stopc)
+                               return;
+                       tp->t_state &= ~TTSTOP;
+                       ttstart(tp);
+               } else {
+                       if (c==tun.t_stopc) {
+                               tp->t_state |= TTSTOP;
+                               (*cdevsw[major(tp->t_dev)].d_stop)(tp);
+                               return;
+                       }
+                       if (c==tun.t_startc)
+                               return;
+               }
+               if (c==tun.t_quitc || c==tun.t_intrc) {
+                       flushtty(tp, FREAD|FWRITE);
+                       c = (c==tun.t_intrc) ? SIGINT:SIGQUIT;
+                       if (tp->t_chan)
+                               scontrol(tp->t_chan, M_SIG, c);
+                       else
+                               gsignal(tp->t_pgrp, c);
+                       return;
+               }
+               if (c=='\r' && t_flags&CRMOD)
+                       c = '\n';
+       }
+       if (tp->t_rawq.c_cc>TTYHOG) {
+               flushtty(tp, FREAD|FWRITE);
+               return;
+       }
+       if (t_flags&LCASE && c>='A' && c<='Z')
+               c += 'a'-'A';
+       (void) putc(c, &tp->t_rawq);
+       if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
+               if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
+                       tp->t_delct++;
+               if ((cp=tp->t_chan)!=NULL)
+                       (void) sdata(cp); else
+                       wakeup((caddr_t)&tp->t_rawq);
+       }
+       if (t_flags&ECHO) {
+               ttyoutput(c, tp);
+               if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0)
+                       ttyoutput('\n', tp);
+               ttstart(tp);
+       }
+}
+
+/*
+ * put character on TTY output queue, adding delays,
+ * expanding tabs, and handling the CR/NL bit.
+ * It is called both from the top half for output, and from
+ * interrupt level for echoing.
+ * The arguments are the character and the tty structure.
+ */
+ttyoutput(c, tp)
+register c;
+register struct tty *tp;
+{
+       register char *colp;
+       register ctype;
+
+       /*
+        * Ignore EOT in normal mode to avoid hanging up
+        * certain terminals.
+        * In raw mode dump the char unchanged.
+        */
+       if ((tp->t_flags&RAW)==0) {
+               c &= 0177;
+               if ((tp->t_flags&CBREAK)==0 && c==CEOT)
+                       return;
+       } else {
+               tk_nout++;
+               (void) putc(c, &tp->t_outq);
+               return;
+       }
+
+       /*
+        * Turn tabs to spaces as required
+        */
+       if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
+               c = 8 - (tp->t_col & 7);
+               (void) b_to_q("        ", c, &tp->t_outq);
+               tp->t_col += c;
+               tk_nout += c;
+               return;
+       }
+       tk_nout++;
+       /*
+        * for upper-case-only terminals,
+        * generate escapes.
+        */
+       if (tp->t_flags&LCASE) {
+               colp = "({)}!|^~'`";
+               while(*colp++)
+                       if(c == *colp++) {
+                               ttyoutput('\\', tp);
+                               c = colp[-2];
+                               break;
+                       }
+               if ('a'<=c && c<='z')
+                       c += 'A' - 'a';
+       }
+       /*
+        * turn <nl> to <cr><lf> if desired.
+        */
+       if (c=='\n' && tp->t_flags&CRMOD)
+               ttyoutput('\r', tp);
+       (void) putc(c, &tp->t_outq);
+       /*
+        * Calculate delays.
+        * The numbers here represent clock ticks
+        * and are not necessarily optimal for all terminals.
+        * The delays are indicated by characters above 0200.
+        * In raw mode there are no delays and the
+        * transmission path is 8 bits wide.
+        */
+       colp = &tp->t_col;
+       ctype = partab[c];
+       c = 0;
+       switch (ctype&077) {
+
+       /* ordinary */
+       case 0:
+               (*colp)++;
+
+       /* non-printing */
+       case 1:
+               break;
+
+       /* backspace */
+       case 2:
+               if (*colp)
+                       (*colp)--;
+               break;
+
+       /* newline */
+       case 3:
+               ctype = (tp->t_flags >> 8) & 03;
+               if(ctype == 1) { /* tty 37 */
+                       if (*colp)
+                               c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
+               } else
+               if(ctype == 2) { /* vt05 */
+                       c = 6;
+               }
+               *colp = 0;
+               break;
+
+       /* tab */
+       case 4:
+               ctype = (tp->t_flags >> 10) & 03;
+               if(ctype == 1) { /* tty 37 */
+                       c = 1 - (*colp | ~07);
+                       if(c < 5)
+                               c = 0;
+               }
+               *colp |= 07;
+               (*colp)++;
+               break;
+
+       /* vertical motion */
+       case 5:
+               if(tp->t_flags & VTDELAY) /* tty 37 */
+                       c = 0177;
+               break;
+
+       /* carriage return */
+       case 6:
+               ctype = (tp->t_flags >> 12) & 03;
+               if(ctype == 1) { /* tn 300 */
+                       c = 5;
+               } else if(ctype == 2) { /* ti 700 */
+                       c = 10;
+               } else if(ctype == 3) { /* concept 100 */
+                       int i;
+                       if ((i = *colp) >= 0)
+                               for (; i<9; i++)
+                                       (void) putc(0177, &tp->t_outq);
+               }
+               *colp = 0;
+       }
+       if(c)
+               (void) putc(c|0200, &tp->t_outq);
+}
+
+/*
+ * Called from device's read routine after it has
+ * calculated the tty-structure given as argument.
+ */
+ttread(tp)
+register struct tty *tp;
+{
+register s;
+
+       if ((tp->t_state&CARR_ON)==0)
+               return(-1);
+       s = spl5();
+       if (tp->t_canq.c_cc==0)
+               while (canon(tp)<0)
+                       if (tp->t_chan==NULL) {
+                               sleep((caddr_t)&tp->t_rawq, TTIPRI); 
+                       } else {
+                               splx(s);
+                               return(0);
+                       }
+       splx(s);
+       while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0)
+                       ;
+       return(tp->t_rawq.c_cc+tp->t_canq.c_cc);
+}
+
+/*
+ * Called from the device's write routine after it has
+ * calculated the tty-structure given as argument.
+ */
+caddr_t
+ttwrite(tp)
+register struct tty *tp;
+{
+       /*
+        * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
+        * AND MUST NOT BE CHANGED WITHOUT PATCHING
+        * THE 'ASM' INLINES BELOW.  WATCH OUT.
+        */
+       register char *cp;
+       register int cc, ce;
+       register i;
+       char obuf[OBUFSIZ];
+       int hiwat = TTHIWAT(tp);
+
+       if ((tp->t_state&CARR_ON)==0)
+               return(NULL);
+       while (u.u_count) {
+               cc = MIN(u.u_count, OBUFSIZ);
+               cp = obuf;
+               iomove(cp, (unsigned)cc, B_WRITE);
+               if (u.u_error)
+                       break;
+               (void) spl5();
+               while (tp->t_outq.c_cc > hiwat) {
+                       ttstart(tp);
+                       tp->t_state |= ASLEEP;
+                       if (tp->t_chan) {
+                               u.u_base -= cc;
+                               u.u_offset -= cc;
+                               u.u_count += cc;
+                               (void) spl0();
+                               return((caddr_t)&tp->t_outq);
+                       }
+                       sleep((caddr_t)&tp->t_outq, TTOPRI);
+               }
+               (void) spl0();
+               if (tp->t_flags&LCASE) {
+                       while (cc--)
+                               ttyoutput(*cp++,tp);
+                       continue;
+               }
+               while (cc) {
+                       if (tp->t_flags&RAW)
+                               ce=cc;
+                       else {
+#ifdef VAX
+                               asm("   scanc   r9,(r10),_partab,$077");
+                               asm("   subl3   r0,r9,r8");
+#else
+                               ce=0;
+                               while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
+                                       ce++;
+#endif
+                               if (ce==0) {
+                                       ttyoutput(*cp++,tp);
+                                       cc--;
+                                       goto check;
+                               }
+                       }
+                       i=b_to_q(cp,ce,&tp->t_outq);
+                       ce-=i;
+                       tk_nout+=ce;
+                       tp->t_col+=ce;
+                       cp+=ce;
+                       cc-=ce;
+check:
+                       if (tp->t_outq.c_cc > hiwat) {
+                               (void) spl5();
+                               while (tp->t_outq.c_cc > hiwat) {
+                                       ttstart(tp);
+                                       tp->t_state |= ASLEEP;
+                                       sleep((caddr_t)&tp->t_outq, TTOPRI);
+                               }
+                               (void) spl0();
+                       }
+               }
+       }
+       ttstart(tp);
+       return(NULL);
+}
diff --git a/usr/src/sys/dev/va.c b/usr/src/sys/dev/va.c
new file mode 100644 (file)
index 0000000..6e94ac3
--- /dev/null
@@ -0,0 +1,291 @@
+/*     va.c    4.1     11/9/80 */
+
+#include "../conf/va.h"
+#if NVA > 0
+/*
+ * Benson-Varian matrix printer/plotter
+ * dma interface driver
+ */
+#include "../h/param.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/buf.h"
+#include "../h/systm.h"
+#include "../h/map.h"
+#include "../h/pte.h"
+#include "../h/uba.h"
+#include "../h/vcmd.h"
+
+int    vabdp = 1;
+
+unsigned minvaph();
+
+#define        VAPRI   (PZERO-1)
+
+#define        ushort  unsigned short
+struct varegs {
+       ushort  vaba;
+       short   vawc;
+       union {
+               short   Vacsw;
+               struct {
+                       char Vacsl;
+                       char Vacsh;
+               } vacsr;
+       } vacs;
+       short   vadata;
+};
+
+#define        vacsw   vacs.Vacsw
+#define        vacsh   vacs.vacsr.Vacsh
+#define        vacsl   vacs.vacsr.Vacsl
+
+/* vacsw bits */
+#define        ERROR           0100000         /* Some error has occurred */
+#define        NPRTIMO         01000           /* DMA timeout error */
+#define        NOTREADY        0400            /* Something besides NPRTIMO */
+#define        DONE            0200
+#define        IENABLE         0100            /* Interrupt enable */
+#define        SUPPLIESLOW     04
+#define        BOTOFFORM       02
+#define        BYTEREVERSE     01              /* Reverse byte order in words */
+
+/* vacsh command bytes */
+#define        VAPLOT          0340
+#define        VAPRINT         0100
+#define        VAPRINTPLOT     0160
+#define        VAAUTOSTEP      0244
+#define        VANOAUTOSTEP    0045            /* unused */
+#define        VAFORMFEED      0263            /* unused */
+#define        VASLEW          0265            /* unused */
+#define        VASTEP          0064            /* unused */
+
+struct {
+       char    va_open;
+       char    va_busy;
+       int     va_state;       /* State: bits are commands in vcmd.h. */
+       int     va_wc;
+       int     va_bufp;
+       struct  buf *va_bp;
+} va11;
+int    va_ubinfo;
+
+struct buf rvabuf;             /* Used by physio for a buffer. */
+
+vaopen()
+{
+
+       if (va11.va_open) {
+               u.u_error = ENXIO;
+               return;
+       }
+       va11.va_open = 1;
+       VAADDR->vawc = 0;
+       va11.va_wc = 0;
+       va11.va_state = 0;
+       VAADDR->vacsl = IENABLE;
+       vatimo();
+       vacmd(VPRINT);
+       if (u.u_error)
+               vaclose();
+}
+
+vastrategy(bp)
+       register struct buf *bp;
+{
+       register int e;
+
+       (void) spl4();
+       while (va11.va_busy)
+               sleep((caddr_t)&va11, VAPRI);
+       va11.va_busy = 1;
+       va11.va_bp = bp;
+       va_ubinfo = ubasetup(bp, vabdp);
+       va11.va_bufp = va_ubinfo & 0x3ffff;
+       if (e = vaerror(DONE))
+               goto brkout;
+       va11.va_wc = -(bp->b_bcount/2);
+       vastart();
+       e = vaerror(DONE);      /* Wait for DMA to complete */
+       va11.va_wc = 0;
+       va11.va_bufp = 0;
+
+       /*
+        * After printing a line of characters, VPRINTPLOT mode essentially
+        * reverts to VPLOT mode, plotting things until a new mode is set.
+        * This change is indicated by sending a VAAUTOSTEP command to
+        * the va.  We also change va_state to reflect this effective
+        * mode change.
+        */
+       if (va11.va_state & VPRINTPLOT) {
+               va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT;
+               VAADDR->vacsh = VAAUTOSTEP;
+               e |= vaerror(DONE);
+       }
+       (void) spl0();
+brkout:
+       ubafree(va_ubinfo), va_ubinfo = 0;
+       va11.va_bp = 0;
+       va11.va_busy = 0;
+       iodone(bp);
+       if (e)
+               u.u_error = EIO;
+       wakeup((caddr_t)&va11);
+}
+
+int    vablock = 16384;
+
+unsigned
+minvaph(bp)
+struct buf *bp;
+{
+       if (bp->b_bcount > vablock)
+               bp->b_bcount = vablock;
+}
+
+/*ARGSUSED*/
+vawrite(dev)
+{
+       physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
+}
+
+/*
+ * Vaerror waits until bit or ERROR gets set, then returns non-zero if
+ * if it was ERROR that was set.
+ */
+vaerror(bit)
+{
+       register int e;
+
+       while ((e = VAADDR->vacsw & (bit|ERROR)) == 0)
+               sleep((caddr_t)&va11, VAPRI);
+       return (e & ERROR);
+}
+
+vastart()
+{
+       if (va11.va_wc) {
+               VAADDR->vaba = va11.va_bufp;
+               VAADDR->vawc = va11.va_wc;
+               return;
+       }
+}
+
+/*ARGSUSED*/
+vaioctl(dev, cmd, addr, flag)
+       register caddr_t addr;
+{
+       register int vcmd;
+
+       switch (cmd) {
+
+       case VGETSTATE:
+               (void) suword(addr, va11.va_state);
+               return;
+
+       case VSETSTATE:
+               vcmd = fuword(addr);
+               if (vcmd == -1) {       
+                       u.u_error = EFAULT;
+                       return;
+               }
+               vacmd(vcmd);
+               return;
+
+       default:
+               u.u_error = ENOTTY;     /* Not a legal ioctl cmd. */
+               return;
+       }
+}
+
+/*
+ * Send a command code to the va, and wait for it to complete.
+ * If an error occurs, u.u_error is set to EIO.
+ * In any case, update va11.va_state.
+ */
+vacmd(vcmd)
+{
+       (void) spl4();
+       (void) vaerror(DONE);           /* Wait for va to be ready */
+       switch (vcmd) {
+
+       case VPLOT:
+               /* Must turn on plot AND autostep modes. */
+               VAADDR->vacsh = VAPLOT;
+               if (vaerror(DONE))
+                       u.u_error = EIO;
+               VAADDR->vacsh = VAAUTOSTEP;
+               break;
+
+       case VPRINT:
+               VAADDR->vacsh = VAPRINT;
+               break;
+
+       case VPRINTPLOT:
+               VAADDR->vacsh = VAPRINTPLOT;
+               break;
+       }
+       va11.va_state =
+               (va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
+
+       if (vaerror(DONE))      /* Wait for command to complete. */
+               u.u_error = EIO;
+       (void) spl0();
+}
+
+vatimo()
+{
+       if (va11.va_open)
+               timeout(vatimo, (caddr_t)0, HZ/10);
+       vaintr(0);
+}
+
+/*ARGSUSED*/
+vaintr(dev)
+{
+       wakeup((caddr_t)&va11);
+}
+
+vaclose()
+{
+
+       va11.va_open = 0;
+       va11.va_busy = 0;
+       va11.va_state = 0;
+       va11.va_wc = 0;
+       va11.va_bufp = 0;
+       VAADDR->vacsl = 0;
+}
+
+#define        DELAY(N)        { register int d; d = N; while (--d > 0); }
+
+vareset()
+{
+
+       if (va11.va_open == 0)
+               return;
+       printf(" va");
+       VAADDR->vacsl = IENABLE;
+       if (va11.va_state & VPLOT) {
+               VAADDR->vacsh = VAPLOT;
+               DELAY(10000);
+               VAADDR->vacsh = VAAUTOSTEP;
+       } else if (va11.va_state & VPRINTPLOT)
+               VAADDR->vacsh = VPRINTPLOT;
+       else
+               VAADDR->vacsh = VAPRINTPLOT;
+       DELAY(10000);
+       if (va11.va_busy == 0)
+               return;
+       if (va_ubinfo) {
+               printf("<%d>", (va_ubinfo>>28)&0xf);
+               ubafree(va_ubinfo), va_ubinfo = 0;
+       }
+       /* This code belongs in vastart() */
+       va_ubinfo = ubasetup(va11.va_bp, vabdp);
+       va11.va_bufp = va_ubinfo & 0x3ffff;
+       va11.va_wc = (-va11.va_bp->b_bcount/2);
+       /* End badly placed code */
+       vastart();
+}
+#endif
diff --git a/usr/src/sys/dev/vp.c b/usr/src/sys/dev/vp.c
new file mode 100644 (file)
index 0000000..ce92d9f
--- /dev/null
@@ -0,0 +1,249 @@
+/*     vp.c    4.1     11/9/80 */
+
+#include "../conf/vp.h"
+#if NVP > 0
+/*
+ * Versatec matrix printer/plotter
+ * dma interface driver
+ */
+#include "../h/param.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/buf.h"
+#include "../h/systm.h"
+#include "../h/map.h"
+#include "../h/pte.h"
+#include "../h/uba.h"
+
+int    vpbdp = 1;
+
+unsigned minvpph();
+
+#define        VPPRI   (PZERO-1)
+
+struct vpregs {
+       short   plbcr;
+       short   fill;
+       short   prbcr;
+       unsigned short pbaddr;
+       short   plcsr;
+       short   plbuf;
+       short   prcsr;
+       unsigned short prbuf;
+};
+
+#define        ERROR   0100000
+#define        DTCINTR 040000
+#define        DMAACT  020000
+#define        READY   0200
+#define        IENABLE 0100
+#define        TERMCOM 040
+#define        FFCOM   020
+#define        EOTCOM  010
+#define        CLRCOM  04
+#define        RESET   02
+#define        SPP     01
+
+struct {
+       int     vp_state;
+       int     vp_count;
+       int     vp_bufp;
+       struct  buf *vp_bp;
+} vp11;
+int    vp_ubinfo;
+
+struct buf rvpbuf;
+
+#define        VISOPEN 01
+#define        CMNDS   076
+#define        MODE    0700
+#define        PRINT   0100
+#define        PLOT    0200
+#define        PPLOT   0400
+#define        VBUSY   01000
+
+vpopen()
+{
+
+       if (vp11.vp_state & VISOPEN) {
+               u.u_error = ENXIO;
+               return;
+       }
+       vp11.vp_state = VISOPEN | PRINT | CLRCOM | RESET;
+       vp11.vp_count = 0;
+       VPADDR->prcsr = IENABLE | DTCINTR;
+       vptimo();
+       while (vp11.vp_state & CMNDS) {
+               (void) spl4();
+               if (vperror(READY)) {
+                       vpclose();
+                       u.u_error = EIO;
+                       return;
+               }
+               vpstart();
+               (void) spl0();
+       }
+}
+
+vpstrategy(bp)
+       register struct buf *bp;
+{
+       register int e;
+
+       (void) spl4();
+       while (vp11.vp_state & VBUSY)
+               sleep((caddr_t)&vp11, VPPRI);
+       vp11.vp_state |= VBUSY;
+       vp11.vp_bp = bp;
+       vp_ubinfo = ubasetup(bp, vpbdp);
+       vp11.vp_bufp = vp_ubinfo & 0x3ffff;
+       if (e = vperror(READY))
+               goto brkout;
+       vp11.vp_count = bp->b_bcount;
+       vpstart();
+       while ((vp11.vp_state&PLOT ? VPADDR->plcsr : VPADDR->prcsr) & DMAACT)
+               sleep((caddr_t)&vp11, VPPRI);
+       vp11.vp_count = 0;
+       vp11.vp_bufp = 0;
+       if ((vp11.vp_state&MODE) == PPLOT)
+               vp11.vp_state = (vp11.vp_state &~ MODE) | PLOT;
+       (void) spl0();
+brkout:
+       ubafree(vp_ubinfo), vp_ubinfo = 0;
+       vp11.vp_state &= ~VBUSY;
+       vp11.vp_bp = 0;
+       iodone(bp);
+       if (e)
+               u.u_error = EIO;
+       wakeup((caddr_t)&vp11);
+}
+
+int    vpblock = 16384;
+
+unsigned
+minvpph(bp)
+struct buf *bp;
+{
+
+       if (bp->b_bcount > vpblock)
+               bp->b_bcount = vpblock;
+}
+
+/*ARGSUSED*/
+vpwrite(dev)
+{
+
+       physio(vpstrategy, &rvpbuf, dev, B_WRITE, minvpph);
+}
+
+vperror(bit)
+{
+       register int state, e;
+
+       state = vp11.vp_state & PLOT;
+       while ((e = (state ? VPADDR->plcsr : VPADDR->prcsr) & (bit|ERROR)) == 0)
+               sleep((caddr_t)&vp11, VPPRI);
+       return (e & ERROR);
+}
+
+vpstart()
+{
+       register short bit;
+
+       if (vp11.vp_count) {
+               VPADDR->pbaddr = vp11.vp_bufp;
+               if (vp11.vp_state & (PRINT|PPLOT))
+                       VPADDR->prbcr = vp11.vp_count;
+               else
+                       VPADDR->plbcr = vp11.vp_count;
+               return;
+       }
+       for (bit = 1; bit != 0; bit <<= 1)
+               if (vp11.vp_state&bit&CMNDS) {
+                       VPADDR->plcsr |= bit;
+                       vp11.vp_state &= ~bit;
+                       return;
+               }
+}
+
+/*ARGSUSED*/
+vpioctl(dev, cmd, addr, flag)
+       register caddr_t addr;
+{
+       register int m;
+
+       switch (cmd) {
+
+       case ('v'<<8)+0:
+               (void) suword(addr, vp11.vp_state);
+               return;
+
+       case ('v'<<8)+1:
+               m = fuword(addr);
+               if (m == -1) {
+                       u.u_error = EFAULT;
+                       return;
+               }
+               vp11.vp_state = (vp11.vp_state & ~MODE) | (m&(MODE|CMNDS));
+               break;
+
+       default:
+               u.u_error = ENOTTY;
+               return;
+       }
+       (void) spl4();
+       (void) vperror(READY);
+       if (vp11.vp_state&PPLOT)
+               VPADDR->plcsr |= SPP;
+       else
+               VPADDR->plcsr &= ~SPP;
+       vp11.vp_count = 0;
+       while (CMNDS & vp11.vp_state) {
+               (void) vperror(READY);
+               vpstart();
+       }
+       (void) spl0();
+}
+
+vptimo()
+{
+
+       if (vp11.vp_state&VISOPEN)
+               timeout(vptimo, (caddr_t)0, HZ/10);
+       vpintr(0);
+}
+
+/*ARGSUSED*/
+vpintr(dev)
+{
+
+       wakeup((caddr_t)&vp11);
+}
+
+vpclose()
+{
+
+       vp11.vp_state = 0;
+       vp11.vp_count = 0;
+       vp11.vp_bufp = 0;
+       VPADDR->plcsr = 0;
+}
+
+vpreset()
+{
+
+       if ((vp11.vp_state & VISOPEN) == 0)
+               return;
+       printf(" vp");
+       VPADDR->prcsr = IENABLE | DTCINTR;
+       if ((vp11.vp_state & VBUSY) == 0)
+               return;
+       if (vp_ubinfo) {
+               printf("<%d>", (vp_ubinfo>>28)&0xf);
+               ubafree(vp_ubinfo), vp_ubinfo = 0;
+       }
+       vp11.vp_bufp = vp_ubinfo & 0x3ffff;
+       vp11.vp_count = vp11.vp_bp->b_bcount;
+       vpstart();
+}
+#endif