Module Name: src Committed By: msaitoh Date: Thu Jan 28 03:09:13 UTC 2010
Modified Files: src/sys/dev/pci: if_bge.c if_bgereg.h if_bgevar.h Log Message: - Introduce IPMI and ASF related code from FreeBSD. It fixes some problems which occured in netboot on sparc64 and PR#32767 - move the code of disabling host interrput in bge_stop() like linux tg3 driver. - fix the return value of bge_eeprom_getbyte(). - remove an unused structure. - KNF To generate a diff of this commit: cvs rdiff -u -r1.176 -r1.177 src/sys/dev/pci/if_bge.c cvs rdiff -u -r1.54 -r1.55 src/sys/dev/pci/if_bgereg.h cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pci/if_bgevar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_bge.c diff -u src/sys/dev/pci/if_bge.c:1.176 src/sys/dev/pci/if_bge.c:1.177 --- src/sys/dev/pci/if_bge.c:1.176 Mon Jan 25 10:25:30 2010 +++ src/sys/dev/pci/if_bge.c Thu Jan 28 03:09:13 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bge.c,v 1.176 2010/01/25 10:25:30 martin Exp $ */ +/* $NetBSD: if_bge.c,v 1.177 2010/01/28 03:09:13 msaitoh Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.176 2010/01/25 10:25:30 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.177 2010/01/28 03:09:13 msaitoh Exp $"); #include "vlan.h" #include "rnd.h" @@ -180,64 +180,87 @@ #define NBGE_RX_THRESH (sizeof(bge_rx_threshes) / sizeof(bge_rx_threshes[0])) /* XXX patchable; should be sysctl'able */ -static int bge_auto_thresh = 1; -static int bge_rx_thresh_lvl; +static int bge_auto_thresh = 1; +static int bge_rx_thresh_lvl; -static int bge_rxthresh_nodenum; +static int bge_rxthresh_nodenum; typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_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_fw(struct bge_softc *, uint8_t[]); -static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]); -static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]); -static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]); -static int bge_get_eaddr(struct bge_softc *, uint8_t[]); - -static void bge_tick(void *); -static void bge_stats_update(struct bge_softc *); -static void bge_stats_update_regs(struct bge_softc *); -static int bge_encap(struct bge_softc *, struct mbuf *, uint32_t *); - -static int bge_intr(void *); -static void bge_start(struct ifnet *); -static int bge_ioctl(struct ifnet *, u_long, void *); -static int bge_init(struct ifnet *); -static void bge_stop(struct ifnet *, int); -static void bge_watchdog(struct ifnet *); -static int bge_ifmedia_upd(struct ifnet *); -static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); +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 int bge_get_eaddr_fw(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr(struct bge_softc *, uint8_t[]); + +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(void *); +static void bge_stats_update(struct bge_softc *); +static void bge_stats_update_regs(struct bge_softc *); +static int bge_encap(struct bge_softc *, struct mbuf *, uint32_t *); + +static int bge_intr(void *); +static void bge_start(struct ifnet *); +static int bge_ioctl(struct ifnet *, u_long, void *); +static int bge_init(struct ifnet *); +static void bge_stop(struct ifnet *, int); +static void bge_watchdog(struct ifnet *); +static int bge_ifmedia_upd(struct ifnet *); +static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); + +static uint8_t bge_nvram_getbyte(struct bge_softc *, int, uint8_t *); +static int bge_read_nvram(struct bge_softc *, uint8_t *, int, int); + +static uint8_t bge_eeprom_getbyte(struct bge_softc *, int, uint8_t *); +static int bge_read_eeprom(struct bge_softc *, void *, int, int); +static void bge_setmulti(struct bge_softc *); -static void bge_setmulti(struct bge_softc *); - -static void bge_handle_events(struct bge_softc *); -static int bge_alloc_jumbo_mem(struct bge_softc *); +static void bge_handle_events(struct bge_softc *); +static int bge_alloc_jumbo_mem(struct bge_softc *); #if 0 /* XXX */ -static void bge_free_jumbo_mem(struct bge_softc *); +static void bge_free_jumbo_mem(struct bge_softc *); #endif -static void *bge_jalloc(struct bge_softc *); -static void bge_jfree(struct mbuf *, void *, size_t, void *); -static int bge_newbuf_std(struct bge_softc *, int, struct mbuf *, +static void *bge_jalloc(struct bge_softc *); +static void bge_jfree(struct mbuf *, void *, size_t, void *); +static int bge_newbuf_std(struct bge_softc *, int, struct mbuf *, bus_dmamap_t); -static int bge_newbuf_jumbo(struct bge_softc *, int, struct mbuf *); -static int bge_init_rx_ring_std(struct bge_softc *); -static void bge_free_rx_ring_std(struct bge_softc *); -static int bge_init_rx_ring_jumbo(struct bge_softc *); -static void bge_free_rx_ring_jumbo(struct bge_softc *); -static void bge_free_tx_ring(struct bge_softc *); -static int bge_init_tx_ring(struct bge_softc *); - -static int bge_chipinit(struct bge_softc *); -static int bge_blockinit(struct bge_softc *); -static int bge_setpowerstate(struct bge_softc *, int); - -static void bge_reset(struct bge_softc *); -static void bge_link_upd(struct bge_softc *); +static int bge_newbuf_jumbo(struct bge_softc *, int, struct mbuf *); +static int bge_init_rx_ring_std(struct bge_softc *); +static void bge_free_rx_ring_std(struct bge_softc *); +static int bge_init_rx_ring_jumbo(struct bge_softc *); +static void bge_free_rx_ring_jumbo(struct bge_softc *); +static void bge_free_tx_ring(struct bge_softc *); +static int bge_init_tx_ring(struct bge_softc *); + +static int bge_chipinit(struct bge_softc *); +static int bge_blockinit(struct bge_softc *); +static int bge_setpowerstate(struct bge_softc *, int); +static uint32_t bge_readmem_ind(struct bge_softc *, int); +static void bge_writemem_ind(struct bge_softc *, int, int); +static void bge_writembx(struct bge_softc *, int, int); +static void bge_writemem_direct(struct bge_softc *, int, int); +static void bge_writereg_ind(struct bge_softc *, int, int); +static void bge_set_max_readrq(struct bge_softc *); + +static int bge_miibus_readreg(device_t, int, int); +static void 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_stop_fw(struct bge_softc *); +static int bge_reset(struct bge_softc *); +static void bge_link_upd(struct bge_softc *); #ifdef BGE_DEBUG #define DPRINTF(x) if (bgedebug) printf x @@ -697,6 +720,8 @@ { 0, NULL } }; +static int bge_allow_asf = 1; + CFATTACH_DECL_NEW(bge, sizeof(struct bge_softc), bge_probe, bge_attach, NULL, NULL); @@ -717,6 +742,31 @@ pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_MEMWIN_DATA, val); } +/* + * PCI Express only + */ +static void +bge_set_max_readrq(struct bge_softc *sc) +{ + device_t dev; + pcireg_t val; + + dev = sc->bge_dev; + + val = pci_conf_read(sc->sc_pc, sc->sc_pcitag, sc->bge_expcap + + PCI_PCIE_DCSR); + if ((val & PCI_PCIE_DCSR_MAX_READ_REQ) != + BGE_PCIE_DEVCTL_MAX_READRQ_4096) { + printf("adjust device control 0x%04x ", + val); + val &= ~PCI_PCIE_DCSR_MAX_READ_REQ; + val |= BGE_PCIE_DEVCTL_MAX_READRQ_4096; + pci_conf_write(sc->sc_pc, sc->sc_pcitag, sc->bge_expcap + + PCI_PCIE_DCSR, val); + printf("-> 0x%04x\n", val); + } +} + #ifdef notdef static uint32_t bge_readreg_ind(struct bge_softc *sc, int off) @@ -855,7 +905,7 @@ if (i == BGE_TIMEOUT * 10) { aprint_error_dev(sc->bge_dev, "eeprom read timed out\n"); - return 0; + return 1; } /* Get result. */ @@ -971,7 +1021,7 @@ } CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | - BGE_MIPHY(phy) | BGE_MIREG(reg)|val); + BGE_MIPHY(phy) | BGE_MIREG(reg) | val); for (i = 0; i < BGE_TIMEOUT; i++) { delay(10); @@ -1597,36 +1647,82 @@ CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); } -const int bge_swapbits[] = { - 0, - BGE_MODECTL_BYTESWAP_DATA, - BGE_MODECTL_WORDSWAP_DATA, - BGE_MODECTL_BYTESWAP_NONFRAME, - BGE_MODECTL_WORDSWAP_NONFRAME, - - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA, - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_BYTESWAP_NONFRAME, - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_NONFRAME, - - BGE_MODECTL_WORDSWAP_DATA|BGE_MODECTL_BYTESWAP_NONFRAME, - BGE_MODECTL_WORDSWAP_DATA|BGE_MODECTL_WORDSWAP_NONFRAME, - - BGE_MODECTL_BYTESWAP_NONFRAME|BGE_MODECTL_WORDSWAP_NONFRAME, - - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA| - BGE_MODECTL_BYTESWAP_NONFRAME, - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA| - BGE_MODECTL_WORDSWAP_NONFRAME, - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_BYTESWAP_NONFRAME| - BGE_MODECTL_WORDSWAP_NONFRAME, - BGE_MODECTL_WORDSWAP_DATA|BGE_MODECTL_BYTESWAP_NONFRAME| - BGE_MODECTL_WORDSWAP_NONFRAME, +static void +bge_sig_pre_reset(sc, type) + struct bge_softc *sc; + int type; +{ + /* + * Some chips don't like this so only do this if ASF is enabled + */ + if (sc->bge_asf_mode) + bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); - BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA| - BGE_MODECTL_BYTESWAP_NONFRAME|BGE_MODECTL_WORDSWAP_NONFRAME, -}; + 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; + } + } +} -int bge_swapindex = 0; +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; + } + } +} + +static 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 @@ -1726,14 +1822,15 @@ BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5704) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; - pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, dma_rw_ctl); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, BGE_PCI_DMA_RW_CTL, + dma_rw_ctl); /* * Set up general mode register. */ CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS | - BGE_MODECTL_MAC_ATTN_INTR | BGE_MODECTL_HOST_SEND_BDS | - BGE_MODECTL_TX_NO_PHDR_CSUM | BGE_MODECTL_RX_NO_PHDR_CSUM); + BGE_MODECTL_MAC_ATTN_INTR | BGE_MODECTL_HOST_SEND_BDS | + BGE_MODECTL_TX_NO_PHDR_CSUM | BGE_MODECTL_RX_NO_PHDR_CSUM); /* * BCM5701 B5 have a bug causing data corruption when using @@ -1746,6 +1843,12 @@ BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_FORCE_PCI32); /* + * Tell the firmware the driver is running + */ + 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. */ @@ -1780,12 +1883,12 @@ static int bge_blockinit(struct bge_softc *sc) { - volatile struct bge_rcb *rcb; - bus_size_t rcb_addr; - int i; - struct ifnet *ifp = &sc->ethercom.ec_if; - bge_hostaddr taddr; - uint32_t val; + volatile struct bge_rcb *rcb; + bus_size_t rcb_addr; + int i; + struct ifnet *ifp = &sc->ethercom.ec_if; + bge_hostaddr taddr; + uint32_t val; /* * Initialize the memory window pointer register so that @@ -2101,16 +2204,15 @@ BGE_MACMODE_FRMHDR_DMA_ENB; if (sc->bge_flags & BGE_PHY_FIBER_TBI) - val |= BGE_PORTMODE_TBI; + val |= BGE_PORTMODE_TBI; else if (sc->bge_flags & BGE_PHY_FIBER_MII) - val |= BGE_PORTMODE_GMII; + val |= BGE_PORTMODE_GMII; else - val |= BGE_PORTMODE_MII; + val |= BGE_PORTMODE_MII; /* Turn on DMA, clear stats */ CSR_WRITE_4(sc, BGE_MAC_MODE, val); - /* Set misc. local control, enable interrupts on attentions */ sc->bge_local_ctrl_reg = BGE_MLC_INTR_ONATTN | BGE_MLC_AUTO_EEPROM; @@ -2195,9 +2297,8 @@ if (sc->bge_flags & BGE_TSO) { /* XXX: magic value from Linux driver */ CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE | 0x08); - } else { + } else CSR_WRITE_4(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); - } /* Turn on send BD initiator state machine */ CSR_WRITE_4(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); @@ -2469,9 +2570,10 @@ } if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PCIEXPRESS, - NULL, NULL) != 0) { + &sc->bge_expcap, NULL) != 0) { /* PCIe */ sc->bge_flags |= BGE_PCIE; + bge_set_max_readrq(sc); } else if ((pci_conf_read(sc->sc_pc, sc->sc_pcitag, BGE_PCI_PCISTATE) & BGE_PCISTATE_PCI_BUSMODE) == 0) { /* PCI-X */ @@ -2628,6 +2730,29 @@ DPRINTFN(5, ("bge_reset\n")); bge_reset(sc); + sc->bge_asf_mode = 0; + if (bge_allow_asf && (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 (BGE_ASICREV(sc->bge_chipid) == 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)) { + aprint_error_dev(sc->bge_dev, "chip reset failed\n"); + } + + bge_sig_legacy(sc, BGE_RESET_STOP); + bge_sig_post_reset(sc, BGE_RESET_STOP); + if (bge_chipinit(sc)) { aprint_error_dev(sc->bge_dev, "chip initialization failed\n"); bge_release_resources(sc); @@ -2802,17 +2927,24 @@ if (sc->bge_flags & BGE_PHY_FIBER_TBI) { ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd, bge_ifmedia_sts); - ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); - ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_1000_SX|IFM_FDX, + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER |IFM_1000_SX, 0, NULL); + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER | IFM_1000_SX|IFM_FDX, 0, NULL); - ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - ifmedia_set(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO); + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->bge_ifmedia, IFM_ETHER | IFM_AUTO); /* Pretend the user requested this setting */ sc->bge_ifmedia.ifm_media = sc->bge_ifmedia.ifm_cur->ifm_media; } else { /* - * Do transceiver setup. + * Do transceiver setup and tell the firmware the + * driver is down so we can try to get access the + * probe if ASF is running. Retry a couple of times + * if we get a conflict with the ASF firmware accessing + * the PHY. */ + BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + bge_asf_driver_up(sc); + ifmedia_init(&sc->bge_mii.mii_media, 0, bge_ifmedia_upd, bge_ifmedia_sts); mii_attach(sc->bge_dev, &sc->bge_mii, 0xffffffff, @@ -2828,6 +2960,12 @@ } else ifmedia_set(&sc->bge_mii.mii_media, IFM_ETHER|IFM_AUTO); + + /* + * Now tell the firmware we are going up after probing the PHY + */ + if (sc->bge_asf_mode & ASF_STACKUP) + BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); } /* @@ -2883,10 +3021,11 @@ free(sc->bge_vpd_readonly, M_DEVBUF); } -static void +static int bge_reset(struct bge_softc *sc) { uint32_t cachesize, command, pcistate, new_pcistate; + pcireg_t devctl; int i, val; void (*write_op)(struct bge_softc *, int, int); @@ -2916,6 +3055,13 @@ BGE_IS_5755_PLUS(sc)) CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0); + /* + * Write the magic number to SRAM at offset 0xB50. + * When firmware finishes its initialization it will + * write ~BGE_MAGIC_NUMBER to the same location. + */ + bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); + val = BGE_MISCCFG_RESET_CORE_CLOCKS | (65<<1); /* * XXX: from FreeBSD/Linux; no documentation @@ -2970,15 +3116,16 @@ BGE_PCI_UNKNOWN0, reg | (1 << 15)); } - /* - * XXX: Magic Numbers. - * Sets maximal PCI-e payload and clears any PCI-e errors. - * Should be replaced with references to PCI config-space - * capability block for PCI-Express. - */ + devctl = pci_conf_read(sc->sc_pc, sc->sc_pcitag, + sc->bge_expcap + PCI_PCIE_DCSR); + /* Clear enable no snoop and disable relaxed ordering. */ + devctl &= ~(0x0010 | PCI_PCIE_DCSR_ENA_NO_SNOOP); + /* Set PCIE max payload size to 128. */ + devctl &= ~(0x00e0); pci_conf_write(sc->sc_pc, sc->sc_pcitag, - BGE_PCI_CONF_DEV_CTRL, 0xf5000); - + sc->bge_expcap + PCI_PCIE_DCSR, devctl); + pci_conf_write(sc->sc_pc, sc->sc_pcitag, + sc->bge_expcap + PCI_PCIE_DSR, 0); } /* Reset some of the PCI state that got zapped by reset */ @@ -2998,12 +3145,6 @@ CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | marbmode); } - /* - * Prevent PXE restart: write a magic number to the - * general communications memory at 0xB50. - */ - bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); - if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) { for (i = 0; i < BGE_TIMEOUT; i++) { val = CSR_READ_4(sc, BGE_VCPU_STATUS); @@ -3013,7 +3154,7 @@ } if (i == BGE_TIMEOUT) { aprint_error_dev(sc->bge_dev, "reset timed out\n"); - return; + return 1; } } else { /* @@ -3029,17 +3170,9 @@ DELAY(10); } - if (i >= BGE_TIMEOUT && (!(sc->bge_flags & BGE_NO_EEPROM))) { + if (i >= BGE_TIMEOUT && (!(sc->bge_flags & BGE_NO_EEPROM))) 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_flags & BGE_PCIE) == 0) - return; - } } /* @@ -3078,6 +3211,10 @@ /* Fix up byte swapping */ CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS); + /* Tell the ASF firmware we are up */ + if (sc->bge_asf_mode & ASF_STACKUP) + BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + CSR_WRITE_4(sc, BGE_MAC_MODE, 0); /* @@ -3106,6 +3243,8 @@ CSR_WRITE_4(sc, 0x7c00, v | (1<<25)); } DELAY(10000); + + return 0; } /* @@ -3424,6 +3563,25 @@ } 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(void *xsc) { struct bge_softc *sc = xsc; @@ -4069,7 +4227,13 @@ /* Cancel pending I/O and flush buffers. */ bge_stop(ifp, 0); + + 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); /* @@ -4413,6 +4577,16 @@ callout_stop(&sc->bge_timeout); /* + * Tell firmware we're shutting down. + */ + bge_stop_fw(sc); + bge_sig_pre_reset(sc, BGE_RESET_STOP); + + /* Disable host interrupts. */ + BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); + + /* * Disable all of the receiver blocks */ bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); @@ -4453,14 +4627,17 @@ bge_stop_block(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); } - /* Disable host interrupts. */ - BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); + bge_reset(sc); + bge_sig_legacy(sc, BGE_RESET_STOP); + bge_sig_post_reset(sc, BGE_RESET_STOP); /* - * Tell firmware we're shutting down. + * Keep the ASF firmware running if up. */ - BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + 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); @@ -4737,9 +4914,8 @@ { int mac_offset = BGE_EE_MAC_OFFSET; - if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) { + 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)); Index: src/sys/dev/pci/if_bgereg.h diff -u src/sys/dev/pci/if_bgereg.h:1.54 src/sys/dev/pci/if_bgereg.h:1.55 --- src/sys/dev/pci/if_bgereg.h:1.54 Sun Jan 24 16:21:09 2010 +++ src/sys/dev/pci/if_bgereg.h Thu Jan 28 03:09:13 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bgereg.h,v 1.54 2010/01/24 16:21:09 msaitoh Exp $ */ +/* $NetBSD: if_bgereg.h,v 1.55 2010/01/28 03:09:13 msaitoh Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -62,7 +62,6 @@ * Flat mode consumes so much host address space that it is not * recommended. */ - #define BGE_PAGE_ZERO 0x00000000 #define BGE_PAGE_ZERO_END 0x000000FF #define BGE_SEND_RING_RCB 0x00000100 @@ -76,6 +75,9 @@ #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_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 @@ -84,6 +86,10 @@ #define BGE_SEND_RING_1_TO_4 0x00004000 #define BGE_SEND_RING_1_TO_4_END 0x00005FFF +/* Firmware interface */ +#define BGE_FW_DRV_ALIVE 0x00000001 +#define BGE_FW_PAUSE 0x00000002 + /* Mappings for internal memory configuration */ #define BGE_STD_RX_RINGS 0x00006000 #define BGE_STD_RX_RINGS_END 0x00006FFF @@ -172,6 +178,26 @@ #define BGE_PCI_MSI_DATA 0x64 /* + * PCI Express definitions + * According to + * PCI Express base specification, REV. 1.0a + */ + +/* PCI Express device control, 16bits */ +#define BGE_PCIE_DEVCTL 0x08 +#define BGE_PCIE_DEVCTL_MAX_READRQ_MASK 0x7000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_128 0x0000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_256 0x1000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_512 0x2000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_1024 0x3000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_2048 0x4000 +#define BGE_PCIE_DEVCTL_MAX_READRQ_4096 0x5000 + +/* PCI MSI. ??? */ +#define BGE_PCIE_CAPID_REG 0xD0 +#define BGE_PCIE_CAPID 0x10 + +/* * PCI registers specific to the BCM570x family. */ #define BGE_PCI_MISC_CTL 0x68 @@ -207,7 +233,6 @@ #define BGE_PCI_CONF_DEV_CTRL 0xD8 #define BGE_PCI_CONF_DEV_STUS 0xDA - /* PCI Misc. Host control register */ #define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001 #define BGE_PCIMISCCTL_MASK_PCI_INTR 0x00000002 @@ -412,11 +437,6 @@ #define BGE_PCICLOCKCTL_SYSPLL_DISABLE 0x00008000 #define BGE_PCICLOCKCTL_BIST_ENABLE 0x00010000 - -#ifndef PCIM_CMD_MWIEN -#define PCIM_CMD_MWIEN 0x0010 -#endif - /* * High priority mailbox registers * Each mailbox is 64-bits wide, though we only use the @@ -628,7 +648,6 @@ #define BGE_SGDIG_CFG 0x05B0 #define BGE_SGDIG_STS 0x05B4 #define BGE_MAC_STATS 0x0800 -#define BGE_TX_STATS 0x0880 /* Ethernet MAC Mode register */ #define BGE_MACMODE_RESET 0x00000001 @@ -1718,7 +1737,7 @@ #define BGE_MODE_CTL 0x6800 #define BGE_MISC_CFG 0x6804 #define BGE_MISC_LOCAL_CTL 0x6808 -#define BGE_MISC_TIMER 0x680c +#define BGE_CPU_EVENT 0x6810 #define BGE_EE_ADDR 0x6838 #define BGE_EE_DATA 0x683C #define BGE_EE_CTL 0x6840 @@ -1797,8 +1816,6 @@ #define BGE_PHY_PCIE_SCRAM_MODE 0x0020 #define BGE_PHY_PCIE_LTASS_MODE 0x0040 - - /* Mode control register */ #define BGE_MODECTL_INT_SNDCOAL_ONLY 0x00000001 #define BGE_MODECTL_BYTESWAP_NONFRAME 0x00000002 @@ -2099,6 +2116,7 @@ #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 Index: src/sys/dev/pci/if_bgevar.h diff -u src/sys/dev/pci/if_bgevar.h:1.2 src/sys/dev/pci/if_bgevar.h:1.3 --- src/sys/dev/pci/if_bgevar.h:1.2 Sun Jan 24 16:21:09 2010 +++ src/sys/dev/pci/if_bgevar.h Thu Jan 28 03:09:13 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bgevar.h,v 1.2 2010/01/24 16:21:09 msaitoh Exp $ */ +/* $NetBSD: if_bgevar.h,v 1.3 2010/01/28 03:09:13 msaitoh Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -217,6 +217,10 @@ SLIST_ENTRY(txdmamap_pool_entry) link; }; +#define ASF_ENABLE 1 +#define ASF_NEW_HANDSHAKE 2 +#define ASF_STACKUP 4 + struct bge_softc { device_t bge_dev; struct ethercom ethercom; /* interface info */ @@ -231,8 +235,11 @@ u_int32_t bge_return_ring_cnt; u_int32_t bge_tx_prodidx; bus_dma_tag_t bge_dmatag; + int bge_expcap; u_int32_t bge_chipid; u_int32_t bge_local_ctrl_reg; + uint8_t bge_asf_mode; + uint8_t bge_asf_count; struct bge_ring_data *bge_rdata; /* rings */ struct bge_chain_data bge_cdata; /* mbufs */ bus_dmamap_t bge_ring_map;