Here I have prepared a patch, that utilizes the
tag in status block on the chips that can do this.
It also moves some chip quirks startup code to a
separate function.

-- 
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE
Index: if_bge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/bge/if_bge.c,v
retrieving revision 1.139
diff -u -p -r1.139 if_bge.c
--- if_bge.c    23 Aug 2006 11:32:54 -0000      1.139
+++ if_bge.c    24 Aug 2006 13:07:12 -0000
@@ -978,7 +978,7 @@ bge_chipinit(struct bge_softc *sc)
        int i;
 
        /* Set endian type before we access any non-PCI registers. */
-       pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4);
+       pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, sc->bge_misc_ctl, 4);
 
        /*
         * Check the 'ROM failed' bit on the RX CPU to see if
@@ -1982,6 +1982,70 @@ bge_dma_alloc(device_t dev)
        return (0);
 }
 
+static void
+bge_recognize(struct bge_softc *sc)
+{
+       device_t dev = sc->bge_dev;
+       uint32_t misccfg;
+
+       /* Save ASIC rev. */
+       sc->bge_chipid =
+           pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
+           BGE_PCIMISCCTL_ASICREV;
+       sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
+       sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
+
+       sc->bge_misc_ctl = (BGE_HIF_SWAP_OPTIONS                |
+                           BGE_PCIMISCCTL_CLEAR_INTA           |
+                           BGE_PCIMISCCTL_MASK_PCI_INTR        |
+                           BGE_PCIMISCCTL_INDIRECT_ACCESS);
+       sc->bge_hcc_mode = 0;
+
+       /*
+        * XXX: Broadcom Linux driver.  Not in specs or eratta.
+        * PCI-Express?
+        */
+       if (BGE_IS_5705_OR_BEYOND(sc)) {
+               uint32_t v;
+
+               v = pci_read_config(dev, BGE_PCI_MSI_CAPID, 4);
+               if (((v >> 8) & 0xff) == BGE_PCIE_CAPID_REG) {
+                       v = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4);
+                       if ((v & 0xff) == BGE_PCIE_CAPID)
+                               sc->bge_flags |= BGE_FLAG_PCIE;
+               }
+       }
+
+       /*
+        * PCI-X?
+        */
+       if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
+           BGE_PCISTATE_PCI_BUSMODE) == 0)
+               sc->bge_flags |= BGE_FLAG_PCIX;
+
+       misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
+       if (sc->bge_asicrev == BGE_ASICREV_BCM5705 &&
+           (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
+           misccfg == BGE_MISCCFG_BOARD_ID_5788M))
+               sc->bge_flags |= BGE_FLAG_5788;
+
+       if (sc->bge_chiprev != BGE_CHIPREV_5700_AX &&
+           sc->bge_chiprev != BGE_CHIPREV_5700_BX)
+               sc->bge_hcc_mode |= BGE_STATBLKSZ_32BYTE;
+
+       /*
+        * 5788 and 5700 does not support tagging the status block.
+        * This is workarounded in bge_tick_locked().
+        */
+       if (!(sc->bge_flags & BGE_FLAG_5788) &&
+           sc->bge_asicrev != BGE_ASICREV_BCM5700) {
+               sc->bge_flags |= BGE_FLAG_STATUSTAG;
+               sc->bge_hcc_mode |= (BGE_HCCMODE_CLRTICK_RXBD |
+                   BGE_HCCMODE_CLRTICK_TXBD);
+               sc->bge_misc_ctl |= BGE_PCIMISCCTL_TAGGED_STATUS;
+       }
+}
+
 static int
 bge_attach(device_t dev)
 {
@@ -2027,35 +2091,8 @@ bge_attach(device_t dev)
 
        BGE_LOCK_INIT(sc, device_get_nameunit(dev));
 
-       /* Save ASIC rev. */
-
-       sc->bge_chipid =
-           pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
-           BGE_PCIMISCCTL_ASICREV;
-       sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
-       sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
-
-       /*
-        * XXX: Broadcom Linux driver.  Not in specs or eratta.
-        * PCI-Express?
-        */
-       if (BGE_IS_5705_OR_BEYOND(sc)) {
-               uint32_t v;
-
-               v = pci_read_config(dev, BGE_PCI_MSI_CAPID, 4);
-               if (((v >> 8) & 0xff) == BGE_PCIE_CAPID_REG) {
-                       v = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4);
-                       if ((v & 0xff) == BGE_PCIE_CAPID)
-                               sc->bge_flags |= BGE_FLAG_PCIE;
-               }
-       }
-
-       /*
-        * PCI-X ?
-        */
-       if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
-           BGE_PCISTATE_PCI_BUSMODE) == 0)
-               sc->bge_flags |= BGE_FLAG_PCIX;
+       /* Fill in bge_flags, recognize features/bugs.*/
+       bge_recognize(sc);
 
        /* Try to reset the chip. */
        bge_reset(sc);
@@ -2684,16 +2721,13 @@ bge_poll(struct ifnet *ifp, enum poll_cm
 static void
 bge_intr(void *xsc)
 {
-       struct bge_softc *sc;
-       struct ifnet *ifp;
+       struct bge_softc *sc = xsc;
+       struct ifnet *ifp = sc->bge_ifp;
+       struct bge_status_block *sblock = sc->bge_ldata.bge_status_block;
        uint32_t statusword;
 
-       sc = xsc;
-
        BGE_LOCK(sc);
 
-       ifp = sc->bge_ifp;
-
 #ifdef DEVICE_POLLING
        if (ifp->if_capenable & IFCAP_POLLING) {
                BGE_UNLOCK(sc);
@@ -2701,6 +2735,15 @@ bge_intr(void *xsc)
        }
 #endif
 
+       if ((((sc->bge_flags & BGE_FLAG_STATUSTAG) &&
+           (sc->bge_last_tag == sblock->bge_tag)) ||
+           !(sblock->bge_status & BGE_STATUS_UPDATED)) &&
+           (pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
+           BGE_PCISTATE_INTR_STATE)) {
+               /* Not our interrupt? */
+               BGE_UNLOCK(sc);
+               return;
+       }
        /*
         * Do the mandatory PCI flush as well as get the link status.
         */
@@ -2729,7 +2772,13 @@ bge_intr(void *xsc)
        }
 
        /* Re-enable interrupts. */
-       CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+       if (sc->bge_flags & BGE_FLAG_STATUSTAG) {
+               sc->bge_last_tag = sblock->bge_tag;
+               CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, (sc->bge_last_tag << 24));
+       } else {
+               sblock->bge_status &= ~BGE_STATUS_UPDATED;
+               CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+       }
 
        if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
            !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -2769,6 +2818,16 @@ bge_tick_locked(struct bge_softc *sc)
                }
        }
 
+       if (!(sc->bge_flags & BGE_FLAG_STATUSTAG)) {
+               struct bge_status_block *sblock = 
sc->bge_ldata.bge_status_block;
+
+               if (sblock->bge_status & BGE_STATUS_UPDATED)
+                       BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET);
+               else
+                       CSR_WRITE_4(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE |
+                           BGE_HCCMODE_COAL_NOW);
+       }
+
        callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
 }
 
Index: if_bgereg.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/bge/if_bgereg.h,v
retrieving revision 1.52
diff -u -p -r1.52 if_bgereg.h
--- if_bgereg.h 23 Aug 2006 11:32:54 -0000      1.52
+++ if_bgereg.h 24 Aug 2006 13:06:05 -0000
@@ -205,6 +205,7 @@
 #define BGE_PCIMISCCTL_CLOCKCTL_RW     0x00000020
 #define BGE_PCIMISCCTL_REG_WORDSWAP    0x00000040
 #define BGE_PCIMISCCTL_INDIRECT_ACCESS 0x00000080
+#define BGE_PCIMISCCTL_TAGGED_STATUS   0x00000200
 #define BGE_PCIMISCCTL_ASICREV         0xFFFF0000
 
 #define BGE_HIF_SWAP_OPTIONS   (BGE_PCIMISCCTL_ENDIAN_WORDSWAP)
@@ -218,10 +219,6 @@
        BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA
 #endif
 
-#define BGE_INIT \
-       (BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_CLEAR_INTA| \
-        BGE_PCIMISCCTL_MASK_PCI_INTR|BGE_PCIMISCCTL_INDIRECT_ACCESS)
-
 #define BGE_CHIPID_TIGON_I             0x40000000
 #define BGE_CHIPID_TIGON_II            0x60000000
 #define BGE_CHIPID_BCM5700_A0          0x70000000
@@ -1190,6 +1187,8 @@
 #define BGE_STATBLKSZ_FULL             0x00000000
 #define BGE_STATBLKSZ_64BYTE           0x00000080
 #define BGE_STATBLKSZ_32BYTE           0x00000100
+#define BGE_HCCMODE_CLRTICK_RXBD        0x00000200
+#define BGE_HCCMODE_CLRTICK_TXBD        0x00000400
 
 /* Host coalescing status register */
 #define BGE_HCCSTAT_ERROR              0x00000004
@@ -1684,6 +1683,9 @@
 /* Misc. config register */
 #define BGE_MISCCFG_RESET_CORE_CLOCKS  0x00000001
 #define BGE_MISCCFG_TIMER_PRESCALER    0x000000FE
+#define BGE_MISCCFG_BOARD_ID_MASK      0x0001e000
+#define BGE_MISCCFG_BOARD_ID_5788      0x00010000
+#define BGE_MISCCFG_BOARD_ID_5788M     0x00018000
 
 #define BGE_32BITTIME_66MHZ            (0x41 << 1)
 
@@ -1932,7 +1934,10 @@ struct bge_sts_idx {
 
 struct bge_status_block {
        uint32_t                bge_status;
-       uint32_t                bge_rsvd0;
+#define        BGE_STATUS_UPDATED      0x00000001
+#define        BGE_STATUS_LINKEV       0x00000002
+#define        BGE_STATUS_ERROR        0x00000004
+       uint32_t                bge_tag;
 #if BYTE_ORDER == LITTLE_ENDIAN
        uint16_t                bge_rx_jumbo_cons_idx;
        uint16_t                bge_rx_std_cons_idx;
@@ -2451,11 +2456,14 @@ struct bge_softc {
 #define BGE_FLAG_NO3LED                0x00000008
 #define BGE_FLAG_PCIX          0x00000010
 #define BGE_FLAG_PCIE          0x00000020
+#define        BGE_FLAG_5788           0x00000040
+#define        BGE_FLAG_STATUSTAG      0x00000080
        uint32_t                bge_chipid;
        uint8_t         bge_asicrev;
        uint8_t         bge_chiprev;
        struct bge_ring_data    bge_ldata;      /* rings */
        struct bge_chain_data   bge_cdata;      /* mbufs */
+       uint32_t                bge_last_tag;
        uint16_t                bge_tx_saved_considx;
        uint16_t                bge_rx_saved_considx;
        uint16_t                bge_ev_saved_considx;
@@ -2474,6 +2482,9 @@ struct bge_softc {
        int                     bge_link;       /* link state */
        int                     bge_link_evt;   /* pending link event */
        struct callout          bge_stat_ch;
+       /* Masks/values for some registers. */
+       uint32_t                bge_hcc_mode;   /* BGE_HCC_MODE */
+       uint32_t                bge_misc_ctl;   /* BGE_PCI_MISC_CTL */
        char                    *bge_vpd_prodname;
        char                    *bge_vpd_readonly;
        u_long                  bge_rx_discards;
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to