PERFORCE change 125498 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Tue Aug 21 06:16:18 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=125498
Change 125498 by thioretic at thioretic_freebox on 2007/08/21 13:15:57
IFC
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl/dev/bce/if_bce.c#3 integrate
.. //depot/projects/soc2007/thioretic_gidl/dev/bce/if_bcereg.h#2 integrate
.. //depot/projects/soc2007/thioretic_gidl/modules/if_tap/Makefile#2 integrate
Differences ...
==== //depot/projects/soc2007/thioretic_gidl/dev/bce/if_bce.c#3 (text) ====
@@ -1,3 +1,4 @@
+>>>> ORIGINAL if_bce.c#17
/*-
* Copyright (c) 2006-2007 Broadcom Corporation
* David Christensen <davidch at broadcom.com>. All rights reserved.
@@ -7504,3 +7505,15136 @@
return;
}
#endif
+==== THEIRS if_bce.c#18
+/*-
+ * Copyright (c) 2006-2007 Broadcom Corporation
+ * David Christensen <davidch at broadcom.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Broadcom Corporation nor the name of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written consent.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.2.2.20 2007/08/20 21:47:49 davidch Exp $");
+
+/*
+ * The following controllers are supported by this driver:
+ * BCM5706C A2, A3
+ * BCM5708C B1, B2
+ *
+ * The following controllers are not supported by this driver:
+ * BCM5706C A0, A1
+ * BCM5706S A0, A1, A2, A3
+ * BCM5708C A0, B0
+ * BCM5708S A0, B0, B1, B2
+ */
+
+#include "opt_bce.h"
+
+#include <dev/bce/if_bcereg.h>
+#include <dev/bce/if_bcefw.h>
+
+/****************************************************************************/
+/* BCE Debug Options */
+/****************************************************************************/
+#ifdef BCE_DEBUG
+ u32 bce_debug = BCE_WARN;
+
+ /* 0 = Never */
+ /* 1 = 1 in 2,147,483,648 */
+ /* 256 = 1 in 8,388,608 */
+ /* 2048 = 1 in 1,048,576 */
+ /* 65536 = 1 in 32,768 */
+ /* 1048576 = 1 in 2,048 */
+ /* 268435456 = 1 in 8 */
+ /* 536870912 = 1 in 4 */
+ /* 1073741824 = 1 in 2 */
+
+ /* Controls how often the l2_fhdr frame error check will fail. */
+ int bce_debug_l2fhdr_status_check = 0;
+
+ /* Controls how often the unexpected attention check will fail. */
+ int bce_debug_unexpected_attention = 0;
+
+ /* Controls how often to simulate an mbuf allocation failure. */
+ int bce_debug_mbuf_allocation_failure = 0;
+
+ /* Controls how often to simulate a DMA mapping failure. */
+ int bce_debug_dma_map_addr_failure = 0;
+
+ /* Controls how often to simulate a bootcode failure. */
+ int bce_debug_bootcode_running_failure = 0;
+#endif
+
+
+/****************************************************************************/
+/* PCI Device ID Table */
+/* */
+/* Used by bce_probe() to identify the devices supported by this driver. */
+/****************************************************************************/
+#define BCE_DEVDESC_MAX 64
+
+static struct bce_type bce_devs[] = {
+ /* BCM5706C Controllers and OEM boards. */
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3101,
+ "HP NC370T Multifunction Gigabit Server Adapter" },
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3106,
+ "HP NC370i Multifunction Gigabit Server Adapter" },
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5706, PCI_ANY_ID, PCI_ANY_ID,
+ "Broadcom NetXtreme II BCM5706 1000Base-T" },
+
+ /* BCM5706S controllers and OEM boards. */
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102,
+ "HP NC370F Multifunction Gigabit Server Adapter" },
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID, PCI_ANY_ID,
+ "Broadcom NetXtreme II BCM5706 1000Base-SX" },
+
+ /* BCM5708C controllers and OEM boards. */
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID,
+ "Broadcom NetXtreme II BCM5708 1000Base-T" },
+
+ /* BCM5708S controllers and OEM boards. */
+ { BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, PCI_ANY_ID, PCI_ANY_ID,
+ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
+ { 0, 0, 0, 0, NULL }
+};
+
+
+/****************************************************************************/
+/* Supported Flash NVRAM device data. */
+/****************************************************************************/
+static struct flash_spec flash_table[] =
+{
+ /* Slow EEPROM */
+ {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - slow"},
+ /* Expansion entry 0001 */
+ {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0001"},
+ /* Saifun SA25F010 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
+ "Non-buffered flash (128kB)"},
+ /* Saifun SA25F020 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
+ "Non-buffered flash (256kB)"},
+ /* Expansion entry 0100 */
+ {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 0100"},
+ /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
+ {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
+ "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
+ /* Entry 0110: ST M45PE20 (non-buffered flash)*/
+ {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
+ 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
+ ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
+ "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
+ /* Saifun SA25F005 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
+ "Non-buffered flash (64kB)"},
+ /* Fast EEPROM */
+ {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - fast"},
+ /* Expansion entry 1001 */
+ {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1001"},
+ /* Expansion entry 1010 */
+ {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1010"},
+ /* ATMEL AT45DB011B (buffered flash) */
+ {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
+ "Buffered flash (128kB)"},
+ /* Expansion entry 1100 */
+ {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1100"},
+ /* Expansion entry 1101 */
+ {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1101"},
+ /* Ateml Expansion entry 1110 */
+ {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
+ "Entry 1110 (Atmel)"},
+ /* ATMEL AT45DB021B (buffered flash) */
+ {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
+ "Buffered flash (256kB)"},
+};
+
+
+/****************************************************************************/
+/* FreeBSD device entry points. */
+/****************************************************************************/
+static int bce_probe (device_t);
+static int bce_attach (device_t);
+static int bce_detach (device_t);
+static void bce_shutdown (device_t);
+
+
+/****************************************************************************/
+/* BCE Debug Data Structure Dump Routines */
+/****************************************************************************/
+#ifdef BCE_DEBUG
+static void bce_dump_mbuf (struct bce_softc *, struct mbuf *);
+static void bce_dump_tx_mbuf_chain (struct bce_softc *, int, int);
+static void bce_dump_rx_mbuf_chain (struct bce_softc *, int, int);
+static void bce_dump_txbd (struct bce_softc *, int, struct tx_bd *);
+static void bce_dump_rxbd (struct bce_softc *, int, struct rx_bd *);
+static void bce_dump_l2fhdr (struct bce_softc *, int, struct l2_fhdr *);
+static void bce_dump_tx_chain (struct bce_softc *, int, int);
+static void bce_dump_rx_chain (struct bce_softc *, int, int);
+static void bce_dump_status_block (struct bce_softc *);
+static void bce_dump_stats_block (struct bce_softc *);
+static void bce_dump_driver_state (struct bce_softc *);
+static void bce_dump_hw_state (struct bce_softc *);
+static void bce_dump_bc_state (struct bce_softc *);
+static void bce_breakpoint (struct bce_softc *);
+#endif
+
+
+/****************************************************************************/
+/* BCE Register/Memory Access Routines */
+/****************************************************************************/
+static u32 bce_reg_rd_ind (struct bce_softc *, u32);
+static void bce_reg_wr_ind (struct bce_softc *, u32, u32);
+static void bce_ctx_wr (struct bce_softc *, u32, u32, u32);
+static int bce_miibus_read_reg (device_t, int, int);
+static int bce_miibus_write_reg (device_t, int, int, int);
+static void bce_miibus_statchg (device_t);
+
+
+/****************************************************************************/
+/* BCE NVRAM Access Routines */
+/****************************************************************************/
+static int bce_acquire_nvram_lock (struct bce_softc *);
+static int bce_release_nvram_lock (struct bce_softc *);
+static void bce_enable_nvram_access (struct bce_softc *);
+static void bce_disable_nvram_access(struct bce_softc *);
+static int bce_nvram_read_dword (struct bce_softc *, u32, u8 *, u32);
+static int bce_init_nvram (struct bce_softc *);
+static int bce_nvram_read (struct bce_softc *, u32, u8 *, int);
+static int bce_nvram_test (struct bce_softc *);
+#ifdef BCE_NVRAM_WRITE_SUPPORT
+static int bce_enable_nvram_write (struct bce_softc *);
+static void bce_disable_nvram_write (struct bce_softc *);
+static int bce_nvram_erase_page (struct bce_softc *, u32);
+static int bce_nvram_write_dword (struct bce_softc *, u32, u8 *, u32);
+static int bce_nvram_write (struct bce_softc *, u32, u8 *, int);
+#endif
+
+/****************************************************************************/
+/* */
+/****************************************************************************/
+static void bce_dma_map_addr (void *, bus_dma_segment_t *, int, int);
+static int bce_dma_alloc (device_t);
+static void bce_dma_free (struct bce_softc *);
+static void bce_release_resources (struct bce_softc *);
+
+/****************************************************************************/
+/* BCE Firmware Synchronization and Load */
+/****************************************************************************/
+static int bce_fw_sync (struct bce_softc *, u32);
+static void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32);
+static void bce_load_cpu_fw (struct bce_softc *, struct cpu_reg *, struct fw_info *);
+static void bce_init_cpus (struct bce_softc *);
+
+static void bce_stop (struct bce_softc *);
+static int bce_reset (struct bce_softc *, u32);
+static int bce_chipinit (struct bce_softc *);
+static int bce_blockinit (struct bce_softc *);
+static int bce_get_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
+
+static int bce_init_tx_chain (struct bce_softc *);
+static void bce_fill_rx_chain (struct bce_softc *);
+static int bce_init_rx_chain (struct bce_softc *);
+static void bce_free_rx_chain (struct bce_softc *);
+static void bce_free_tx_chain (struct bce_softc *);
+
+static int bce_tx_encap (struct bce_softc *, struct mbuf **);
+static void bce_start_locked (struct ifnet *);
+static void bce_start (struct ifnet *);
+static int bce_ioctl (struct ifnet *, u_long, caddr_t);
+static void bce_watchdog (struct bce_softc *);
+static int bce_ifmedia_upd (struct ifnet *);
+static void bce_ifmedia_upd_locked (struct ifnet *);
+static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *);
+static void bce_init_locked (struct bce_softc *);
+static void bce_init (void *);
+static void bce_mgmt_init_locked (struct bce_softc *sc);
+
+static void bce_init_context (struct bce_softc *);
+static void bce_get_mac_addr (struct bce_softc *);
+static void bce_set_mac_addr (struct bce_softc *);
+static void bce_phy_intr (struct bce_softc *);
+static void bce_rx_intr (struct bce_softc *);
+static void bce_tx_intr (struct bce_softc *);
+static void bce_disable_intr (struct bce_softc *);
+static void bce_enable_intr (struct bce_softc *);
+
+#ifdef DEVICE_POLLING
+static void bce_poll_locked (struct ifnet *, enum poll_cmd, int);
+static void bce_poll (struct ifnet *, enum poll_cmd, int);
+#endif
+static void bce_intr (void *);
+static void bce_set_rx_mode (struct bce_softc *);
+static void bce_stats_update (struct bce_softc *);
+static void bce_tick (void *);
+static void bce_pulse (void *);
+static void bce_add_sysctls (struct bce_softc *);
+
+
+/****************************************************************************/
+/* FreeBSD device dispatch table. */
+/****************************************************************************/
+static device_method_t bce_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bce_probe),
+ DEVMETHOD(device_attach, bce_attach),
+ DEVMETHOD(device_detach, bce_detach),
+ DEVMETHOD(device_shutdown, bce_shutdown),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, bce_miibus_read_reg),
+ DEVMETHOD(miibus_writereg, bce_miibus_write_reg),
+ DEVMETHOD(miibus_statchg, bce_miibus_statchg),
+
+ { 0, 0 }
+};
+
+static driver_t bce_driver = {
+ "bce",
+ bce_methods,
+ sizeof(struct bce_softc)
+};
+
+static devclass_t bce_devclass;
+
+MODULE_DEPEND(bce, pci, 1, 1, 1);
+MODULE_DEPEND(bce, ether, 1, 1, 1);
+MODULE_DEPEND(bce, miibus, 1, 1, 1);
+
+DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0);
+DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
+
+
+/****************************************************************************/
+/* Tunable device values */
+/****************************************************************************/
+static int bce_msi_enable = 1;
+
+/* Allowable values are 0 (IRQ only) and 1 (IRQ or MSI) */
+TUNABLE_INT("hw.bce.msi_enable", &bce_msi_enable);
+SYSCTL_NODE(_hw, OID_AUTO, bce, CTLFLAG_RD, 0, "bce driver parameters");
+SYSCTL_UINT(_hw_bce, OID_AUTO, msi_enable, CTLFLAG_RDTUN, &bce_msi_enable, 0,
+"MSI | INTx selector");
+
+/****************************************************************************/
+/* Device probe function. */
+/* */
+/* Compares the device to the driver's list of supported devices and */
+/* reports back to the OS whether this is the right driver for the device. */
+/* */
+/* Returns: */
+/* BUS_PROBE_DEFAULT on success, positive value on failure. */
+/****************************************************************************/
+static int
+bce_probe(device_t dev)
+{
+ struct bce_type *t;
+ struct bce_softc *sc;
+ char *descbuf;
+ u16 vid = 0, did = 0, svid = 0, sdid = 0;
+
+ t = bce_devs;
+
+ sc = device_get_softc(dev);
+ bzero(sc, sizeof(struct bce_softc));
+ sc->bce_unit = device_get_unit(dev);
+ sc->bce_dev = dev;
+
+ /* Get the data for the device to be probed. */
+ vid = pci_get_vendor(dev);
+ did = pci_get_device(dev);
+ svid = pci_get_subvendor(dev);
+ sdid = pci_get_subdevice(dev);
+
+ DBPRINT(sc, BCE_VERBOSE_LOAD,
+ "%s(); VID = 0x%04X, DID = 0x%04X, SVID = 0x%04X, "
+ "SDID = 0x%04X\n", __FUNCTION__, vid, did, svid, sdid);
+
+ /* Look through the list of known devices for a match. */
+ while(t->bce_name != NULL) {
+
+ if ((vid == t->bce_vid) && (did == t->bce_did) &&
+ ((svid == t->bce_svid) || (t->bce_svid == PCI_ANY_ID)) &&
+ ((sdid == t->bce_sdid) || (t->bce_sdid == PCI_ANY_ID))) {
+
+ descbuf = malloc(BCE_DEVDESC_MAX, M_TEMP, M_NOWAIT);
+
+ if (descbuf == NULL)
+ return(ENOMEM);
+
+ /* Print out the device identity. */
+ snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)",
+ t->bce_name,
+ (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
+ (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
+
+ device_set_desc_copy(dev, descbuf);
+ free(descbuf, M_TEMP);
+ return(BUS_PROBE_DEFAULT);
+ }
+ t++;
+ }
+
+ return(ENXIO);
+}
+
+
+/****************************************************************************/
+/* Device attach function. */
+/* */
+/* Allocates device resources, performs secondary chip identification, */
+/* resets and initializes the hardware, and initializes driver instance */
+/* variables. */
+/* */
+/* Returns: */
+/* 0 on success, positive value on failure. */
+/****************************************************************************/
+static int
+bce_attach(device_t dev)
+{
+ struct bce_softc *sc;
+ struct ifnet *ifp;
+ u32 val;
+ int count, mbuf, rid, rc = 0;
+
+ sc = device_get_softc(dev);
+ sc->bce_dev = dev;
+
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
+
+ mbuf = device_get_unit(dev);
+
+ /* Set initial device and PHY flags */
+ sc->bce_flags = 0;
+ sc->bce_phy_flags = 0;
+
+ sc->bce_unit = mbuf;
+
+ pci_enable_busmaster(dev);
+
+ /* Allocate PCI memory resources. */
+ rid = PCIR_BAR(0);
+ sc->bce_res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE | PCI_RF_DENSE);
+
+ if (sc->bce_res_mem == NULL) {
+ BCE_PRINTF("%s(%d): PCI memory allocation failed\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Get various resource handles. */
+ sc->bce_btag = rman_get_bustag(sc->bce_res_mem);
+ sc->bce_bhandle = rman_get_bushandle(sc->bce_res_mem);
+ sc->bce_vhandle = (vm_offset_t) rman_get_virtual(sc->bce_res_mem);
+
+ /* If MSI is enabled in the driver, get the vector count. */
+ count = bce_msi_enable ? pci_msi_count(dev) : 0;
+
+ /* Allocate PCI IRQ resources. */
+ if (count == 1 && pci_alloc_msi(dev, &count) == 0 && count == 1) {
+ rid = 1;
+ sc->bce_flags |= BCE_USING_MSI_FLAG;
+ DBPRINT(sc, BCE_VERBOSE_LOAD,
+ "Allocating %d MSI interrupt(s)\n", count);
+ } else {
+ rid = 0;
+ DBPRINT(sc, BCE_VERBOSE_LOAD, "Allocating IRQ interrupt\n");
+ }
+
+ sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+
+ if (sc->bce_res_irq == NULL) {
+ BCE_PRINTF("%s(%d): PCI map interrupt failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Initialize mutex for the current device instance. */
+ BCE_LOCK_INIT(sc, device_get_nameunit(dev));
+
+ /*
+ * Configure byte swap and enable indirect register access.
+ * Rely on CPU to do target byte swapping on big endian systems.
+ * Access to registers outside of PCI configurtion space are not
+ * valid until this is done.
+ */
+ pci_write_config(dev, BCE_PCICFG_MISC_CONFIG,
+ BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4);
+
+ /* Save ASIC revsion info. */
+ sc->bce_chipid = REG_RD(sc, BCE_MISC_ID);
+
+ /* Weed out any non-production controller revisions. */
+ switch(BCE_CHIP_ID(sc)) {
+ case BCE_CHIP_ID_5706_A0:
+ case BCE_CHIP_ID_5706_A1:
+ case BCE_CHIP_ID_5708_A0:
+ case BCE_CHIP_ID_5708_B0:
+ BCE_PRINTF("%s(%d): Unsupported controller revision (%c%d)!\n",
+ __FILE__, __LINE__,
+ (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
+ (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
+ rc = ENODEV;
+ goto bce_attach_fail;
+ }
+
+ /*
+ * The embedded PCIe to PCI-X bridge (EPB)
+ * in the 5708 cannot address memory above
+ * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043).
+ */
+ if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)
+ sc->max_bus_addr = BCE_BUS_SPACE_MAXADDR;
+ else
+ sc->max_bus_addr = BUS_SPACE_MAXADDR;
+
+ /*
+ * Find the base address for shared memory access.
+ * Newer versions of bootcode use a signature and offset
+ * while older versions use a fixed address.
+ */
+ val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE);
+ if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == BCE_SHM_HDR_SIGNATURE_SIG)
+ sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0);
+ else
+ sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE;
+
+ DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): bce_shmem_base = 0x%08X\n",
+ __FUNCTION__, sc->bce_shmem_base);
+
+ sc->bce_fw_ver = REG_RD_IND(sc, sc->bce_shmem_base +
+ BCE_DEV_INFO_BC_REV);
+ DBPRINT(sc, BCE_INFO_FIRMWARE, "%s(): bce_fw_ver = 0x%08X\n",
+ __FUNCTION__, sc->bce_fw_ver);
+
+ /* Check if any management firmware is running. */
+ val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_FEATURE);
+ if (val & (BCE_PORT_FEATURE_ASF_ENABLED | BCE_PORT_FEATURE_IMD_ENABLED)) {
+ sc->bce_flags |= BCE_MFW_ENABLE_FLAG;
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): BCE_MFW_ENABLE_FLAG\n",
+ __FUNCTION__);
+ }
+
+ /* Get PCI bus information (speed and type). */
+ val = REG_RD(sc, BCE_PCICFG_MISC_STATUS);
+ if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) {
+ u32 clkreg;
+
+ sc->bce_flags |= BCE_PCIX_FLAG;
+
+ clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS);
+
+ clkreg &= BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
+ switch (clkreg) {
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
+ sc->bus_speed_mhz = 133;
+ break;
+
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
+ sc->bus_speed_mhz = 100;
+ break;
+
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
+ sc->bus_speed_mhz = 66;
+ break;
+
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
+ sc->bus_speed_mhz = 50;
+ break;
+
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
+ case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
+ sc->bus_speed_mhz = 33;
+ break;
+ }
+ } else {
+ if (val & BCE_PCICFG_MISC_STATUS_M66EN)
+ sc->bus_speed_mhz = 66;
+ else
+ sc->bus_speed_mhz = 33;
+ }
+
+ if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET)
+ sc->bce_flags |= BCE_PCI_32BIT_FLAG;
+
+ /* Reset the controller and announce to bootcode that driver is present. */
+ if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) {
+ BCE_PRINTF("%s(%d): Controller reset failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Initialize the controller. */
+ if (bce_chipinit(sc)) {
+ BCE_PRINTF("%s(%d): Controller initialization failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Perform NVRAM test. */
+ if (bce_nvram_test(sc)) {
+ BCE_PRINTF("%s(%d): NVRAM test failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Fetch the permanent Ethernet MAC address. */
+ bce_get_mac_addr(sc);
+
+ /*
+ * Trip points control how many BDs
+ * should be ready before generating an
+ * interrupt while ticks control how long
+ * a BD can sit in the chain before
+ * generating an interrupt. Set the default
+ * values for the RX and TX chains.
+ */
+
+#ifdef BCE_DEBUG
+ /* Force more frequent interrupts. */
+ sc->bce_tx_quick_cons_trip_int = 1;
+ sc->bce_tx_quick_cons_trip = 1;
+ sc->bce_tx_ticks_int = 0;
+ sc->bce_tx_ticks = 0;
+
+ sc->bce_rx_quick_cons_trip_int = 1;
+ sc->bce_rx_quick_cons_trip = 1;
+ sc->bce_rx_ticks_int = 0;
+ sc->bce_rx_ticks = 0;
+#else
+ /* Improve throughput at the expense of increased latency. */
+ sc->bce_tx_quick_cons_trip_int = 20;
+ sc->bce_tx_quick_cons_trip = 20;
+ sc->bce_tx_ticks_int = 80;
+ sc->bce_tx_ticks = 80;
+
+ sc->bce_rx_quick_cons_trip_int = 6;
+ sc->bce_rx_quick_cons_trip = 6;
+ sc->bce_rx_ticks_int = 18;
+ sc->bce_rx_ticks = 18;
+#endif
+
+ /* Update statistics once every second. */
+ sc->bce_stats_ticks = 1000000 & 0xffff00;
+
+ /*
+ * The SerDes based NetXtreme II controllers
+ * that support 2.5Gb operation (currently
+ * 5708S) use a PHY at address 2, otherwise
+ * the PHY is present at address 1.
+ */
+ sc->bce_phy_addr = 1;
+
+ if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
+ sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
+ sc->bce_flags |= BCE_NO_WOL_FLAG;
+ if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) {
+ sc->bce_phy_addr = 2;
+ val = REG_RD_IND(sc, sc->bce_shmem_base +
+ BCE_SHARED_HW_CFG_CONFIG);
+ if (val & BCE_SHARED_HW_CFG_PHY_2_5G) {
+ sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG;
+ DBPRINT(sc, BCE_INFO_LOAD, "Found 2.5Gb capable adapter\n");
+ }
+ }
+ }
+
+ /* Store data needed by PHY driver for backplane applications */
+ sc->bce_shared_hw_cfg = REG_RD_IND(sc, sc->bce_shmem_base +
+ BCE_SHARED_HW_CFG_CONFIG);
+ sc->bce_port_hw_cfg = REG_RD_IND(sc, sc->bce_shmem_base +
+ BCE_SHARED_HW_CFG_CONFIG);
+
+ /* Allocate DMA memory resources. */
+ if (bce_dma_alloc(dev)) {
+ BCE_PRINTF("%s(%d): DMA resource allocation failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Allocate an ifnet structure. */
+ ifp = sc->bce_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ BCE_PRINTF("%s(%d): Interface allocation failed!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Initialize the ifnet interface. */
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = bce_ioctl;
+ ifp->if_start = bce_start;
+ ifp->if_init = bce_init;
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_hwassist = BCE_IF_HWASSIST;
+ ifp->if_capabilities = BCE_IF_CAPABILITIES;
+ ifp->if_capenable = ifp->if_capabilities;
+
+ /* Assume a standard 1500 byte MTU size for mbuf allocations. */
+ sc->mbuf_alloc_size = MCLBYTES;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
+ ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
+ IFQ_SET_READY(&ifp->if_snd);
+
+ if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
+ ifp->if_baudrate = IF_Mbps(2500ULL);
+ else
+ ifp->if_baudrate = IF_Mbps(1000);
+
+ /* Check for an MII child bus by probing the PHY. */
+ if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd,
+ bce_ifmedia_sts)) {
+ BCE_PRINTF("%s(%d): No PHY found on child MII bus!\n",
+ __FILE__, __LINE__);
+ rc = ENXIO;
+ goto bce_attach_fail;
+ }
+
+ /* Attach to the Ethernet interface list. */
+ ether_ifattach(ifp, sc->eaddr);
+
+#if __FreeBSD_version < 500000
+ callout_init(&sc->bce_tick_callout);
+ callout_init(&sc->bce_pulse_callout);
+#else
+ callout_init_mtx(&sc->bce_tick_callout, &sc->bce_mtx, 0);
+ callout_init_mtx(&sc->bce_pulse_callout, &sc->bce_mtx, 0);
+#endif
+
+ /* Hookup IRQ last. */
+#if __FreeBSD_version > 700030
+ rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, bce_intr, sc, &sc->bce_intrhand);
+#else
+ rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ bce_intr, sc, &sc->bce_intrhand);
+#endif
+
+ if (rc) {
+ BCE_PRINTF("%s(%d): Failed to setup IRQ!\n",
+ __FILE__, __LINE__);
+ bce_detach(dev);
+ goto bce_attach_exit;
+ }
+
+ /*
+ * At this point we've acquired all the resources
+ * we need to run so there's no turning back, we're
+ * cleared for launch.
+ */
+
+ /* Print some important debugging info. */
+ DBRUN(BCE_INFO, bce_dump_driver_state(sc));
+
+ /* Add the supported sysctls to the kernel. */
+ bce_add_sysctls(sc);
+
+ BCE_LOCK(sc);
+ /*
+ * The chip reset earlier notified the bootcode that
+ * a driver is present. We now need to start our pulse
+ * routine so that the bootcode is reminded that we're
+ * still running.
+ */
+ bce_pulse(sc);
+
+ bce_mgmt_init_locked(sc);
+ BCE_UNLOCK(sc);
+
+ /* Finally, print some useful adapter info */
+ BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
+ printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
+ ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
+ printf("Bus (PCI%s, %s, %dMHz); ",
+ ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
+ ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
+ sc->bus_speed_mhz);
+ printf("F/W (0x%08X); Flags( ", sc->bce_fw_ver);
+ if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
+ printf("MFW ");
+ if (sc->bce_flags & BCE_USING_MSI_FLAG)
+ printf("MSI ");
+ if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
+ printf("2.5G ");
+ printf(")\n");
+
+ goto bce_attach_exit;
+
+bce_attach_fail:
+ bce_release_resources(sc);
+
+bce_attach_exit:
+
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+
+ return(rc);
+}
+
+
+/****************************************************************************/
+/* Device detach function. */
+/* */
+/* Stops the controller, resets the controller, and releases resources. */
+/* */
+/* Returns: */
+/* 0 on success, positive value on failure. */
+/****************************************************************************/
+static int
+bce_detach(device_t dev)
+{
+ struct bce_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ u32 msg;
+
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
+
+ ifp = sc->bce_ifp;
+
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
+
+ /* Stop the pulse so the bootcode can go to driver absent state. */
+ callout_stop(&sc->bce_pulse_callout);
+
+ /* Stop and reset the controller. */
+ BCE_LOCK(sc);
+ bce_stop(sc);
+ if (sc->bce_flags & BCE_NO_WOL_FLAG)
+ msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN;
+ else
+ msg = BCE_DRV_MSG_CODE_UNLOAD;
+ bce_reset(sc, msg);
+ BCE_UNLOCK(sc);
+
+ ether_ifdetach(ifp);
+
+ /* If we have a child device on the MII bus remove it too. */
+ bus_generic_detach(dev);
+ device_delete_child(dev, sc->bce_miibus);
+
+ /* Release all remaining resources. */
+ bce_release_resources(sc);
+
+ DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
+
+ return(0);
+}
+
+
+/****************************************************************************/
+/* Device shutdown function. */
+/* */
+/* Stops and resets the controller. */
+/* */
+/* Returns: */
+/* Nothing */
+/****************************************************************************/
+static void
+bce_shutdown(device_t dev)
+{
+ struct bce_softc *sc = device_get_softc(dev);
+ u32 msg;
+
+ DBPRINT(sc, BCE_VERBOSE_SPECIAL, "Entering %s()\n", __FUNCTION__);
+
+ BCE_LOCK(sc);
+ bce_stop(sc);
+ if (sc->bce_flags & BCE_NO_WOL_FLAG)
+ msg = BCE_DRV_MSG_CODE_UNLOAD_LNK_DN;
+ else
+ msg = BCE_DRV_MSG_CODE_UNLOAD;
+ bce_reset(sc, msg);
+ BCE_UNLOCK(sc);
+
+ DBPRINT(sc, BCE_VERBOSE_SPECIAL, "Exiting %s()\n", __FUNCTION__);
+}
+
+
+/****************************************************************************/
+/* Indirect register read. */
+/* */
+/* Reads NetXtreme II registers using an index/data register pair in PCI */
+/* configuration space. Using this mechanism avoids issues with posted */
+/* reads but is much slower than memory-mapped I/O. */
+/* */
+/* Returns: */
+/* The value of the register. */
+/****************************************************************************/
+static u32
+bce_reg_rd_ind(struct bce_softc *sc, u32 offset)
+{
+ device_t dev;
+ dev = sc->bce_dev;
+
+ pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
+#ifdef BCE_DEBUG
+ {
+ u32 val;
+ val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
+ DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
+ __FUNCTION__, offset, val);
+ return val;
+ }
+#else
+ return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
+#endif
+}
+
+
+/****************************************************************************/
+/* Indirect register write. */
+/* */
+/* Writes NetXtreme II registers using an index/data register pair in PCI */
+/* configuration space. Using this mechanism avoids issues with posted */
+/* writes but is muchh slower than memory-mapped I/O. */
+/* */
+/* Returns: */
+/* Nothing. */
+/****************************************************************************/
+static void
+bce_reg_wr_ind(struct bce_softc *sc, u32 offset, u32 val)
+{
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list