Date: Fri, 14 Oct 2005 12:15:19 -0700 (PDT) From: Doug Ambrisko <ambrisko@ambrisko.com> To: freebsd-net@freebsd.org Subject: bge BCM5721/BCM5750 fixes to work with IPMI Message-ID: <200510141915.j9EJFJ8T059154@ambrisko.com>
next in thread | raw e-mail | index | archive | help
Here are some first pass patches to make the bge driver not break IPMI. This was tested on a Dell PE850: bge0: <Broadcom BCM5721 Gigabit Ethernet, ASIC rev. 0x4101> mem 0xfe6f0000-0xfe6fffff irq 16 at device 0.0 on pci4 miibus1: <MII bus> on bge0 brgphy0: <BCM5750 10/100/1000baseTX PHY> on miibus1 brgphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseTX, 1000baseTX-FDX, auto It shouldn't break other bge cards and it might work with other Broadcom IPMI capable chips (they seem to have different usages). Please let me know how this goes. I gleaned this info. from the Linux drivers. YMMV. Doug A. Index: if_bge.c =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/bge/if_bge.c,v retrieving revision 1.94 diff -u -p -r1.94 if_bge.c --- if_bge.c 4 Sep 2005 06:35:59 -0000 1.94 +++ if_bge.c 14 Oct 2005 19:11:11 -0000 @@ -264,6 +264,11 @@ static int bge_miibus_readreg (device_t, static int bge_miibus_writereg (device_t, int, int, int); static void bge_miibus_statchg (device_t); +#define BGE_RESET_START 1 +#define BGE_RESET_STOP 2 +static void bge_sig_post_reset(struct bge_softc *, int); +static void bge_sig_legacy(struct bge_softc *, int); +static void bge_sig_pre_reset(struct bge_softc *, int); static void bge_reset (struct bge_softc *); static device_method_t bge_methods[] = { @@ -1187,6 +1192,78 @@ bge_setmulti(sc) return; } +static void +bge_sig_pre_reset(sc, type) + struct bge_softc *sc; + int type; +{ + bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); + + if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) { + switch (type) { + case BGE_RESET_START: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */ + break; + case BGE_RESET_STOP: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */ + break; + } + } +} + +static void +bge_sig_post_reset(sc, type) + struct bge_softc *sc; + int type; +{ + if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) { + switch (type) { + case BGE_RESET_START: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000001); + /* START DONE */ + break; + case BGE_RESET_STOP: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000002); + break; + } + } +} + +static void +bge_sig_legacy(sc, type) + struct bge_softc *sc; + int type; +{ + if (sc->bge_asf_mode) { + switch (type) { + case BGE_RESET_START: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */ + break; + case BGE_RESET_STOP: + bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */ + break; + } + } +} + +void bge_stop_fw(struct bge_softc *); +void +bge_stop_fw(sc) + struct bge_softc *sc; +{ + int i; + + if (sc->bge_asf_mode) { + bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW, BGE_FW_PAUSE); + + for (i = 0; i < 100; i++ ) { + if (!(CSR_READ_4(sc, BGE_CPU_EVENT) & (1 << 14))) + break; + DELAY(10); + } + } +} + /* * Do endian, PCI and DMA initialization. Also check the on-board ROM * self-test results. @@ -1284,10 +1361,13 @@ bge_chipinit(sc) /* * Set up general mode register. */ + CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_MODECTL_WORDSWAP_NONFRAME| BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA| BGE_MODECTL_MAC_ATTN_INTR|BGE_MODECTL_HOST_SEND_BDS| BGE_MODECTL_TX_NO_PHDR_CSUM|BGE_MODECTL_RX_NO_PHDR_CSUM); + BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + /* * Disable memory write invalidate. Apparently it is not supported @@ -2326,8 +2406,28 @@ bge_attach(dev) } } + sc->bge_asf_mode = 0; + if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) + == BGE_MAGIC_NUMBER) { + if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG) + & BGE_HWCFG_ASF) { + sc->bge_asf_mode |= ASF_ENABLE; + if (CSR_READ_4(sc, BGE_MODE_CTL) + & BGE_MODECTL_STACKUP ) { + sc->bge_asf_mode |= ASF_STACKUP; + } + if (sc->bge_asicrev == BGE_ASICREV_BCM5750) { + sc->bge_asf_mode |= ASF_NEW_HANDSHAKE; + } + } + } + /* Try to reset the chip. */ + bge_stop_fw(sc); + bge_sig_pre_reset(sc, BGE_RESET_STOP); bge_reset(sc); + bge_sig_legacy(sc, BGE_RESET_STOP); + bge_sig_post_reset(sc, BGE_RESET_STOP); if (bge_chipinit(sc)) { printf("bge%d: chip initialization failed\n", sc->bge_unit); @@ -2636,11 +2736,14 @@ bge_reset(sc) sc->bge_asicrev != BGE_ASICREV_BCM5750) CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); +#ifdef ASF /* this conflicts with ASF/IPMI and is done in bge_sig_pre_reset*/ /* * Prevent PXE restart: write a magic number to the * general communications memory at 0xB50. */ bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); +#endif + /* * Poll the value location we just wrote until * we see the 1's complement of the magic number. @@ -2676,6 +2779,8 @@ bge_reset(sc) /* Fix up byte swapping */ CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_MODECTL_BYTESWAP_NONFRAME| BGE_MODECTL_BYTESWAP_DATA); + if (sc->bge_asf_mode & ASF_STACKUP) + BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); CSR_WRITE_4(sc, BGE_MAC_MODE, 0); @@ -3338,7 +3443,13 @@ bge_init_locked(sc) /* Cancel pending I/O and flush buffers. */ bge_stop(sc); + + bge_stop_fw(sc); + bge_sig_pre_reset(sc, BGE_RESET_START); bge_reset(sc); + bge_sig_legacy(sc, BGE_RESET_START); + bge_sig_post_reset(sc, BGE_RESET_START); + bge_chipinit(sc); /* @@ -3728,7 +3839,16 @@ bge_stop(sc) /* * Tell firmware we're shutting down. */ - BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + + bge_stop_fw(sc); + bge_sig_pre_reset(sc, BGE_RESET_STOP); + bge_reset(sc); + bge_sig_legacy(sc, BGE_RESET_STOP); + bge_sig_post_reset(sc, BGE_RESET_STOP); + if (sc->bge_asf_mode & ASF_STACKUP) + BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + else + BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); /* Free the RX lists. */ bge_free_rx_ring_std(sc); Index: if_bgereg.h =================================================================== RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/bge/if_bgereg.h,v retrieving revision 1.36 diff -u -p -r1.36 if_bgereg.h --- if_bgereg.h 10 Jun 2005 16:49:05 -0000 1.36 +++ if_bgereg.h 14 Oct 2005 19:11:11 -0000 @@ -74,6 +74,8 @@ #define BGE_SOFTWARE_GENCOMM 0x00000B50 #define BGE_SOFTWARE_GENCOMM_SIG 0x00000B54 #define BGE_SOFTWARE_GENCOMM_NICCFG 0x00000B58 +#define BGE_SOFTWARE_GENCOMM_FW 0x00000B78 +#define BGE_FW_PAUSE 0x00000002 #define BGE_SOFTWARE_GENCOMM_END 0x00000FFF #define BGE_UNMAPPED 0x00001000 #define BGE_UNMAPPED_END 0x00001FFF @@ -1620,6 +1622,7 @@ #define BGE_MODE_CTL 0x6800 #define BGE_MISC_CFG 0x6804 #define BGE_MISC_LOCAL_CTL 0x6808 +#define BGE_CPU_EVENT 0x6810 #define BGE_EE_ADDR 0x6838 #define BGE_EE_DATA 0x683C #define BGE_EE_CTL 0x6840 @@ -1928,6 +1931,7 @@ struct bge_status_block { #define BGE_HWCFG_VOLTAGE 0x00000003 #define BGE_HWCFG_PHYLED_MODE 0x0000000C #define BGE_HWCFG_MEDIA 0x00000030 +#define BGE_HWCFG_ASF 0x00000080 #define BGE_VOLTAGE_1POINT3 0x00000000 #define BGE_VOLTAGE_1POINT8 0x00000001 @@ -2312,6 +2316,10 @@ struct bge_bcom_hack { int val; }; +#define ASF_ENABLE 1 +#define ASF_NEW_HANDSHAKE 2 +#define ASF_STACKUP 4 + struct bge_softc { struct ifnet *bge_ifp; /* interface info */ device_t bge_dev; @@ -2332,6 +2340,7 @@ struct bge_softc { u_int8_t bge_asicrev; u_int8_t bge_chiprev; u_int8_t bge_no_3_led; + u_int8_t bge_asf_mode; u_int8_t bge_pcie; struct bge_ring_data bge_ldata; /* rings */ struct bge_chain_data bge_cdata; /* mbufs */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510141915.j9EJFJ8T059154>