Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-2-0]: src/sys/arch/sgimips/hpc Pull up revisions 1.22-1.23 (reque...



details:   https://anonhg.NetBSD.org/src/rev/234162fa3208
branches:  netbsd-2-0
changeset: 564756:234162fa3208
user:      he <he%NetBSD.org@localhost>
date:      Wed Apr 06 17:16:03 2005 +0000

description:
Pull up revisions 1.22-1.23 (requested by rumble in ticket #1054):
  Fix the HPC1 transmit logic, which was previously very broken.

diffstat:

 sys/arch/sgimips/hpc/if_sq.c |  346 +++++++++++++++++++++++++++---------------
 1 files changed, 220 insertions(+), 126 deletions(-)

diffs (truncated from 550 to 300 lines):

diff -r dd22e33598cb -r 234162fa3208 sys/arch/sgimips/hpc/if_sq.c
--- a/sys/arch/sgimips/hpc/if_sq.c      Wed Apr 06 17:13:41 2005 +0000
+++ b/sys/arch/sgimips/hpc/if_sq.c      Wed Apr 06 17:16:03 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_sq.c,v 1.20.2.1 2005/04/06 17:12:07 he Exp $        */
+/*     $NetBSD: if_sq.c,v 1.20.2.2 2005/04/06 17:16:03 he Exp $        */
 
 /*
  * Copyright (c) 2001 Rafal K. Boni
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.20.2.1 2005/04/06 17:12:07 he Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.20.2.2 2005/04/06 17:16:03 he Exp $");
 
 #include "bpfilter.h"
 
@@ -113,46 +113,15 @@
 static int     sq_intr(void *);
 static int     sq_rxintr(struct sq_softc *);
 static int     sq_txintr(struct sq_softc *);
+static void    sq_txring_hpc1(struct sq_softc *);
+static void    sq_txring_hpc3(struct sq_softc *);
 static void    sq_reset(struct sq_softc *);
 static int     sq_add_rxbuf(struct sq_softc *, int);
 static void    sq_dump_buffer(u_int32_t addr, u_int32_t len);
+static void    sq_trace_dump(struct sq_softc *);
 
 static void    enaddr_aton(const char*, u_int8_t*);
 
-/* Actions */
-#define SQ_RESET               1
-#define SQ_ADD_TO_DMA          2
-#define SQ_START_DMA           3
-#define SQ_DONE_DMA            4
-#define SQ_RESTART_DMA         5
-#define SQ_TXINTR_ENTER                6
-#define SQ_TXINTR_EXIT         7
-#define SQ_TXINTR_BUSY         8
-
-struct sq_action_trace {
-       int action;
-       int bufno;
-       int status;
-       int freebuf;
-};
-
-#define SQ_TRACEBUF_SIZE       100
-int sq_trace_idx = 0;
-struct sq_action_trace sq_trace[SQ_TRACEBUF_SIZE];
-
-void sq_trace_dump(struct sq_softc* sc);
-
-#define SQ_TRACE(act, buf, stat, free) do {                            \
-       sq_trace[sq_trace_idx].action = (act);                          \
-       sq_trace[sq_trace_idx].bufno = (buf);                           \
-       sq_trace[sq_trace_idx].status = (stat);                         \
-       sq_trace[sq_trace_idx].freebuf = (free);                        \
-       if (++sq_trace_idx == SQ_TRACEBUF_SIZE) {                       \
-               memset(&sq_trace, 0, sizeof(sq_trace));                 \
-               sq_trace_idx = 0;                                       \
-       }                                                               \
-} while (0)
-
 CFATTACH_DECL(sq, sizeof(struct sq_softc),
     sq_match, sq_attach, NULL, NULL);
 
@@ -315,7 +284,7 @@
        if_attach(ifp);
        ether_ifattach(ifp, sc->sc_enaddr);
 
-       memset(&sq_trace, 0, sizeof(sq_trace));
+       memset(&sc->sq_trace, 0, sizeof(sc->sq_trace));
        /* Done! */
        return;
 
@@ -368,7 +337,7 @@
        sc->sc_nfreetx = SQ_NTXDESC;
        sc->sc_nexttx = sc->sc_prevtx = 0;
 
-       SQ_TRACE(SQ_RESET, 0, 0, sc->sc_nfreetx);
+       SQ_TRACE(SQ_RESET, sc, 0, 0);
 
        /* Set into 8003 mode, bank 0 to program ethernet address */
        bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, TXCMD_BANK0);
@@ -405,9 +374,9 @@
        /* Set up HPC ethernet DMA config */
        if (sc->hpc_regs->revision == 3) {
                reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch,
-                               sc->hpc_regs->enetr_dmacfg);
+                               HPC_ENETR_DMACFG);      
                bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
-                               sc->hpc_regs->enetr_dmacfg,
+                               HPC_ENETR_DMACFG,       
                                reg | ENETR_DMACFG_FIX_RXDC |
                                ENETR_DMACFG_FIX_INTR |
                                ENETR_DMACFG_FIX_EOP);
@@ -421,6 +390,14 @@
        bus_space_write_4(sc->sc_hpct, sc->sc_hpch, sc->hpc_regs->enetr_ctl,
                                       sc->hpc_regs->enetr_ctl_active);
 
+       /*
+        * Turn off delayed receive interrupts on HPC1.
+        * (see Hollywood HPC Specification 2.1.4.3)
+        */ 
+       if (sc->hpc_regs->revision != 3)
+               bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC1_ENET_INTDELAY,
+                   HPC1_ENET_INTDELAYVAL);
+
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
 
@@ -472,6 +449,8 @@
 {
        int s, error = 0;
 
+       SQ_TRACE(SQ_IOCTL, (struct sq_softc *)ifp->if_softc, 0, 0);
+
        s = splnet();
 
        error = ether_ioctl(ifp, cmd, data);
@@ -611,6 +590,8 @@
                 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
                 */
 
+               SQ_TRACE(SQ_ENQUEUE, sc, sc->sc_nexttx, 0);
+
                /* Sync the DMA map. */
                bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
                    BUS_DMASYNC_PREWRITE);
@@ -680,7 +661,6 @@
                /* Advance the tx pointer. */
                sc->sc_nfreetx -= dmamap->dm_nsegs;
                sc->sc_nexttx = nexttx;
-
        }
 
        /* All transmit descriptors used up, let upper layers know */
@@ -697,8 +677,9 @@
                 * last packet we enqueued, mark it as the last
                 * descriptor.
                 *
-                * HDD_CTL_EOPACKET && HDD_CTL_INTR cause an 
-                * interrupt.
+                * HDD_CTL_INTR will generate an interrupt on
+                * HPC1 by itself. HPC3 will not interrupt unless 
+                * HDD_CTL_EOPACKET is set as well.
                 */
                KASSERT(lasttx != -1);
                if (sc->hpc_regs->revision == 3) {
@@ -729,32 +710,52 @@
                                sc->hpc_regs->enetx_ctl);
 
                if ((status & sc->hpc_regs->enetx_ctl_active) != 0) {
-                       SQ_TRACE(SQ_ADD_TO_DMA, firsttx, status,
-                           sc->sc_nfreetx);
+                       SQ_TRACE(SQ_ADD_TO_DMA, sc, firsttx, status);
 
                        /* NB: hpc3_hdd_ctl is also hpc1_hdd_bufptr */
                        sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc3_hdd_ctl &=
                            ~HDD_CTL_EOCHAIN;
 
+                       if (sc->hpc_regs->revision != 3)
+                               sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc1_hdd_ctl
+                                   &= ~HPC1_HDD_CTL_INTR;
+
                        SQ_CDTXSYNC(sc, SQ_PREVTX(firsttx),  1,
                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-               } else {
-                       SQ_TRACE(SQ_START_DMA, firsttx, status, sc->sc_nfreetx);
+               } else if (sc->hpc_regs->revision == 3) { 
+                       SQ_TRACE(SQ_START_DMA, sc, firsttx, status);
 
                        bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
-                           sc->hpc_regs->enetx_ndbp, SQ_CDTXADDR(sc, firsttx));
-
-                       if (sc->hpc_regs->revision != 3) {
-                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
-                                 HPC1_ENETX_CFXBP, SQ_CDTXADDR(sc, firsttx));
-                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
-                                 HPC1_ENETX_CBP, SQ_CDTXADDR(sc, firsttx));
-                       }
+                           HPC_ENETX_NDBP, SQ_CDTXADDR(sc, firsttx));
 
                        /* Kick DMA channel into life */
                        bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
-                                         sc->hpc_regs->enetx_ctl,
-                                         sc->hpc_regs->enetx_ctl_active);
+                           HPC_ENETX_CTL, ENETX_CTL_ACTIVE); 
+               } else {
+                       /*
+                        * In the HPC1 case where transmit DMA is
+                        * inactive, we can either kick off if
+                        * the ring was previously empty, or call
+                        * our transmit interrupt handler to
+                        * figure out if the ring stopped short
+                        * and restart at the right place.
+                        */
+                       if (ofree == SQ_NTXDESC) {
+                               SQ_TRACE(SQ_START_DMA, sc, firsttx, status);
+
+                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+                                   HPC1_ENETX_NDBP, 
+                                   SQ_CDTXADDR(sc, firsttx));
+                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+                                   HPC1_ENETX_CFXBP, SQ_CDTXADDR(sc, firsttx));
+                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+                                   HPC1_ENETX_CBP, SQ_CDTXADDR(sc, firsttx));
+
+                               /* Kick DMA channel into life */
+                               bus_space_write_4(sc->sc_hpct, sc->sc_hpch,
+                                   HPC1_ENETX_CTL, HPC1_ENETX_CTL_ACTIVE); 
+                       } else
+                               sq_txring_hpc1(sc);
                }
 
                /* Set a watchdog timer in case the chip flakes out. */
@@ -801,23 +802,39 @@
 
        sq_trace_dump(sc);
 
-       memset(&sq_trace, 0, sizeof(sq_trace));
-       sq_trace_idx = 0;
+       memset(&sc->sq_trace, 0, sizeof(sc->sq_trace));
+       sc->sq_trace_idx = 0;
 
        ++ifp->if_oerrors;
 
        sq_init(ifp);
 }
 
-void sq_trace_dump(struct sq_softc* sc)
+static void
+sq_trace_dump(struct sq_softc *sc)
 {
        int i;
+       char *act;
 
-       for(i = 0; i < sq_trace_idx; i++) {
-               printf("%s: [%d] action %d, buf %d, free %d, status %08x\n",
-                       sc->sc_dev.dv_xname, i, sq_trace[i].action,
-                       sq_trace[i].bufno, sq_trace[i].freebuf,
-                       sq_trace[i].status);
+       for (i = 0; i < sc->sq_trace_idx; i++) {
+               switch (sc->sq_trace[i].action) {
+               case SQ_RESET:          act = "SQ_RESET";               break;
+               case SQ_ADD_TO_DMA:     act = "SQ_ADD_TO_DMA";          break;
+               case SQ_START_DMA:      act = "SQ_START_DMA";           break;
+               case SQ_DONE_DMA:       act = "SQ_DONE_DMA";            break; 
+               case SQ_RESTART_DMA:    act = "SQ_RESTART_DMA";         break;
+               case SQ_TXINTR_ENTER:   act = "SQ_TXINTR_ENTER";        break;
+               case SQ_TXINTR_EXIT:    act = "SQ_TXINTR_EXIT";         break;
+               case SQ_TXINTR_BUSY:    act = "SQ_TXINTR_BUSY";         break;
+               case SQ_IOCTL:          act = "SQ_IOCTL";               break;
+               case SQ_ENQUEUE:        act = "SQ_ENQUEUE";             break;
+               default:                act = "UNKNOWN";
+               }
+
+               printf("%s: [%03d] action %-16s buf %03d free %03d "
+                   "status %08x line %d\n", sc->sc_dev.dv_xname, i, act,
+                   sc->sq_trace[i].bufno, sc->sq_trace[i].freebuf,
+                   sc->sq_trace[i].status, sc->sq_trace[i].line);
        }
 }
 
@@ -928,6 +945,8 @@
                            sc->sc_rxmap[i]->dm_mapsize,
                            BUS_DMASYNC_PREREAD);
                        SQ_INIT_RXDESC(sc, i);
+                       SQ_DPRINTF(("%s: sq_rxintr: buf %d no RXSTAT_GOOD\n",
+                           sc->sc_dev.dv_xname, i));
                        continue;
                }
 
@@ -937,6 +956,8 @@
                            sc->sc_rxmap[i]->dm_mapsize,
                            BUS_DMASYNC_PREREAD);
                        SQ_INIT_RXDESC(sc, i);
+                       SQ_DPRINTF(("%s: sq_rxintr: buf %d sq_add_rxbuf() "
+                           "failed\n", sc->sc_dev.dv_xname, i));
                        continue;
                }
 
@@ -995,11 +1016,8 @@
 static int
 sq_txintr(struct sq_softc *sc)
 {
-       int i;
        int shift = 0;
        u_int32_t status;
-       u_int32_t hpc1_ready = 0;
-       u_int32_t hpc3_not_ready = 1;
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 
        if (sc->hpc_regs->revision != 3)
@@ -1008,10 +1026,9 @@
        status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch,
                                  sc->hpc_regs->enetx_ctl) >> shift;
 



Home | Main Index | Thread Index | Old Index