Doug Ambrisko wrote: >I'd like to commit my final bge version of the IPMI patch to keep IPMI >working when FreeBSD attaches and also when the NIC is downed. >I also have patches for the bce to do the same that I sent to David. >This has various reviews and testing in the wild. I want to give >a heads up since there have been changes in the bge driver recently. >I'd like to not hold off on this anymore. > > code looks good but could you add a bunch of comments explaining the handshake and how this works. (be verbose please) >Thanks, > >Doug A. > >Index: if_bge.c >=================================================================== >RCS file: /cvs/src/sys/dev/bge/if_bge.c,v >retrieving revision 1.140 >diff -u -p -r1.140 if_bge.c >--- if_bge.c 24 Aug 2006 14:41:16 -0000 1.140 >+++ if_bge.c 7 Sep 2006 18:31:59 -0000 >_at__at_ -326,6 +326,7 _at__at_ static void bge_dma_free(struct bge_soft > static void bge_txeof(struct bge_softc *); > static void bge_rxeof(struct bge_softc *); > >+static void bge_asf_driver_up (struct bge_softc *); > static void bge_tick_locked(struct bge_softc *); > static void bge_tick(void *); > static void bge_stats_update(struct bge_softc *); >_at__at_ -376,7 +377,12 _at__at_ static void bge_miibus_statchg(device_t) > static void bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); > #endif > >-static void bge_reset(struct bge_softc *); >+#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 int bge_reset(struct bge_softc *); > static void bge_link_upd(struct bge_softc *); > > static device_method_t bge_methods[] = { >_at__at_ -646,7 +652,6 _at__at_ bge_miibus_statchg(device_t dev) > { > struct bge_softc *sc; > struct mii_data *mii; >- > sc = device_get_softc(dev); > mii = device_get_softc(sc->bge_miibus); > >_at__at_ -968,6 +973,81 _at__at_ bge_setmulti(struct bge_softc *sc) > CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); > } > >+static void >+bge_sig_pre_reset(sc, type) >+ struct bge_softc *sc; >+ int type; >+{ >+ if (sc->bge_asf_mode) >+ 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); >+ CSR_WRITE_4(sc, BGE_CPU_EVENT, >+ CSR_READ_4(sc, BGE_CPU_EVENT) != (1 << 14)); >+ >+ 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. >_at__at_ -978,7 +1058,7 _at__at_ bge_chipinit(struct bge_softc *sc) > uint32_t dma_rw_ctl; > int i; > >- /* Set endian type before we access any non-PCI registers. */ >+ /* Set endianness before we access any non-PCI registers. */ > pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4); > > /* >_at__at_ -1069,6 +1149,9 _at__at_ bge_chipinit(struct bge_softc *sc) > BGE_MODECTL_MAC_ATTN_INTR|BGE_MODECTL_HOST_SEND_BDS| > BGE_MODECTL_TX_NO_PHDR_CSUM); > >+ if (sc->bge_asf_mode & ASF_STACKUP) >+ BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); >+ > /* > * Disable memory write invalidate. Apparently it is not supported > * properly by these devices. >_at__at_ -1992,6 +2075,7 _at__at_ bge_attach(device_t dev) > uint32_t mac_tmp = 0; > u_char eaddr[6]; > int error = 0, rid; >+ int trys; > > sc = device_get_softc(dev); > sc->bge_dev = dev; >_at__at_ -2059,7 +2143,38 _at__at_ bge_attach(device_t dev) > sc->bge_flags |= BGE_FLAG_PCIX; > > /* Try to reset the chip. */ >- bge_reset(sc); >+ if (bge_reset(sc)) { >+ device_printf(sc->bge_dev, "chip reset failed\n"); >+ bge_release_resources(sc); >+ error = ENXIO; >+ goto fail; >+ } >+ >+ 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; >+ 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 again the nice way. */ >+ bge_stop_fw(sc); >+ bge_sig_pre_reset(sc, BGE_RESET_STOP); >+ if (bge_reset(sc)) { >+ device_printf(sc->bge_dev, "chip reset failed\n"); >+ bge_release_resources(sc); >+ error = ENXIO; >+ goto fail; >+ } >+ >+ bge_sig_legacy(sc, BGE_RESET_STOP); >+ bge_sig_post_reset(sc, BGE_RESET_STOP); > > if (bge_chipinit(sc)) { > device_printf(sc->bge_dev, "chip initialization failed\n"); >_at__at_ -2188,13 +2303,26 _at__at_ bge_attach(device_t dev) > /* > * Do transceiver setup. > */ >+ BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); >+again: >+ bge_asf_driver_up(sc); >+ >+ trys = 0; > if (mii_phy_probe(dev, &sc->bge_miibus, > bge_ifmedia_upd, bge_ifmedia_sts)) { >+ if (trys++ < 4) { >+ device_printf(sc->bge_dev, "Try again\n"); >+ bge_miibus_writereg(sc->bge_dev, 1, MII_BMCR, BMCR_RESET); >+ goto again; >+ } >+ > device_printf(sc->bge_dev, "MII without any PHY!\n"); > bge_release_resources(sc); > error = ENXIO; > goto fail; > } >+ if (sc->bge_asf_mode & ASF_STACKUP) >+ BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); > } > > /* >_at__at_ -2295,7 +2423,7 _at__at_ bge_release_resources(struct bge_softc * > BGE_LOCK_DESTROY(sc); > } > >-static void >+static int > bge_reset(struct bge_softc *sc) > { > device_t dev; >_at__at_ -2381,7 +2509,7 _at__at_ bge_reset(struct bge_softc *sc) > > if (i == BGE_TIMEOUT) { > device_printf(sc->bge_dev, "firmware handshake timed out\n"); >- return; >+ return(0); > } > > /* >_at__at_ -2401,6 +2529,8 _at__at_ bge_reset(struct bge_softc *sc) > /* Fix up byte swapping. */ > CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS| > 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); > >_at__at_ -2427,6 +2557,8 _at__at_ bge_reset(struct bge_softc *sc) > CSR_WRITE_4(sc, 0x7c00, v | (1<<25)); > } > DELAY(10000); >+ >+ return(0); > } > > /* >_at__at_ -2740,6 +2872,25 _at__at_ bge_intr(void *xsc) > } > > static void >+bge_asf_driver_up(struct bge_softc *sc) >+{ >+ if (sc->bge_asf_mode & ASF_STACKUP) { >+ /* Send ASF heartbeat aprox. every 2s */ >+ if (sc->bge_asf_count) >+ sc->bge_asf_count --; >+ else { >+ sc->bge_asf_count = 5; >+ bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW, >+ BGE_FW_DRV_ALIVE); >+ bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_LEN, 4); >+ bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_DATA, 3); >+ CSR_WRITE_4(sc, BGE_CPU_EVENT, >+ CSR_READ_4(sc, BGE_CPU_EVENT) != (1 << 14)); >+ } >+ } >+} >+ >+static void > bge_tick_locked(struct bge_softc *sc) > { > struct mii_data *mii = NULL; >_at__at_ -2753,7 +2904,9 _at__at_ bge_tick_locked(struct bge_softc *sc) > > if ((sc->bge_flags & BGE_FLAG_TBI) == 0) { > mii = device_get_softc(sc->bge_miibus); >- mii_tick(mii); >+ /* Don't mess with the PHY in IPMI/ASF mode */ >+ if (!((sc->bge_asf_mode & ASF_STACKUP) && (sc->bge_link))) >+ mii_tick(mii); > } else { > /* > * Since in TBI mode auto-polling can't be used we should poll >_at__at_ -2770,6 +2923,8 _at__at_ bge_tick_locked(struct bge_softc *sc) > } > } > >+ bge_asf_driver_up(sc); >+ > callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc); > } > >_at__at_ -3116,7 +3271,13 _at__at_ bge_init_locked(struct bge_softc *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); > > /* >_at__at_ -3199,7 +3360,7 _at__at_ bge_init_locked(struct bge_softc *sc) > CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 1); > } else > #endif >- >+ > /* Enable host interrupts. */ > { > BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA); >_at__at_ -3551,7 +3712,16 _at__at_ bge_stop(struct bge_softc *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: /cvs/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 7 Sep 2006 18:31:59 -0000 >_at__at_ -74,6 +74,11 _at__at_ > #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_DRV_ALIVE 0x00000001 >+#define BGE_FW_PAUSE 0x00000002 >+#define BGE_SOFTWARE_GENNCOMM_FW_LEN 0x00000B7C >+#define BGE_SOFTWARE_GENNCOMM_FW_DATA 0x00000B80 > #define BGE_SOFTWARE_GENCOMM_END 0x00000FFF > #define BGE_UNMAPPED 0x00001000 > #define BGE_UNMAPPED_END 0x00001FFF >_at__at_ -1651,6 +1656,7 _at__at_ > #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 >_at__at_ -2063,6 +2069,7 _at__at_ 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 >_at__at_ -2433,6 +2440,10 _at__at_ 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; >_at__at_ -2452,8 +2463,10 _at__at_ struct bge_softc { > #define BGE_FLAG_PCIX 0x00000010 > #define BGE_FLAG_PCIE 0x00000020 > uint32_t bge_chipid; >- uint8_t bge_asicrev; >- uint8_t bge_chiprev; >+ uint8_t bge_asicrev; >+ uint8_t bge_chiprev; >+ uint8_t bge_asf_mode; >+ uint8_t bge_asf_count; > struct bge_ring_data bge_ldata; /* rings */ > struct bge_chain_data bge_cdata; /* mbufs */ > uint16_t bge_tx_saved_considx; >_______________________________________________ >freebsd-current_at_freebsd.org mailing list >http://lists.freebsd.org/mailman/listinfo/freebsd-current >To unsubscribe, send any mail to "freebsd-current-unsubscribe_at_freebsd.org" > >Received on Thu Sep 07 2006 - 16:46:00 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:00 UTC