../conf/*.h
[unix-history] / usr / src / sys / vax / uba / up.c
index ac04685..c244ef0 100644 (file)
@@ -1,15 +1,19 @@
-/*     %H%     3.16    %G%     */
+/*     up.c    3.26    %G%     */
 
 
+#include "../conf/up.h"
 /*
 /*
- * Emulex UNIBUS disk driver with overlapped seeks and ECC recovery.
+ * UNIBUS disk driver with overlapped seeks and ECC recovery.
  *
  *
- * NB: This driver works reliably only on an SC-11B controller with
- *     rev. level at least J (in particular rev. level H will not work well).
- *     If you have an older controller you may be able to get by if you
- *             #define OLDUCODE
- *     which implements larger delays for slow ucode.
+ * This driver works marginally on an Emulex SC-11B controller with rev
+ * level J microcode, defining:
+ *     int     olducode = 1;
+ * to force CPU stalling delays.
  *
  *
- * Controller switch settings:
+ * It has worked with no delays and no problems on a prototype
+ * SC-21 controller.  Emulex intends to upgrade all SC-11s on VAXes to SC-21s.
+ * You should get a SC-21 to replace any SC-11 on a VAX.
+ *
+ * SC-11B Controller switch settings:
  *     SW1-1   5/19 surfaces   (off, 19 surfaces on Ampex 9300)
  *     SW1-2   chksum enable   (off, checksum disabled)
  *     SW1-3   volume select   (off, 815 cylinders)
  *     SW1-1   5/19 surfaces   (off, 19 surfaces on Ampex 9300)
  *     SW1-2   chksum enable   (off, checksum disabled)
  *     SW1-3   volume select   (off, 815 cylinders)
 #include "../h/dir.h"
 #include "../h/user.h"
 #include "../h/map.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/mba.h"
 #include "../h/mtpr.h"
-#include "../h/pte.h"
 #include "../h/uba.h"
 #include "../h/vm.h"
 
 #include "../h/uba.h"
 #include "../h/vm.h"
 
-/*
- * Define number of drives, and range of sampling information to be used.
- *
- * Normally, DK_N .. DK_N+NUP-1 gather individual drive stats,
- * and DK_N+NUP gathers controller transferring stats.
- *
- * If DK_N+NUP > DK_NMAX, then transfer stats are divided per drive.
- * If DK_NMAX is yet smaller, some drives are not monitored.
- */
-#define        DK_N    2
-#define        DK_NMAX 3
-
 #define        ushort  unsigned short
 
 struct device
 #define        ushort  unsigned short
 
 struct device
@@ -90,10 +82,6 @@ int  upsoftas;
  */
 int    upseek;
 
  */
 int    upseek;
 
-#define        UPADDR  ((struct device *)(UBA0_DEV + 0176700))
-
-#define        NUP     2               /* Number of drives this installation */
-
 #define        NSECT   32
 #define        NTRAC   19
 
 #define        NSECT   32
 #define        NTRAC   19
 
@@ -193,7 +181,7 @@ struct      buf     rupbuf;                 /* Buffer for raw i/o */
 /* Other bits of upcs1 */
 #define        IE      0100            /* Controller wide interrupt enable */
 #define        TRE     040000          /* Transfer error */
 /* Other bits of upcs1 */
 #define        IE      0100            /* Controller wide interrupt enable */
 #define        TRE     040000          /* Transfer error */
-#define        RDY     020             /* Transfer terminated */
+#define        RDY     0200            /* Transfer terminated */
 
 /* Drive status bits of upds */
 #define        PIP     020000          /* Positioning in progress */
 
 /* Drive status bits of upds */
 #define        PIP     020000          /* Positioning in progress */
@@ -223,14 +211,12 @@ int       up_ubinfo;              /* Information about UBA usage saved here */
  * like PRESET and DCLR.  The following variables control the delay
  * DELAY(n) is approximately n usec.
  */
  * like PRESET and DCLR.  The following variables control the delay
  * DELAY(n) is approximately n usec.
  */
+int    olducode = 1;
 int    idelay = 500;           /* Delay after PRESET or DCLR */
 int    idelay = 500;           /* Delay after PRESET or DCLR */
-#ifdef OLDUCODE
-int    sdelay = 150;           /* Delay after selecting drive in upcs2 */
-int    rdelay = 100;           /* Delay after SEARCH */
-int    asdel = 100;            /* Delay after clearing bit in upas */
-#else
-int    sdelay = 25;
-#endif
+int    osdelay = 150;          /* Old delay after selecting drive in upcs2 */
+int    ordelay = 100;          /* Old delay after SEARCH */
+int    oasdel = 100;           /* Old delay after clearing bit in upas */
+int    nsdelay = 25;
 
 #define        DELAY(N)                { register int d; d = N; while (--d > 0); }
  
 
 #define        DELAY(N)                { register int d; d = N; while (--d > 0); }
  
@@ -275,6 +261,8 @@ register struct buf *bp;
                iodone(bp);
                return;
        }
                iodone(bp);
                return;
        }
+       if (DK_N+unit <= DK_NMAX)
+               dk_mspw[DK_N+unit] = .0000020345;
        bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff;
        dp = &uputab[unit];
        (void) spl5();
        bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff;
        dp = &uputab[unit];
        (void) spl5();
@@ -341,7 +329,7 @@ register unit;
        dp->b_active = 1;
        if ((upaddr->upcs2 & 07) != unit) {
                upaddr->upcs2 = unit;
        dp->b_active = 1;
        if ((upaddr->upcs2 & 07) != unit) {
                upaddr->upcs2 = unit;
-               DELAY(sdelay);
+               DELAY(olducode ? osdelay : nsdelay);
                nwaitcs2++;
        } else
                neasycs2++;
                nwaitcs2++;
        } else
                neasycs2++;
@@ -398,11 +386,10 @@ search:
        unit += DK_N;
        if (unit <= DK_NMAX) {
                dk_busy |= 1<<unit;
        unit += DK_N;
        if (unit <= DK_NMAX) {
                dk_busy |= 1<<unit;
-               dk_numb[unit]++;
+               dk_seek[unit]++;
        }
        }
-#ifdef OLDUCODE
-       DELAY(rdelay);
-#endif
+       if (olducode)
+               DELAY(ordelay);
        goto out;
 
 done:
        goto out;
 
 done:
@@ -475,21 +462,26 @@ loop:
         * (Then on to any other ready drives.)
         */
        if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
         * (Then on to any other ready drives.)
         */
        if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
-               printf("!DPR || !MOL, unit %d, ds %o\n", dn, upaddr->upds);
-               uptab.b_active = 0;
-               uptab.b_errcnt = 0;
-               dp->b_actf = bp->av_forw;
-               dp->b_active = 0;
-               bp->b_flags |= B_ERROR;
-               iodone(bp);
-               ubafree(up_ubinfo), up_ubinfo = 0;      /* A funny place ... */
-               goto loop;
+               printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds);
+               if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
+                       printf("-- hard\n");
+                       uptab.b_active = 0;
+                       uptab.b_errcnt = 0;
+                       dp->b_actf = bp->av_forw;
+                       dp->b_active = 0;
+                       bp->b_flags |= B_ERROR;
+                       iodone(bp);
+                       /* A funny place to do this ... */
+                       ubafree(up_ubinfo), up_ubinfo = 0;
+                       goto loop;
+               }
+               printf("-- came back\n");
        }
        /*
         * If this is a retry, then with the 16'th retry we
         * begin to try offsetting the heads to recover the data.
         */
        }
        /*
         * If this is a retry, then with the 16'th retry we
         * begin to try offsetting the heads to recover the data.
         */
-       if (uptab.b_errcnt >= 16) {
+       if (uptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
                upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22;
                upaddr->upcs1 = IE|OFFSET|GO;
                DELAY(idelay);
                upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22;
                upaddr->upcs1 = IE|OFFSET|GO;
                DELAY(idelay);
@@ -519,11 +511,9 @@ loop:
         * (if there is room for that).
         */
        unit = dn+DK_N;
         * (if there is room for that).
         */
        unit = dn+DK_N;
-       if (NUP+DK_N == DK_NMAX)
-               unit = NUP+DK_N;
        if (unit <= DK_NMAX) {
                dk_busy |= 1<<unit;
        if (unit <= DK_NMAX) {
                dk_busy |= 1<<unit;
-               dk_numb[unit]++;
+               dk_xfer[unit]++;
                dk_wds[unit] += bp->b_bcount>>6;
        }
        return (1);
                dk_wds[unit] += bp->b_bcount>>6;
        }
        return (1);
@@ -547,9 +537,7 @@ upintr()
        int oupsoftas;
        int needie = 1;
 
        int oupsoftas;
        int needie = 1;
 
-#ifdef OLDUCODE
        (void) spl6();
        (void) spl6();
-#endif
        up_wticks = 0;
        if (uptab.b_active) {
                /*
        up_wticks = 0;
        if (uptab.b_active) {
                /*
@@ -564,23 +552,21 @@ upintr()
                            uputab[0].b_active, uputab[1].b_active);
                }
                /*
                            uputab[0].b_active, uputab[1].b_active);
                }
                /*
-                * Mark controller or drive not busy, and check for an
+                * Mark drive not busy, and check for an
                 * error condition which may have resulted from the transfer.
                 */
                dp = uptab.b_actf;
                bp = dp->b_actf;
                unit = dkunit(bp);
                 * error condition which may have resulted from the transfer.
                 */
                dp = uptab.b_actf;
                bp = dp->b_actf;
                unit = dkunit(bp);
-               if (DK_N+NUP == DK_NMAX)
-                       dk_busy &= ~(1<<(DK_N+NUP));
-               else if (DK_N+unit <= DK_NMAX)
+               if (DK_N+unit <= DK_NMAX)
                        dk_busy &= ~(1<<(DK_N+unit));
                if ((upaddr->upcs2 & 07) != unit) {
                        upaddr->upcs2 = unit;
                        dk_busy &= ~(1<<(DK_N+unit));
                if ((upaddr->upcs2 & 07) != unit) {
                        upaddr->upcs2 = unit;
-                       DELAY(sdelay);
+                       DELAY(olducode ? osdelay : nsdelay);
                        nwaitcs2++;
                } else
                        neasycs2++;
                        nwaitcs2++;
                } else
                        neasycs2++;
-               if (upaddr->upds & ERR) {
+               if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) {
                        /*
                         * An error occurred, indeed.  Select this unit
                         * to get at the drive status (a SEARCH may have
                        /*
                         * An error occurred, indeed.  Select this unit
                         * to get at the drive status (a SEARCH may have
@@ -683,9 +669,8 @@ upintr()
                if ((as|oupsoftas) & (1<<unit)) {
                        if (as & (1<<unit)) {
                                upaddr->upas = 1<<unit;
                if ((as|oupsoftas) & (1<<unit)) {
                        if (as & (1<<unit)) {
                                upaddr->upas = 1<<unit;
-#ifdef OLDUCODE
-                               DELAY(asdel);
-#endif
+                               if (olducode)
+                                       DELAY(oasdel);
                        }
                        if (upustart(unit))
                                needie = 0;
                        }
                        if (upustart(unit))
                                needie = 0;
@@ -808,8 +793,6 @@ upreset()
        printf(" up");
        uptab.b_active = 0;
        uptab.b_actf = uptab.b_actl = 0;
        printf(" up");
        uptab.b_active = 0;
        uptab.b_actf = uptab.b_actl = 0;
-       if (DK_N+NUP == DK_NMAX)
-               dk_busy &= ~(1<<(DK_N+NUP));
        if (up_ubinfo) {
                printf("<%d>", (up_ubinfo>>28)&0xf);
                ubafree(up_ubinfo), up_ubinfo = 0;
        if (up_ubinfo) {
                printf("<%d>", (up_ubinfo>>28)&0xf);
                ubafree(up_ubinfo), up_ubinfo = 0;