BSD 4_4 release
[unix-history] / usr / src / sys / hp300 / dev / nhpib.c
index 8bf6547..2ccd0aa 100644 (file)
@@ -1,10 +1,36 @@
 /*
 /*
- * Copyright (c) 1982, 1990 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)nhpib.c     7.1 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nhpib.c     8.1 (Berkeley) 6/10/93
  */
 
 /*
  */
 
 /*
 #include "hpib.h"
 #if NHPIB > 0
 
 #include "hpib.h"
 #if NHPIB > 0
 
-#include "param.h"
-#include "systm.h"
-#include "buf.h"
-#include "device.h"
-#include "nhpibreg.h"
-#include "hpibvar.h"
-#include "dmavar.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+
+#include <hp/dev/device.h>
+#include <hp300/dev/nhpibreg.h>
+#include <hp300/dev/hpibvar.h>
+#include <hp300/dev/dmavar.h>
 
 nhpibtype(hc)
        register struct hp_ctlr *hc;
 
 nhpibtype(hc)
        register struct hp_ctlr *hc;
@@ -27,7 +54,7 @@ nhpibtype(hc)
        register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
        register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
 
        register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
        register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
 
-       if ((int)hc->hp_addr == internalhpib) {
+       if (hc->hp_addr == internalhpib) {
                hs->sc_type = HPIBA;
                hs->sc_ba = HPIBA_BA;
                hc->hp_ipl = HPIBA_IPL;
                hs->sc_type = HPIBA;
                hs->sc_ba = HPIBA_BA;
                hc->hp_ipl = HPIBA_IPL;
@@ -78,85 +105,98 @@ nhpibifc(hd)
        hd->hpib_acr = AUX_SSRE;
 }
 
        hd->hpib_acr = AUX_SSRE;
 }
 
-nhpibsend(unit, slave, sec, addr, cnt)
+nhpibsend(unit, slave, sec, addr, origcnt)
        register char *addr;
        register char *addr;
-       register int cnt;
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
-       register int origcnt = cnt;
+       register int cnt = origcnt;
 
        hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
        hd->hpib_acr = AUX_TCA;
        hd->hpib_data = C_UNL;
 
        hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
        hd->hpib_acr = AUX_TCA;
        hd->hpib_data = C_UNL;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto senderror;
        hd->hpib_data = C_TAG + hs->sc_ba;
        hd->hpib_acr = AUX_STON;
        hd->hpib_data = C_TAG + hs->sc_ba;
        hd->hpib_acr = AUX_STON;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto senderror;
        hd->hpib_data = C_LAG + slave;
        hd->hpib_data = C_LAG + slave;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto senderror;
        if (sec != -1) {
                hd->hpib_data = C_SCG + sec;
        if (sec != -1) {
                hd->hpib_data = C_SCG + sec;
-               nhpibowait(hd);
+               if (nhpibwait(hd, MIS_BO))
+                       goto senderror;
        }
        hd->hpib_acr = AUX_GTS;
        if (cnt) {
        }
        hd->hpib_acr = AUX_GTS;
        if (cnt) {
-               while (--cnt) {
+               while (--cnt > 0) {
                        hd->hpib_data = *addr++;
                        hd->hpib_data = *addr++;
-                       if (nhpibowait(hd) < 0) {
-                               nhpibifc(hd);
-                               cnt++;
-                               goto out;
-                       }
+                       if (nhpibwait(hd, MIS_BO))
+                               goto senderror;
                }
                hd->hpib_acr = AUX_EOI;
                hd->hpib_data = *addr;
                }
                hd->hpib_acr = AUX_EOI;
                hd->hpib_data = *addr;
-               if (nhpibowait(hd) < 0) {
-                       nhpibifc(hd);
-                       cnt++;
-               }
-               else
-                       hd->hpib_acr = AUX_TCA;
+               if (nhpibwait(hd, MIS_BO))
+                       goto senderror;
+               hd->hpib_acr = AUX_TCA;
+#if 0
+               /*
+                * May be causing 345 disks to hang due to interference
+                * with PPOLL mechanism.
+                */
+               hd->hpib_data = C_UNL;
+               (void) nhpibwait(hd, MIS_BO);
+#endif
        }
        }
-out:
-       return(origcnt - cnt);
+       return(origcnt);
+senderror:
+       nhpibifc(hd);
+       return(origcnt - cnt - 1);
 }
 
 }
 
-nhpibrecv(unit, slave, sec, addr, cnt)
+nhpibrecv(unit, slave, sec, addr, origcnt)
        register char *addr;
        register char *addr;
-       register int cnt;
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
-       register int origcnt = cnt;
+       register int cnt = origcnt;
 
        hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
        hd->hpib_acr = AUX_TCA;
        hd->hpib_data = C_UNL;
 
        hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
        hd->hpib_acr = AUX_TCA;
        hd->hpib_data = C_UNL;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto recverror;
        hd->hpib_data = C_LAG + hs->sc_ba;
        hd->hpib_acr = AUX_SLON;
        hd->hpib_data = C_LAG + hs->sc_ba;
        hd->hpib_acr = AUX_SLON;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto recverror;
        hd->hpib_data = C_TAG + slave;
        hd->hpib_data = C_TAG + slave;
-       nhpibowait(hd);
+       if (nhpibwait(hd, MIS_BO))
+               goto recverror;
        if (sec != -1) {
                hd->hpib_data = C_SCG + sec;
        if (sec != -1) {
                hd->hpib_data = C_SCG + sec;
-               nhpibowait(hd);
+               if (nhpibwait(hd, MIS_BO))
+                       goto recverror;
        }
        hd->hpib_acr = AUX_RHDF;
        hd->hpib_acr = AUX_GTS;
        if (cnt) {
                while (--cnt >= 0) {
        }
        hd->hpib_acr = AUX_RHDF;
        hd->hpib_acr = AUX_GTS;
        if (cnt) {
                while (--cnt >= 0) {
-                       if (nhpibiwait(hd) < 0) {
-                               nhpibifc(hd);
-                               break;
-                       }
+                       if (nhpibwait(hd, MIS_BI))
+                               goto recvbyteserror;
                        *addr++ = hd->hpib_data;
                }
                        *addr++ = hd->hpib_data;
                }
-               cnt++;
                hd->hpib_acr = AUX_TCA;
                hd->hpib_acr = AUX_TCA;
+               hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
+               (void) nhpibwait(hd, MIS_BO);
        }
        }
-       return(origcnt - cnt);
+       return(origcnt);
+recverror:
+       nhpibifc(hd);
+recvbyteserror:
+       return(origcnt - cnt - 1);
 }
 
 nhpibgo(unit, slave, sec, addr, count, rw)
 }
 
 nhpibgo(unit, slave, sec, addr, count, rw)
@@ -183,19 +223,17 @@ nhpibgo(unit, slave, sec, addr, count, rw)
                dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
                nhpibrecv(unit, slave, sec, 0, 0);
                hd->hpib_mim = MIS_END;
                dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
                nhpibrecv(unit, slave, sec, 0, 0);
                hd->hpib_mim = MIS_END;
-       }
-       else {
-               if (count == 1) {
-                       hs->sc_curcnt = 1;
-                       dmago(hs->sc_dq.dq_ctlr, addr, 1, DMAGO_BYTE);
-                       nhpibsend(unit, slave, sec, 0, 0);
-                       hd->hpib_acr = AUX_EOI;
-               }
-               else {
-                       hs->sc_curcnt = count - 1;
-                       dmago(hs->sc_dq.dq_ctlr, addr, count - 1, DMAGO_BYTE);
-                       nhpibsend(unit, slave, sec, 0, 0);
+       } else {
+               hd->hpib_mim = 0;
+               if (count < hpibdmathresh) {
+                       hs->sc_curcnt = count;
+                       nhpibsend(unit, slave, sec, addr, count);
+                       nhpibdone(unit);
+                       return;
                }
                }
+               hs->sc_curcnt = --count;
+               dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
+               nhpibsend(unit, slave, sec, 0, 0);
        }
        hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
 }
        }
        hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
 }
@@ -211,19 +249,19 @@ nhpibdone(unit)
        cnt = hs->sc_curcnt;
        hs->sc_addr += cnt;
        hs->sc_count -= cnt;
        cnt = hs->sc_curcnt;
        hs->sc_addr += cnt;
        hs->sc_count -= cnt;
-       if (hs->sc_flags & HPIBF_READ) {
-               hs->sc_flags |= HPIBF_DONE;
-               hd->hpib_ie = IDS_IE;
-       } else {
+       hs->sc_flags |= HPIBF_DONE;
+       hd->hpib_ie = IDS_IE;
+       if ((hs->sc_flags & HPIBF_READ) == 0) {
                if (hs->sc_count == 1) {
                if (hs->sc_count == 1) {
-                       hs->sc_curcnt = 1;
+                       (void) nhpibwait(hd, MIS_BO);
                        hd->hpib_acr = AUX_EOI;
                        hd->hpib_acr = AUX_EOI;
-                       dmago(hs->sc_dq.dq_ctlr, hs->sc_addr, 1, DMAGO_BYTE);
-                       return;
+                       hd->hpib_data = *hs->sc_addr;
+                       hd->hpib_mim = MIS_BO;
                }
                }
-               hs->sc_flags |= HPIBF_DONE;
-               hd->hpib_ie = IDS_IE;
-               hd->hpib_mim = MIS_BO;
+#ifdef DEBUG
+               else if (hs->sc_count)
+                       panic("nhpibdone");
+#endif
        }
 }
 
        }
 }
 
@@ -232,7 +270,7 @@ nhpibintr(unit)
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
 {
        register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
-       register struct devqueue *dq = hs->sc_sq.dq_forw;
+       register struct devqueue *dq;
        register int stat0;
        int stat1;
 
        register int stat0;
        int stat1;
 
@@ -244,6 +282,7 @@ nhpibintr(unit)
                return(0);
        stat0 = hd->hpib_mis;
        stat1 = hd->hpib_lis;
                return(0);
        stat0 = hd->hpib_mis;
        stat1 = hd->hpib_lis;
+       dq = hs->sc_sq.dq_forw;
        if (hs->sc_flags & HPIBF_IO) {
                hd->hpib_mim = 0;
                if ((hs->sc_flags & HPIBF_DONE) == 0)
        if (hs->sc_flags & HPIBF_IO) {
                hd->hpib_mim = 0;
                if ((hs->sc_flags & HPIBF_DONE) == 0)
@@ -252,28 +291,29 @@ nhpibintr(unit)
                hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
                dmafree(&hs->sc_dq);
                (dq->dq_driver->d_intr)(dq->dq_unit);
                hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
                dmafree(&hs->sc_dq);
                (dq->dq_driver->d_intr)(dq->dq_unit);
-               return(1);
-       }
-       if (hs->sc_flags & HPIBF_PPOLL) {
+       } else if (hs->sc_flags & HPIBF_PPOLL) {
                hd->hpib_mim = 0;
                stat0 = nhpibppoll(unit);
                if (stat0 & (0x80 >> dq->dq_slave)) {
                        hs->sc_flags &= ~HPIBF_PPOLL;
                        (dq->dq_driver->d_intr)(dq->dq_unit);
                }
                hd->hpib_mim = 0;
                stat0 = nhpibppoll(unit);
                if (stat0 & (0x80 >> dq->dq_slave)) {
                        hs->sc_flags &= ~HPIBF_PPOLL;
                        (dq->dq_driver->d_intr)(dq->dq_unit);
                }
-               return(1);
+#ifdef DEBUG
+               else
+                       printf("hpib%d: PPOLL intr bad status %x\n",
+                              unit, stat0);
+#endif
        }
        return(1);
 }
 
 nhpibppoll(unit)
        }
        return(1);
 }
 
 nhpibppoll(unit)
-       register int unit;
+       int unit;
 {
 {
-       register struct hpib_softc *hs = &hpib_softc[unit];
        register struct nhpibdevice *hd;
        register int ppoll;
 
        register struct nhpibdevice *hd;
        register int ppoll;
 
-       hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
+       hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
        hd->hpib_acr = AUX_SPP;
        DELAY(25);
        ppoll = hd->hpib_cpt;
        hd->hpib_acr = AUX_SPP;
        DELAY(25);
        ppoll = hd->hpib_cpt;
@@ -281,44 +321,37 @@ nhpibppoll(unit)
        return(ppoll);
 }
 
        return(ppoll);
 }
 
-nhpibowait(hd)
+nhpibwait(hd, x)
        register struct nhpibdevice *hd;
 {
        register struct nhpibdevice *hd;
 {
-       extern int hpibtimeout;
        register int timo = hpibtimeout;
 
        register int timo = hpibtimeout;
 
-       while ((hd->hpib_mis & MIS_BO) == 0 && --timo)
-               ;
+       while ((hd->hpib_mis & x) == 0 && --timo)
+               DELAY(1);
        if (timo == 0)
                return(-1);
        return(0);
 }
 
        if (timo == 0)
                return(-1);
        return(0);
 }
 
-nhpibiwait(hd)
-       register struct nhpibdevice *hd;
+void
+nhpibppwatch(arg)
+       void *arg;
 {
 {
-       extern int hpibtimeout;
-       register int timo = hpibtimeout;
-
-       while ((hd->hpib_mis & MIS_BI) == 0 && --timo)
-               ;
-       if (timo == 0)
-               return(-1);
-       return(0);
-}
-
-nhpibppwatch(unit)
+       register struct hpib_softc *hs;
        register int unit;
        register int unit;
-{
-       register struct hpib_softc *hs = &hpib_softc[unit];
-       register struct devqueue *dq = hs->sc_sq.dq_forw;
-       register int slave = 0x80 >> dq->dq_slave;
+       extern int cold;
 
 
+       unit = (int)arg;
+       hs = &hpib_softc[unit];
        if ((hs->sc_flags & HPIBF_PPOLL) == 0)
                return;
        if ((hs->sc_flags & HPIBF_PPOLL) == 0)
                return;
-       if (nhpibppoll(unit) & slave)
+again:
+       if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
                        ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
                        ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
+       else if (cold)
+               /* timeouts not working yet */
+               goto again;
        else
        else
-               timeout(nhpibppwatch, unit, 1);
+               timeout(nhpibppwatch, (void *)unit, 1);
 }
 #endif
 }
 #endif