remove HPER1_UNS from hard errors until figure out why it happens
[unix-history] / usr / src / sys / vax / mba / mba.c
index 51cc80c..f908daa 100644 (file)
@@ -1,10 +1,9 @@
-/*     mba.c   4.14    81/03/06        */
+/*     mba.c   4.20    81/05/09        */
 
 #include "mba.h"
 #if NMBA > 0
 /*
 
 #include "mba.h"
 #if NMBA > 0
 /*
- * Massbus driver; arbitrates massbus using device
- * driver routines.  This module provides common functions.
+ * Massbus driver, arbitrates a massbus among attached devices.
  */
 #include "../h/param.h"
 #include "../h/systm.h"
  */
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/proc.h"
 #include "../h/map.h"
 #include "../h/pte.h"
 #include "../h/proc.h"
 #include "../h/map.h"
 #include "../h/pte.h"
-#include "../h/mba.h"
+#include "../h/mbareg.h"
+#include "../h/mbavar.h"
 #include "../h/mtpr.h"
 #include "../h/vm.h"
 
 #include "../h/mtpr.h"
 #include "../h/vm.h"
 
-char   mbasr_bits[] = MBASR_BITS;
+char   mbsr_bits[] = MBSR_BITS;
 /*
  * Start activity on a massbus device.
 /*
  * Start activity on a massbus device.
- * We are given the device's mba_info structure and activate
+ * We are given the device's mba_device structure and activate
  * the device via the unit start routine.  The unit start
  * routine may indicate that it is finished (e.g. if the operation
  * was a ``sense'' on a tape drive), that the (multi-ported) unit
  * the device via the unit start routine.  The unit start
  * routine may indicate that it is finished (e.g. if the operation
  * was a ``sense'' on a tape drive), that the (multi-ported) unit
@@ -32,9 +32,8 @@ char  mbasr_bits[] = MBASR_BITS;
  * set up a data transfer operation and we should start the massbus adaptor.
  */
 mbustart(mi)
  * set up a data transfer operation and we should start the massbus adaptor.
  */
 mbustart(mi)
-       register struct mba_info *mi;
+       register struct mba_device *mi;
 {
 {
-       register struct mba_drv *mdp;   /* drive registers */
        register struct buf *bp;        /* i/o operation at head of queue */
        register struct mba_hd *mhp;    /* header for mba device is on */
 
        register struct buf *bp;        /* i/o operation at head of queue */
        register struct mba_hd *mhp;    /* header for mba device is on */
 
@@ -45,7 +44,6 @@ loop:
        bp = mi->mi_tab.b_actf;
        if (bp == NULL)
                return;
        bp = mi->mi_tab.b_actf;
        if (bp == NULL)
                return;
-       mdp = mi->mi_drv;
        /*
         * Let the drivers unit start routine have at it
         * and then process the request further, per its instructions.
        /*
         * Let the drivers unit start routine have at it
         * and then process the request further, per its instructions.
@@ -54,13 +52,14 @@ loop:
 
        case MBU_NEXT:          /* request is complete (e.g. ``sense'') */
                mi->mi_tab.b_active = 0;
 
        case MBU_NEXT:          /* request is complete (e.g. ``sense'') */
                mi->mi_tab.b_active = 0;
+               mi->mi_tab.b_errcnt = 0;
                mi->mi_tab.b_actf = bp->av_forw;
                iodone(bp);
                goto loop;
 
        case MBU_DODATA:        /* all ready to do data transfer */
                /*
                mi->mi_tab.b_actf = bp->av_forw;
                iodone(bp);
                goto loop;
 
        case MBU_DODATA:        /* all ready to do data transfer */
                /*
-                * Queue the device mba_info structure on the massbus
+                * Queue the device mba_device structure on the massbus
                 * mba_hd structure for processing as soon as the
                 * data path is available.
                 */
                 * mba_hd structure for processing as soon as the
                 * data path is available.
                 */
@@ -86,8 +85,10 @@ loop:
                 * Mark device busy during non-data transfer
                 * and count this as a ``seek'' on the device.
                 */
                 * Mark device busy during non-data transfer
                 * and count this as a ``seek'' on the device.
                 */
-               if (mi->mi_dk >= 0)
+               if (mi->mi_dk >= 0) {
                        dk_seek[mi->mi_dk]++;
                        dk_seek[mi->mi_dk]++;
+                       dk_busy |= (1 << mi->mi_dk);
+               }
                mi->mi_tab.b_active = 1;
                return;
 
                mi->mi_tab.b_active = 1;
                return;
 
@@ -114,16 +115,18 @@ loop:
 mbstart(mhp)
        register struct mba_hd *mhp;
 {
 mbstart(mhp)
        register struct mba_hd *mhp;
 {
-       register struct mba_info *mi;
+       register struct mba_device *mi;
        struct buf *bp;
        register struct mba_regs *mbp;
        struct buf *bp;
        register struct mba_regs *mbp;
+       register int com;
 
 loop:
        /*
         * Look for an operation at the front of the queue.
         */
 
 loop:
        /*
         * Look for an operation at the front of the queue.
         */
-       if ((mi = mhp->mh_actf) == NULL)
+       if ((mi = mhp->mh_actf) == NULL) {
                return;
                return;
+       }
        if ((bp = mi->mi_tab.b_actf) == NULL) {
                mhp->mh_actf = mi->mi_forw;
                goto loop;
        if ((bp = mi->mi_tab.b_actf) == NULL) {
                mhp->mh_actf = mi->mi_forw;
                goto loop;
@@ -132,8 +135,9 @@ loop:
         * If this device isn't present and on-line, then
         * we screwed up, and can't really do the operation.
         */
         * If this device isn't present and on-line, then
         * we screwed up, and can't really do the operation.
         */
-       if ((mi->mi_drv->mbd_ds & (MBD_DPR|MBD_MOL)) != (MBD_DPR|MBD_MOL)) {
-               printf("%c%d: not ready\n", mi->mi_name, dkunit(bp));
+       if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) {
+               printf("%s%d: not ready\n", mi->mi_driver->md_dname,
+                   dkunit(bp));
                mi->mi_tab.b_actf = bp->av_forw;
                mi->mi_tab.b_errcnt = 0;
                mi->mi_tab.b_active = 0;
                mi->mi_tab.b_actf = bp->av_forw;
                mi->mi_tab.b_errcnt = 0;
                mi->mi_tab.b_active = 0;
@@ -148,8 +152,12 @@ loop:
         * on disks).
         */
        mhp->mh_active = 1;
         * on disks).
         */
        mhp->mh_active = 1;
-       if (mi->mi_driver->md_start)
-               (*mi->mi_driver->md_start)(mi);
+       if (mi->mi_driver->md_start) {
+               if ((com = (*mi->mi_driver->md_start)(mi)) == 0)
+                       com = (bp->b_flags & B_READ) ?
+                           MB_RCOM|MB_GO : MB_WCOM|MB_GO;
+       } else
+               com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO;
 
        /*
         * Setup the massbus control and map registers and start
 
        /*
         * Setup the massbus control and map registers and start
@@ -159,8 +167,7 @@ loop:
        mbp->mba_sr = -1;       /* conservative */
        mbp->mba_var = mbasetup(mi);
        mbp->mba_bcr = -bp->b_bcount;
        mbp->mba_sr = -1;       /* conservative */
        mbp->mba_var = mbasetup(mi);
        mbp->mba_bcr = -bp->b_bcount;
-       mi->mi_drv->mbd_cs1 =
-           (bp->b_flags & B_READ) ? MBD_RCOM|MBD_GO : MBD_WCOM|MBD_GO;
+       mi->mi_drv->mbd_cs1 = com;
        if (mi->mi_dk >= 0) {
                dk_busy |= 1 << mi->mi_dk;
                dk_xfer[mi->mi_dk]++;
        if (mi->mi_dk >= 0) {
                dk_busy |= 1 << mi->mi_dk;
                dk_xfer[mi->mi_dk]++;
@@ -177,35 +184,28 @@ mbintr(mbanum)
 {
        register struct mba_hd *mhp = &mba_hd[mbanum];
        register struct mba_regs *mbp = mhp->mh_mba;
 {
        register struct mba_hd *mhp = &mba_hd[mbanum];
        register struct mba_regs *mbp = mhp->mh_mba;
-       register struct mba_info *mi;
+       register struct mba_device *mi;
        register struct buf *bp;
        register int drive;
        register struct buf *bp;
        register int drive;
-       int mbastat, as;
+       int mbasr, as;
        
        /*
         * Read out the massbus status register
         * and attention status register and clear
         * the bits in same by writing them back.
         */
        
        /*
         * Read out the massbus status register
         * and attention status register and clear
         * the bits in same by writing them back.
         */
-       mbastat = mbp->mba_sr;
-       mbp->mba_sr = mbastat;
+       mbasr = mbp->mba_sr;
+       mbp->mba_sr = mbasr;
 #if VAX750
 #if VAX750
-       if (mbastat&MBS_CBHUNG) {
+       if (mbasr&MBSR_CBHUNG) {
                printf("mba%d: control bus hung\n", mbanum);
                panic("cbhung");
        }
 #endif
        /* note: the mbd_as register is shared between drives */
                printf("mba%d: control bus hung\n", mbanum);
                panic("cbhung");
        }
 #endif
        /* note: the mbd_as register is shared between drives */
-       as = mbp->mba_drv[0].mbd_as;
+       as = mbp->mba_drv[0].mbd_as & 0xff;
        mbp->mba_drv[0].mbd_as = as;
 
        mbp->mba_drv[0].mbd_as = as;
 
-       /*
-        * Disable interrupts from the massbus adapter
-        * for the duration of the operation of the massbus
-        * driver, so that spurious interrupts won't be generated.
-        */
-       mbp->mba_cr &= ~MBAIE;
-
        /*
         * If the mba was active, process the data transfer
         * complete interrupt; otherwise just process units which
        /*
         * If the mba was active, process the data transfer
         * complete interrupt; otherwise just process units which
@@ -214,14 +214,15 @@ mbintr(mbanum)
        if (mhp->mh_active) {
                /*
                 * Clear attention status for drive whose data
        if (mhp->mh_active) {
                /*
                 * Clear attention status for drive whose data
-                * transfer completed, and give the dtint driver
+                * transfer related operation completed,
+                * and give the dtint driver
                 * routine a chance to say what is next.
                 */
                mi = mhp->mh_actf;
                as &= ~(1 << mi->mi_drive);
                dk_busy &= ~(1 << mi->mi_dk);
                bp = mi->mi_tab.b_actf;
                 * routine a chance to say what is next.
                 */
                mi = mhp->mh_actf;
                as &= ~(1 << mi->mi_drive);
                dk_busy &= ~(1 << mi->mi_dk);
                bp = mi->mi_tab.b_actf;
-               switch((*mi->mi_driver->md_dtint)(mi, mbastat)) {
+               switch ((*mi->mi_driver->md_dtint)(mi, mbasr)) {
 
                case MBD_DONE:          /* all done, for better or worse */
                        /*
 
                case MBD_DONE:          /* all done, for better or worse */
                        /*
@@ -255,69 +256,61 @@ mbintr(mbanum)
                        panic("mbintr");
                }
        }
                        panic("mbintr");
                }
        }
-doattn:
        /*
         * Service drives which require attention
         * after non-data-transfer operations.
         */
        /*
         * Service drives which require attention
         * after non-data-transfer operations.
         */
-       for (drive = 0; as && drive < 8; drive++)
-               if (as & (1 << drive)) {
-                       as &= ~(1 << drive);
-                       /*
-                        * Consistency check the implied attention,
-                        * to make sure the drive should have interrupted.
-                        */
-                       mi = mhp->mh_mbip[drive];
-                       if (mi == NULL || mi->mi_tab.b_active == 0 &&
-                           (mi->mi_tab.b_flags&B_BUSY) == 0 ||
-                           (bp = mi->mi_tab.b_actf) == NULL)
-                               continue;               /* unsolicited */
+       while (drive = ffs(as)) {
+               drive--;                /* was 1 origin */
+               as &= ~(1 << drive);
+               mi = mhp->mh_mbip[drive];
+               if (mi == NULL)
+                       continue;
+               /*
+                * If driver has a handler for non-data transfer
+                * interrupts, give it a chance to tell us what to do.
+                */
+               if (mi->mi_driver->md_ndint) {
+                       mi->mi_tab.b_active = 0;
+                       switch ((*mi->mi_driver->md_ndint)(mi)) {
+
+                       case MBN_DONE:          /* operation completed */
+                               mi->mi_tab.b_errcnt = 0;
+                               bp = mi->mi_tab.b_actf;
+                               mi->mi_tab.b_actf = bp->av_forw;
+                               iodone(bp);
+                               /* fall into common code */
+                       case MBN_RETRY:         /* operation continues */
+                               if (mi->mi_tab.b_actf)
+                                       mbustart(mi);
+                               break;
+                       case MBN_SKIP:          /* ignore unsol. interrupt */
+                               break;
+                       default:
+                               panic("mbintr");
+                       }
+               } else
                        /*
                        /*
-                        * If this interrupt wasn't a notification that
-                        * a dual ported drive is available, and if the
-                        * driver has a handler for non-data transfer
-                        * interrupts, give it a chance to tell us that
-                        * the operation needs to be redone
+                        * If there is no non-data transfer interrupt
+                        * routine, then we should just
+                        * restart the unit, leading to a mbstart() soon.
                         */
                         */
-                       if (mi->mi_driver->md_ndint &&
-                           (mi->mi_tab.b_flags&B_BUSY) == 0) {
-                               mi->mi_tab.b_active = 0;
-                               switch((*mi->mi_driver->md_ndint)(mi)) {
-
-                               case MBN_DONE:
-                                       /*
-                                        * Non-data transfer interrupt
-                                        * completed i/o request's processing.
-                                        */
-                                       mi->mi_tab.b_errcnt = 0;
-                                       mi->mi_tab.b_actf = bp->av_forw;
-                                       iodone(bp);
-                                       /* fall into... */
-                               case MBN_RETRY:
-                                       if (mi->mi_tab.b_actf)
-                                               mbustart(mi);
-                                       break;
-
-                               default:
-                                       panic("mbintr");
-                               }
-                       } else
-                               mbustart(mi);
-               }
+                       mbustart(mi);
+       }
        /*
         * If there is an operation available and
         * the massbus isn't active, get it going.
         */
        if (mhp->mh_actf && !mhp->mh_active)
                mbstart(mhp);
        /*
         * If there is an operation available and
         * the massbus isn't active, get it going.
         */
        if (mhp->mh_actf && !mhp->mh_active)
                mbstart(mhp);
-       mbp->mba_cr |= MBAIE;
+       /* THHHHATS all folks... */
 }
 
 /*
  * Setup the mapping registers for a transfer.
  */
 mbasetup(mi)
 }
 
 /*
  * Setup the mapping registers for a transfer.
  */
 mbasetup(mi)
-       register struct mba_info *mi;
+       register struct mba_device *mi;
 {
        register struct mba_regs *mbap = mi->mi_mba;
        struct buf *bp = mi->mi_tab.b_actf;
 {
        register struct mba_regs *mbap = mi->mi_mba;
        struct buf *bp = mi->mi_tab.b_actf;
@@ -360,11 +353,14 @@ mbasetup(mi)
        return (vaddr);
 }
 
        return (vaddr);
 }
 
+/*
+ * Init and interrupt enable a massbus adapter.
+ */
 mbainit(mp)
        struct mba_regs *mp;
 {
 
 mbainit(mp)
        struct mba_regs *mp;
 {
 
-       mp->mba_cr = MBAINIT;
-       mp->mba_cr = MBAIE;
+       mp->mba_cr = MBCR_INIT;
+       mp->mba_cr = MBCR_IE;
 }
 #endif
 }
 #endif