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;

Reply via email to