Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Aug 2007 13:20:23 GMT
From:      Maxim Zhuravlev <thioretic@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 125499 for review
Message-ID:  <200708211320.l7LDKNT9015886@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=125499

Change 125499 by thioretic@thioretic_freebox on 2007/08/21 13:19:53

	IFC

Affected files ...

.. //depot/projects/soc2007/thioretic_gidl2/dev/bce/if_bce.c#3 integrate
.. //depot/projects/soc2007/thioretic_gidl2/dev/bce/if_bcereg.h#2 integrate
.. //depot/projects/soc2007/thioretic_gidl2/modules/if_tap/Makefile#2 integrate

Differences ...

==== //depot/projects/soc2007/thioretic_gidl2/dev/bce/if_bce.c#3 (text) ====

@@ -1,3 +1,7511 @@
+>>>> ORIGINAL if_bce.c#17
+/*-
+ * Copyright (c) 2006-2007 Broadcom Corporation
+ *	David Christensen <davidch@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.19 2007/07/14 20:25:19 csjp 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 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 bootcde 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. */
+	rc = bus_setup_intr(dev, sc->bce_res_irq, INTR_TYPE_NET | INTR_MPSAFE,
+	   bce_intr, sc, &sc->bce_intrhand);
+
+	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)
+{
+	device_t dev;
+	dev = sc->bce_dev;
+
+	DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
+		__FUNCTION__, offset, val);
+
+	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
+	pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4);
+}
+
+
+/****************************************************************************/
+/* Context memory write.                                                    */
+/*                                                                          */

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200708211320.l7LDKNT9015886>