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