NetBSD-Bugs archive

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

kern/39241: Changes of bge driver to support bcm5906(m) (Patch included)



>Number:         39241
>Category:       kern
>Synopsis:       The Broadcom BCM5906(M) is not supported
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 28 20:55:00 +0000 2008
>Originator:     charlie%tigress.com@localhost
>Release:        NetBSD 4.99.70
>Organization:
>Environment:
System: NetBSD ramses 4.99.70 NetBSD 4.99.70 (GENERIC) #7: Mon Jul 28 13:00:47 
UTC 2008 
charlie@ramses:/home/charlie/netbsd-src/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
Basically this patch is based on the FreeBSD driver.

I had a problems in the brgphy code. The MII_MODEL number for the
BCM5906 PHY allready existed.... 

>Fix:
Apply this patch:


Index: dev/mii/brgphy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/brgphy.c,v
retrieving revision 1.39
diff -u -r1.39 brgphy.c
--- dev/mii/brgphy.c    4 May 2008 17:06:09 -0000       1.39
+++ dev/mii/brgphy.c    26 Jul 2008 19:04:53 -0000
@@ -183,6 +183,9 @@
        { MII_OUI_BROADCOM2,            MII_MODEL_BROADCOM2_BCM5754,
          MII_STR_BROADCOM2_BCM5754 },
 
+       { MII_OUI_xxBROADCOM_ALT1,      MII_MODEL_xxBROADCOM_ALT1_BCM5906,
+         MII_STR_xxBROADCOM_ALT1_BCM5906 },
+
        { 0,                            0,
          NULL },
 };
@@ -226,57 +229,62 @@
        sc->mii_flags = ma->mii_flags;
        sc->mii_anegticks = MII_ANEGTICKS;
 
-       switch (MII_MODEL(ma->mii_id2)) {
-       case MII_MODEL_BROADCOM_BCM5400:
-               sc->mii_funcs = &brgphy_5401_funcs;
-               aprint_normal_dev(self, "using BCM5401 DSP patch\n");
-               break;
-
-       case MII_MODEL_BROADCOM_BCM5401:
-               if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) == 3) {
+       if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM_ALT1) {
+               sc->mii_funcs = &brgphy_5750_funcs;
+               aprint_normal_dev(self, "using BCM5750 DSP patch\n");
+       } else {
+               switch (MII_MODEL(ma->mii_id2)) {
+               case MII_MODEL_BROADCOM_BCM5400:
                        sc->mii_funcs = &brgphy_5401_funcs;
                        aprint_normal_dev(self, "using BCM5401 DSP patch\n");
-               } else
-                       sc->mii_funcs = &brgphy_funcs;
-               break;
+                       break;
 
-       case MII_MODEL_BROADCOM_BCM5411:
-               sc->mii_funcs = &brgphy_5411_funcs;
-               aprint_normal_dev(self, "using BCM5411 DSP patch\n");
-               break;
+               case MII_MODEL_BROADCOM_BCM5401:
+                       if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) 
== 3) {
+                               sc->mii_funcs = &brgphy_5401_funcs;
+                               aprint_normal_dev(self, "using BCM5401 DSP 
patch\n");
+                       } else
+                               sc->mii_funcs = &brgphy_funcs;
+                       break;
 
-#ifdef notyet /* unverified, untested */
-       case MII_MODEL_BROADCOM_BCM5703:
-               sc->mii_funcs = &brgphy_5703_funcs;
-               aprint_normal_dev(self, "using BCM5703 DSP patch\n");
-               break;
-#endif
+               case MII_MODEL_BROADCOM_BCM5411:
+                       sc->mii_funcs = &brgphy_5411_funcs;
+                       aprint_normal_dev(self, "using BCM5411 DSP patch\n");
+                       break;
 
-       case MII_MODEL_BROADCOM_BCM5704:
-               sc->mii_funcs = &brgphy_5704_funcs;
-               aprint_normal_dev(self, "using BCM5704 DSP patch\n");
-               break;
+       #ifdef notyet /* unverified, untested */
+               case MII_MODEL_BROADCOM_BCM5703:
+                       sc->mii_funcs = &brgphy_5703_funcs;
+                       aprint_normal_dev(self, "using BCM5703 DSP patch\n");
+                       break;
+       #endif
 
-       case MII_MODEL_BROADCOM_BCM5705:
-               sc->mii_funcs = &brgphy_5705_funcs;
-               break;
+               case MII_MODEL_BROADCOM_BCM5704:
+                       sc->mii_funcs = &brgphy_5704_funcs;
+                       aprint_normal_dev(self, "using BCM5704 DSP patch\n");
+                       break;
 
-       case MII_MODEL_BROADCOM_BCM5714:
-       case MII_MODEL_BROADCOM_BCM5780:
-       case MII_MODEL_BROADCOM_BCM5708C:
-       case MII_MODEL_BROADCOM_BCM5750:
-       case MII_MODEL_BROADCOM_BCM5752:
-               sc->mii_funcs = &brgphy_5750_funcs;
-               break;
+               case MII_MODEL_BROADCOM_BCM5705:
+                       sc->mii_funcs = &brgphy_5705_funcs;
+                       break;
 
-       case MII_MODEL_BROADCOM2_BCM5754:
-       case MII_MODEL_BROADCOM2_BCM5755:
-               sc->mii_funcs = &brgphy_5755_funcs;
-               break;
+               case MII_MODEL_BROADCOM_BCM5714:
+               case MII_MODEL_BROADCOM_BCM5780:
+               case MII_MODEL_BROADCOM_BCM5708C:
+               case MII_MODEL_BROADCOM_BCM5750:
+               case MII_MODEL_BROADCOM_BCM5752:
+                       sc->mii_funcs = &brgphy_5750_funcs;
+                       break;
 
-       default:
-               sc->mii_funcs = &brgphy_funcs;
-               break;
+               case MII_MODEL_BROADCOM2_BCM5754:
+               case MII_MODEL_BROADCOM2_BCM5755:
+                       sc->mii_funcs = &brgphy_5755_funcs;
+                       break;
+
+               default:
+                       sc->mii_funcs = &brgphy_funcs;
+                       break;
+               }
        }
 
        PHY_RESET(sc);
Index: dev/mii/brgphyreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/brgphyreg.h,v
retrieving revision 1.2
diff -u -r1.2 brgphyreg.h
--- dev/mii/brgphyreg.h 22 Jun 2002 14:37:58 -0000      1.2
+++ dev/mii/brgphyreg.h 26 Jul 2008 19:04:53 -0000
@@ -75,6 +75,14 @@
 #define BRGPHY_PHY_EXTSTS_LOCK_ER      0x0002  /* Lock error */
 #define BRGPHY_PHY_EXTSTS_MLT3_ER      0x0001  /* MLT3 code error */
 
+#define BRGPHY_MII_1000CTL     0x09    /* 1000baseT control */
+#define        BRGPHY_1000CTL_TST      0xE000  /* Test modes */
+#define        BRGPHY_1000CTL_MSE      0x1000  /* Master/Slave enable */
+#define        BRGPHY_1000CTL_MSC      0x0800  /* Master/Slave configuration */
+#define        BRGPHY_1000CTL_RD       0x0400  /* Repeater/DTE */
+#define        BRGPHY_1000CTL_AFD      0x0200  /* Advertise full duplex */
+#define        BRGPHY_1000CTL_AHD      0x0100  /* Advertise half duplex */
+
 #define BRGPHY_MII_RXERRCNT    0x12    /* RX error counter */
 
 #define BRGPHY_MII_FCERRCNT    0x13    /* false carrier sense counter */
Index: dev/mii/miidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs,v
retrieving revision 1.76
diff -u -r1.76 miidevs
--- dev/mii/miidevs     28 Apr 2008 20:23:53 -0000      1.76
+++ dev/mii/miidevs     26 Jul 2008 19:04:53 -0000
@@ -77,6 +77,7 @@
 /* bad bitorder (bits "g" and "h" (= MSBs byte 1) lost) */
 oui yyAMD                      0x000058        Advanced Micro Devices
 oui xxBROADCOM                 0x000818        Broadcom Corporation
+oui xxBROADCOM_ALT1            0x0050ef        Broadcom Corporation
 oui xxDAVICOM                  0x000676        Davicom Semiconductor
 oui yyINTEL                    0x005500        Intel
 oui xxMARVELL                  0x000ac2        Marvell Semiconductor
@@ -138,6 +139,7 @@
 model BROADCOM BCM5708C                0x0036 BCM5708C 1000BASE-T media 
interface
 model BROADCOM2 BCM5755                0x000c BCM5755 1000BASE-T media 
interface
 model BROADCOM2 BCM5754                0x000e BCM5754/5787 1000BASE-T media 
interface
+model xxBROADCOM_ALT1 BCM5906          0x0004 BCM5906 10/100baseTX media 
interface
  
 /* Cicada Semiconductor PHYs (now owned by Vitesse?) */
 model CICADA CS8201            0x0001 Cicada CS8201 10/100/1000TX PHY
Index: dev/mii/miidevs.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs.h,v
retrieving revision 1.79
diff -u -r1.79 miidevs.h
--- dev/mii/miidevs.h   28 Apr 2008 20:23:53 -0000      1.79
+++ dev/mii/miidevs.h   26 Jul 2008 19:04:54 -0000
@@ -1,10 +1,10 @@
-/*     $NetBSD: miidevs.h,v 1.79 2008/04/28 20:23:53 martin Exp $      */
+/*     $NetBSD$        */
 
 /*
  * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
  *
  * generated from:
- *     NetBSD: miidevs,v 1.75 2008/02/20 11:17:41 markd Exp
+ *     NetBSD: miidevs,v 1.76 2008/04/28 20:23:53 martin Exp
  */
 
 /*-
@@ -84,6 +84,7 @@
 /* bad bitorder (bits "g" and "h" (= MSBs byte 1) lost) */
 #define        MII_OUI_yyAMD   0x000058        /* Advanced Micro Devices */
 #define        MII_OUI_xxBROADCOM      0x000818        /* Broadcom Corporation 
*/
+#define        MII_OUI_xxBROADCOM_ALT1 0x0050ef        /* Broadcom Corporation 
*/
 #define        MII_OUI_xxDAVICOM       0x000676        /* Davicom 
Semiconductor */
 #define        MII_OUI_yyINTEL 0x005500        /* Intel */
 #define        MII_OUI_xxMARVELL       0x000ac2        /* Marvell 
Semiconductor */
@@ -176,6 +177,8 @@
 #define        MII_STR_BROADCOM2_BCM5755       "BCM5755 1000BASE-T media 
interface"
 #define        MII_MODEL_BROADCOM2_BCM5754     0x000e
 #define        MII_STR_BROADCOM2_BCM5754       "BCM5754/5787 1000BASE-T media 
interface"
+#define        MII_MODEL_xxBROADCOM_ALT1_BCM5906       0x0004
+#define        MII_STR_xxBROADCOM_ALT1_BCM5906 "BCM5906 10/100baseTX media 
interface"
  
 /* Cicada Semiconductor PHYs (now owned by Vitesse?) */
 #define        MII_MODEL_CICADA_CS8201 0x0001
Index: dev/mii/miidevs_data.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs_data.h,v
retrieving revision 1.69
diff -u -r1.69 miidevs_data.h
--- dev/mii/miidevs_data.h      28 Apr 2008 20:23:53 -0000      1.69
+++ dev/mii/miidevs_data.h      26 Jul 2008 19:04:54 -0000
@@ -1,10 +1,10 @@
-/*     $NetBSD: miidevs_data.h,v 1.69 2008/04/28 20:23:53 martin Exp $ */
+/*     $NetBSD$        */
 
 /*
  * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
  *
  * generated from:
- *     NetBSD: miidevs,v 1.75 2008/02/20 11:17:41 markd Exp
+ *     NetBSD: miidevs,v 1.76 2008/04/28 20:23:53 martin Exp
  */
 
 /*-
@@ -68,6 +68,7 @@
  { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5708C, MII_STR_BROADCOM_BCM5708C },
  { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5755, MII_STR_BROADCOM2_BCM5755 },
  { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754, MII_STR_BROADCOM2_BCM5754 },
+ { MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906, 
MII_STR_xxBROADCOM_ALT1_BCM5906 },
  { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201, MII_STR_CICADA_CS8201 },
  { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201A, MII_STR_CICADA_CS8201A },
  { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201B, MII_STR_CICADA_CS8201B },
Index: dev/pci/if_bge.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.150
diff -u -r1.150 if_bge.c
--- dev/pci/if_bge.c    25 Jul 2008 19:45:06 -0000      1.150
+++ dev/pci/if_bge.c    26 Jul 2008 19:04:59 -0000
@@ -186,12 +186,19 @@
 
 static int     bge_rxthresh_nodenum;
 
+typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, u_int8_t[]);
+
 static int     bge_probe(device_t, cfdata_t, void *);
 static void    bge_attach(device_t, device_t, void *);
 static void    bge_release_resources(struct bge_softc *);
 static void    bge_txeof(struct bge_softc *);
 static void    bge_rxeof(struct bge_softc *);
 
+static int     bge_get_eaddr_mem(struct bge_softc *, u_int8_t[]);
+static int     bge_get_eaddr_nvram(struct bge_softc *, u_int8_t[]);
+static int     bge_get_eaddr_eeprom(struct bge_softc *, u_int8_t[]);
+static int     bge_get_eaddr(struct bge_softc *, u_int8_t[]);
+
 static void    bge_tick(void *);
 static void    bge_stats_update(struct bge_softc *);
 static int     bge_encap(struct bge_softc *, struct mbuf *, u_int32_t *);
@@ -282,6 +289,7 @@
         BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || \
         BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || \
         BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 || \
+        BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 || \
         BGE_IS_5714_FAMILY(sc) )
 
 #define BGE_IS_5705_OR_BEYOND(sc)  \
@@ -329,6 +337,21 @@
        pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_REG_DATA, val);
 }
 
+static void
+bge_writemem_direct(struct bge_softc *sc, int off, int val)
+{
+       CSR_WRITE_4(sc, off, val);
+}
+
+static void
+bge_writembx(struct bge_softc *sc, int off, int val)
+{
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906)
+               off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
+
+       CSR_WRITE_4(sc, off, val);
+}
+
 #ifdef notdef
 static u_int8_t
 bge_vpd_readbyte(struct bge_softc *sc, int addr)
@@ -413,6 +436,79 @@
 }
 #endif
 
+static u_int8_t
+bge_nvram_getbyte(struct bge_softc *sc, int addr, u_int8_t *dest)
+{
+       u_int32_t access, byte = 0;
+       int i;
+
+       /* Lock. */
+       CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
+       for (i = 0; i < 8000; i++) {
+               if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1)
+                       break;
+               DELAY(20);
+       }
+       if (i == 8000)
+               return (1);
+
+       /* Enable access. */
+       access = CSR_READ_4(sc, BGE_NVRAM_ACCESS);
+       CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE);
+
+       CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc);
+       CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD);
+       for (i = 0; i < BGE_TIMEOUT * 10; i++) {
+               DELAY(10);
+               if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) {
+                       DELAY(10);
+                       break;
+               }
+       }
+
+       if (i == BGE_TIMEOUT * 10) {
+               aprint_error_dev(sc->bge_dev, "nvram read timed out\n");
+               return (1);
+       }
+
+       /* Get result. */
+       byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA);
+
+       *dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF;
+
+       /* Disable access. */
+       CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access);
+
+       /* Unlock. */
+       CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
+       CSR_READ_4(sc, BGE_NVRAM_SWARB);
+
+       return (0);
+}
+
+/*
+ * Read a sequence of bytes from NVRAM.
+ */
+static int
+bge_read_nvram(struct bge_softc *sc, u_int8_t *dest, int off, int cnt)
+{
+       int err = 0, i;
+       u_int8_t byte = 0;
+
+       if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5906)
+               return (1);
+
+       for (i = 0; i < cnt; i++) {
+               err = bge_nvram_getbyte(sc, off + i, &byte);
+               if (err)
+                       break;
+               *(dest + i) = byte;
+       }
+
+       return (err ? 1 : 0);
+}
+
+
 /*
  * Read a byte of data stored in the EEPROM at address 'addr.' The
  * BCM570x supports both the traditional bitbang interface and an
@@ -539,6 +635,15 @@
        u_int32_t saved_autopoll;
        int i;
 
+       if (phy!=1) {
+               return;
+       }
+
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 &&
+           (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL)) {
+               return;
+       }
+
        /* Touching the PHY while autopolling is on may trigger PCI errors */
        saved_autopoll = CSR_READ_4(sc, BGE_MI_MODE);
        if (saved_autopoll & BGE_MIMODE_AUTOPOLL) {
@@ -552,9 +657,12 @@
            BGE_MIPHY(phy)|BGE_MIREG(reg)|val);
 
        for (i = 0; i < BGE_TIMEOUT; i++) {
-               if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY))
-                       break;
                delay(10);
+               if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
+                       delay(5);
+                       CSR_READ_4(sc, BGE_MI_COMM);
+                       break;
+               }
        }
 
        if (saved_autopoll & BGE_MIMODE_AUTOPOLL) {
@@ -968,7 +1076,7 @@
        }
 
        sc->bge_std = i - 1;
-       CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
+       bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
 
        sc->bge_flags |= BGE_RXRING_VALID;
 
@@ -1018,7 +1126,7 @@
        rcb->bge_maxlen_flags = 0;
        CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
 
-       CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
+       bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
 
        return(0);
 }
@@ -1091,14 +1199,14 @@
 
        /* Initialize transmit producer index for host-memory send ring. */
        sc->bge_tx_prodidx = 0;
-       CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+       bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
        if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)    /* 5700 b2 errata */
-               CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
+               bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
 
        /* NIC-memory send ring  not used; initialize to zero. */
-       CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+       bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
        if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)    /* 5700 b2 errata */
-               CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
+               bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
 
        SLIST_INIT(&sc->txdma_list);
        for (i = 0; i < BGE_RSLOTS; i++) {
@@ -1466,6 +1574,10 @@
                        CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50);
                        CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20);
                        CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
+               } else if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
+                       CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
+                       CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04);
+                       CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10);
                } else {
                        /* Values from Linux driver... */
                        CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 304);
@@ -1484,20 +1596,22 @@
        CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10);
 
        /* Enable buffer manager */
-       CSR_WRITE_4(sc, BGE_BMAN_MODE,
-           BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN);
+       if ((sc->bge_quirks & BGE_QUIRK_5705_CORE) == 0) {
+               CSR_WRITE_4(sc, BGE_BMAN_MODE,
+                   BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN);
 
-       /* Poll for buffer manager start indication */
-       for (i = 0; i < BGE_TIMEOUT; i++) {
-               if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
-                       break;
-               DELAY(10);
-       }
+               /* Poll for buffer manager start indication */
+               for (i = 0; i < BGE_TIMEOUT; i++) {
+                       if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE)
+                               break;
+                       DELAY(10);
+               }
 
-       if (i == BGE_TIMEOUT) {
-               aprint_error_dev(sc->bge_dev,
-                   "buffer manager failed to start\n");
-               return(ENXIO);
+               if (i == BGE_TIMEOUT) {
+                       aprint_error_dev(sc->bge_dev,
+                           "buffer manager failed to start\n");
+                       return(ENXIO);
+               }
        }
 
        /* Enable flow-through queues */
@@ -1597,7 +1711,8 @@
        if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 ||
            BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 ||
            BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 ||
-           BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787)
+           BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 ||
+           BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906)
                i = 8;
 
        CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, i);
@@ -1637,15 +1752,15 @@
                            BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt,
                                      BGE_RCB_FLAG_RING_DISABLED));
                RCB_WRITE_4(sc, rcb_addr, bge_nicaddr, 0);
-               CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO +
+               bge_writembx(sc, BGE_MBX_RX_CONS0_LO +
                    (i * (sizeof(u_int64_t))), 0);
                rcb_addr += sizeof(struct bge_rcb);
        }
 
        /* Initialize RX ring indexes */
-       CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, 0);
-       CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
-       CSR_WRITE_4(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
+       bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0);
+       bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
+       bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
 
        /*
         * Set up RX return ring 0
@@ -2092,6 +2207,10 @@
          BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
          "unknown BCM5787" },
 
+       { BGE_ASICREV_BCM5906,
+         BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+         "unknown BCM5906" }, 
+
        { 0,
          0,
          NULL }
@@ -2345,6 +2464,16 @@
          "3Com 3c996 Gigabit Ethernet",
          },
 
+       { PCI_VENDOR_BROADCOM,
+         PCI_PRODUCT_BROADCOM_BCM5906,
+         "Broadcom BCM5906 Fast Ethernet",
+         },
+
+       { PCI_VENDOR_BROADCOM,
+         PCI_PRODUCT_BROADCOM_BCM5906M,
+         "Broadcom BCM5906M Fast Ethernet",
+         },
+
        { 0,
          0,
          NULL },
@@ -2444,7 +2573,6 @@
        bus_dma_segment_t       seg;
        int                     rseg;
        u_int32_t               hwcfg = 0;
-       u_int32_t               mac_addr = 0;
        u_int32_t               command;
        struct ifnet            *ifp;
        void *                  kva;
@@ -2558,19 +2686,9 @@
        /*
         * Get station address from the EEPROM.
         */
-       mac_addr = bge_readmem_ind(sc, 0x0c14);
-       if ((mac_addr >> 16) == 0x484b) {
-               eaddr[0] = (u_char)(mac_addr >> 8);
-               eaddr[1] = (u_char)(mac_addr >> 0);
-               mac_addr = bge_readmem_ind(sc, 0x0c18);
-               eaddr[2] = (u_char)(mac_addr >> 24);
-               eaddr[3] = (u_char)(mac_addr >> 16);
-               eaddr[4] = (u_char)(mac_addr >> 8);
-               eaddr[5] = (u_char)(mac_addr >> 0);
-       } else if (bge_read_eeprom(sc, (void *)eaddr,
-           BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
-               aprint_error_dev(sc->bge_dev,
-                   "failed to read station address\n");
+       if (bge_get_eaddr(sc, eaddr)) {
+               aprint_error_dev(sc->bge_dev, 
+               "failed to reade station address\n");
                bge_release_resources(sc);
                return;
        }
@@ -2818,6 +2936,19 @@
 {
        u_int32_t cachesize, command, pcistate, new_pcistate;
        int i, val;
+       void (*write_op)(struct bge_softc *, int, int);
+
+       if (BGE_IS_5750_OR_BEYOND(sc) && !BGE_IS_5714_FAMILY(sc) && 
+           (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5906)) {
+               if (sc->bge_pcie) {
+                       write_op = bge_writemem_direct;
+               } else {
+                       write_op = bge_writemem_ind;
+               }
+       } else {
+               write_op = bge_writereg_ind;
+       }
+
 
        /* Save some important PCI state. */
        cachesize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ);
@@ -2852,7 +2983,18 @@
        }
 
        /* Issue global reset */
-       bge_writereg_ind(sc, BGE_MISC_CFG, val);
+       write_op(sc, BGE_MISC_CFG, val);
+
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
+               i = CSR_READ_4(sc, BGE_VCPU_STATUS);
+               CSR_WRITE_4(sc, BGE_VCPU_STATUS,
+                   i | BGE_VCPU_STATUS_DRV_RESET);
+               i = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL);
+               CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL,
+                   i & ~BGE_VCPU_EXT_CTRL_HALT_CPU);
+       }
+
+
 
        DELAY(1000);
 
@@ -2886,7 +3028,7 @@
            BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW);
        pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CMD, command);
        pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_CACHESZ, cachesize);
-       bge_writereg_ind(sc, BGE_MISC_CFG, (65 << 1));
+       write_op(sc, BGE_MISC_CFG, (65 << 1));
 
        /* Enable memory arbiter. */
        {
@@ -2897,35 +3039,49 @@
                CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode);
        }
 
-       /*
-        * Write the magic number to the firmware mailbox at 0xb50
-        * so that the driver can synchronize with the firmware.
-        */
-       bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
 
-       /*
-        * Poll the value location we just wrote until
-        * we see the 1's complement of the magic number.
-        * This indicates that the firmware initialization
-        * is complete.
-        */
-       for (i = 0; i < BGE_TIMEOUT; i++) {
-               val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
-               if (val == ~BGE_MAGIC_NUMBER)
-                       break;
-               DELAY(1000);
-       }
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
+               for (i = 0; i < BGE_TIMEOUT; i++) {
+                       val = CSR_READ_4(sc, BGE_VCPU_STATUS);
+                       if (val & BGE_VCPU_STATUS_INIT_DONE)
+                               break;
+                       DELAY(100);
+               }
+               if (i == BGE_TIMEOUT) {
+                       aprint_error_dev(sc->bge_dev, "reset timed out\n");
+                       return;
+               }
+       } else {
+               /*
+                * Write the magic number to the firmware mailbox at 0xb50
+                * so that the driver can synchronize with the firmware.
+                */
+               bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
 
-       if (i >= BGE_TIMEOUT) {
-               aprint_error_dev(sc->bge_dev,
-                   "firmware handshake timed out, val = %x\n", val);
                /*
-                * XXX: occasionally fired on bcm5721, but without
-                * apparent harm.  For now, keep going if we timeout
-                * against PCI-E devices.
+                * Poll the value location we just wrote until
+                * we see the 1's complement of the magic number.
+                * This indicates that the firmware initialization
+                * is complete.
                 */
-                if (!sc->bge_pcie)
-                 return;
+               for (i = 0; i < BGE_TIMEOUT; i++) {
+                       val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
+                       if (val == ~BGE_MAGIC_NUMBER)
+                               break;
+                       DELAY(1000);
+               }
+
+               if (i >= BGE_TIMEOUT) {
+                       aprint_error_dev(sc->bge_dev,
+                           "firmware handshake timed out, val = %x\n", val);
+                       /*
+                        * XXX: occasionally fired on bcm5721, but without
+                        * apparent harm.  For now, keep going if we timeout
+                        * against PCI-E devices.
+                        */
+                        if (!sc->bge_pcie)
+                                 return;
+               }
        }
 
        /*
@@ -3131,11 +3287,11 @@
                (*ifp->if_input)(ifp, m);
        }
 
-       CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
+       bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
        if (stdcnt)
-               CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
+               bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
        if (jumbocnt)
-               CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
+               bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
 }
 
 static void
@@ -3246,7 +3402,7 @@
         */
 
        /* Ack interrupt and stop others from occuring. */
-       CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
+       bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
 
        BGE_EVCNT_INCR(sc->bge_ev_intr);
 
@@ -3318,7 +3474,7 @@
        bge_handle_events(sc);
 
        /* Re-enable interrupts. */
-       CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+       bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
 
        if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
                bge_start(ifp);
@@ -3949,9 +4105,9 @@
                return;
 
        /* Transmit */
-       CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+       bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
        if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)    /* 5700 b2 errata */
-               CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+               bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
 
        sc->bge_tx_prodidx = prodidx;
 
@@ -4037,7 +4193,7 @@
        /* Enable host interrupts. */
        BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
        BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
-       CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+       bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
 
        if ((error = bge_ifmedia_upd(ifp)) != 0)
                goto out;
@@ -4162,6 +4318,13 @@
                sc->bge_if_flags = ifp->if_flags;
                error = 0;
                break;
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               if (ifp->if_flags & IFF_RUNNING) {
+                       bge_setmulti(sc);
+                       error = 0;
+               }
+               break;
        case SIOCSIFMEDIA:
                /* XXX Flow control is not supported for 1000BASE-SX */
                if (sc->bge_tbi) {
@@ -4194,15 +4357,10 @@
                }
                break;
        default:
-               if ((error = ether_ioctl(ifp, command, data)) != ENETRESET)
-                       break;
-
-               error = 0;
-
-               if (command != SIOCADDMULTI && command != SIOCDELMULTI)
-                       ;
-               else if (ifp->if_flags & IFF_RUNNING)
-                       bge_setmulti(sc);
+               error = ether_ioctl(ifp, command, data);
+               if (error == ENETRESET) {
+                       error = 0;
+               }
                break;
        }
 
@@ -4302,7 +4460,7 @@
 
        /* Disable host interrupts. */
        BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
-       CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
+       bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
 
        /*
         * Tell firmware we're shutting down.
@@ -4405,3 +4563,66 @@
 err:
        aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
 }
+
+static int 
+bge_get_eaddr_mem(struct bge_softc *sc, u_int8_t ether_addr[])
+{
+       u_int32_t mac_addr;
+
+       mac_addr = bge_readmem_ind(sc, 0x0c14);
+       if ((mac_addr >> 16) == 0x484b) {
+               ether_addr[0] = (uint8_t)(mac_addr >> 8);
+               ether_addr[1] = (uint8_t)mac_addr;
+               mac_addr = bge_readmem_ind(sc, 0x0c18);
+               ether_addr[2] = (uint8_t)(mac_addr >> 24);
+               ether_addr[3] = (uint8_t)(mac_addr >> 16);
+               ether_addr[4] = (uint8_t)(mac_addr >> 8);
+               ether_addr[5] = (uint8_t)mac_addr;
+               return (0);
+       }
+       return (1);
+}
+
+static int
+bge_get_eaddr_nvram(struct bge_softc *sc, u_int8_t ether_addr[])
+{
+       int mac_offset = BGE_EE_MAC_OFFSET;
+
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
+               mac_offset = BGE_EE_MAC_OFFSET_5906;
+       }
+
+       return (bge_read_nvram(sc, ether_addr, mac_offset + 2,
+           ETHER_ADDR_LEN));
+}
+
+static int
+bge_get_eaddr_eeprom(struct bge_softc *sc, u_int8_t ether_addr[])
+{
+
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) {
+               return (1);
+       }
+
+       return (bge_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2,
+          ETHER_ADDR_LEN));
+}
+
+static int
+bge_get_eaddr(struct bge_softc *sc, u_int8_t eaddr[])
+{
+       static const bge_eaddr_fcn_t bge_eaddr_funcs[] = {
+               /* NOTE: Order is critical */
+               bge_get_eaddr_mem,
+               bge_get_eaddr_nvram,
+               bge_get_eaddr_eeprom,
+               NULL
+       };
+       const bge_eaddr_fcn_t *func;
+
+       for (func = bge_eaddr_funcs; *func != NULL; ++func) {
+               if ((*func)(sc, eaddr) == 0)
+                       break;
+       }
+       return (*func == NULL ? ENXIO : 0);
+}
Index: dev/pci/if_bgereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bgereg.h,v
retrieving revision 1.47
diff -u -r1.47 if_bgereg.h
--- dev/pci/if_bgereg.h 24 Jul 2008 08:14:49 -0000      1.47
+++ dev/pci/if_bgereg.h 26 Jul 2008 19:05:01 -0000
@@ -300,8 +300,11 @@
 #define BGE_ASICREV_BCM5714            0x09
 #define BGE_ASICREV_BCM5755            0x0a
 #define BGE_ASICREV_BCM5787            0x0b
+/* is this one mistyped ??? */
 #define BGE_ASICREV_BCM5706            0x0c
 
+#define BGE_ASICREV_BCM5906            0x0c
+
 /* chip revisions */
 #define BGE_CHIPREV(x)                 ((x) >> 24)
 #define BGE_CHIPREV_5700_AX            0x70
@@ -1425,6 +1428,17 @@
 #define BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW 0x40000000
 #define BGE_RXCPUSTAT_BLOCKING_READ    0x80000000
 
+/*
+ * V? CPU registers
+ */
+#define        BGE_VCPU_STATUS                 0x5100
+#define        BGE_VCPU_EXT_CTRL               0x6890
+
+#define        BGE_VCPU_STATUS_INIT_DONE       0x04000000
+#define        BGE_VCPU_STATUS_DRV_RESET       0x08000000
+
+#define        BGE_VCPU_EXT_CTRL_HALT_CPU      0x00400000
+#define        BGE_VCPU_EXT_CTRL_DISABLE_WOL   0x20000000
 
 /*
  * TX CPU registers
@@ -1676,6 +1690,57 @@
  */
 #define BGE_PCIE_CTL0                  0x7c00
 #define BGE_PCIE_CTL1                  0x7e2c
+
+/*
+ * NVRAM Control registers
+ */
+#define        BGE_NVRAM_CMD                   0x7000
+#define        BGE_NVRAM_STAT                  0x7004
+#define        BGE_NVRAM_WRDATA                0x7008
+#define        BGE_NVRAM_ADDR                  0x700c
+#define        BGE_NVRAM_RDDATA                0x7010
+#define        BGE_NVRAM_CFG1                  0x7014
+#define        BGE_NVRAM_CFG2                  0x7018
+#define        BGE_NVRAM_CFG3                  0x701c
+#define        BGE_NVRAM_SWARB                 0x7020
+#define        BGE_NVRAM_ACCESS                0x7024
+#define        BGE_NVRAM_WRITE1                0x7028
+
+#define        BGE_NVRAMCMD_RESET              0x00000001
+#define        BGE_NVRAMCMD_DONE               0x00000008
+#define        BGE_NVRAMCMD_START              0x00000010
+#define        BGE_NVRAMCMD_WR                 0x00000020 /* 1 = wr, 0 = rd */
+#define        BGE_NVRAMCMD_ERASE              0x00000040
+#define        BGE_NVRAMCMD_FIRST              0x00000080
+#define        BGE_NVRAMCMD_LAST               0x00000100
+
+#define        BGE_NVRAM_READCMD \
+       (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
+       BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE)
+#define        BGE_NVRAM_WRITECMD \
+       (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
+       BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR)
+
+#define        BGE_NVRAMSWARB_SET0             0x00000001
+#define        BGE_NVRAMSWARB_SET1             0x00000002
+#define        BGE_NVRAMSWARB_SET2             0x00000003
+#define        BGE_NVRAMSWARB_SET3             0x00000004
+#define        BGE_NVRAMSWARB_CLR0             0x00000010
+#define        BGE_NVRAMSWARB_CLR1             0x00000020
+#define        BGE_NVRAMSWARB_CLR2             0x00000040
+#define        BGE_NVRAMSWARB_CLR3             0x00000080
+#define        BGE_NVRAMSWARB_GNT0             0x00000100
+#define        BGE_NVRAMSWARB_GNT1             0x00000200
+#define        BGE_NVRAMSWARB_GNT2             0x00000400
+#define        BGE_NVRAMSWARB_GNT3             0x00000800
+#define        BGE_NVRAMSWARB_REQ0             0x00001000
+#define        BGE_NVRAMSWARB_REQ1             0x00002000
+#define        BGE_NVRAMSWARB_REQ2             0x00004000
+#define        BGE_NVRAMSWARB_REQ3             0x00008000
+
+#define        BGE_NVRAMACC_ENABLE             0x00000001
+#define        BGE_NVRAMACC_WRENABLE           0x00000002
+
 /*
  * TLP Control Register
  * Applicable to BCM5721 and BCM5751 only
@@ -1720,6 +1785,7 @@
 /* Misc. config register */
 #define BGE_MISCCFG_RESET_CORE_CLOCKS  0x00000001
 #define BGE_MISCCFG_TIMER_PRESCALER    0x000000FE
+#define BGE_MISCCFG_EPHY_IDDQ          0x00200000
 
 #define BGE_32BITTIME_66MHZ            (0x41 << 1)
 
@@ -1997,6 +2063,7 @@
  * Offset of MAC address inside EEPROM.
  */
 #define BGE_EE_MAC_OFFSET              0x7C
+#define BGE_EE_MAC_OFFSET_5906         0x10
 #define BGE_EE_HWCFG_OFFSET            0xC8
 
 #define BGE_HWCFG_VOLTAGE              0x00000003



Home | Main Index | Thread Index | Old Index