summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2006-02-19 22:39:19 +0000
committergallatin <gallatin@FreeBSD.org>2006-02-19 22:39:19 +0000
commit9a34695ace03c6cf7bf16f38837d5c90c310d5db (patch)
tree0062dda628f25042020575c33e42389f89e8c7b2 /sys/dev
parent35856d05d214e9842e12f9fa271f43bf8e4ccb90 (diff)
downloadFreeBSD-src-9a34695ace03c6cf7bf16f38837d5c90c310d5db.zip
FreeBSD-src-9a34695ace03c6cf7bf16f38837d5c90c310d5db.tar.gz
10GbE mode driver and binary firmware for Myricom's PCI-express NICs.
More info regarding these nics can be found at http://www.myri.com. Please note that the files sys/dev/myri10ge/{mcp_gen_header.h,myri10ge_mcp.h} are internally shared between all our drivers (solaris, macosx, windows, linux, etc). I'd like to keep these files unchanged, so I can just import newer versions of them when the firmware API/ABI changes. This means I'm stuck with some of the crazy-long #define names, and possibly non-style(9) characteristics of these files. Many thanks to mlaier for doing firmware(9) just as I needed it, and to scottl for his helpful review. Reviewed by: scottl, glebius Sponsored by: Myricom Inc.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mxge/eth_z8e.dat.gz.uu633
-rw-r--r--sys/dev/mxge/ethp_z8e.dat.gz.uu639
-rw-r--r--sys/dev/mxge/if_mxge.c2489
-rw-r--r--sys/dev/mxge/if_mxge_var.h203
-rw-r--r--sys/dev/mxge/mcp_gen_header.h107
-rw-r--r--sys/dev/mxge/mxge_mcp.h265
-rw-r--r--sys/dev/myri10ge/eth_z8e.dat.gz.uu633
-rw-r--r--sys/dev/myri10ge/ethp_z8e.dat.gz.uu639
-rw-r--r--sys/dev/myri10ge/if_myri10ge.c2489
-rw-r--r--sys/dev/myri10ge/if_myri10ge_var.h203
-rw-r--r--sys/dev/myri10ge/mcp_gen_header.h107
-rw-r--r--sys/dev/myri10ge/myri10ge_mcp.h265
12 files changed, 8672 insertions, 0 deletions
diff --git a/sys/dev/mxge/eth_z8e.dat.gz.uu b/sys/dev/mxge/eth_z8e.dat.gz.uu
new file mode 100644
index 0000000..6f9f310
--- /dev/null
+++ b/sys/dev/mxge/eth_z8e.dat.gz.uu
@@ -0,0 +1,633 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+begin 644 eth_z8e.dat.gz
+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
+:H`>XA3R!"DX3\NT@B'.)5?X_S^VI\1AH`0``
+`
+end
diff --git a/sys/dev/mxge/ethp_z8e.dat.gz.uu b/sys/dev/mxge/ethp_z8e.dat.gz.uu
new file mode 100644
index 0000000..ad582ba
--- /dev/null
+++ b/sys/dev/mxge/ethp_z8e.dat.gz.uu
@@ -0,0 +1,639 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+begin 644 ethp_z8e.dat.gz
+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
+6`2"L\@DF&03#SO@J_P]CB=E(^'`!````
+`
+end
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
new file mode 100644
index 0000000..96a063f
--- /dev/null
+++ b/sys/dev/mxge/if_mxge.c
@@ -0,0 +1,2489 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/linker.h>
+#include <sys/firmware.h>
+#include <sys/endian.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/memrange.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+#include <net/zlib.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include <machine/clock.h> /* for DELAY */
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <vm/vm.h> /* for pmap_mapdev() */
+#include <vm/pmap.h>
+
+#include <dev/myri10ge/myri10ge_mcp.h>
+#include <dev/myri10ge/mcp_gen_header.h>
+#include <dev/myri10ge/if_myri10ge_var.h>
+
+/* tunable params */
+static int myri10ge_nvidia_ecrc_enable = 1;
+static int myri10ge_max_intr_slots = 128;
+static int myri10ge_intr_coal_delay = 30;
+static int myri10ge_skip_pio_read = 0;
+static int myri10ge_flow_control = 1;
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e";
+
+static int myri10ge_probe(device_t dev);
+static int myri10ge_attach(device_t dev);
+static int myri10ge_detach(device_t dev);
+static int myri10ge_shutdown(device_t dev);
+static void myri10ge_intr(void *arg);
+
+static device_method_t myri10ge_methods[] =
+{
+ /* Device interface */
+ DEVMETHOD(device_probe, myri10ge_probe),
+ DEVMETHOD(device_attach, myri10ge_attach),
+ DEVMETHOD(device_detach, myri10ge_detach),
+ DEVMETHOD(device_shutdown, myri10ge_shutdown),
+ {0, 0}
+};
+
+static driver_t myri10ge_driver =
+{
+ "myri10ge",
+ myri10ge_methods,
+ sizeof(myri10ge_softc_t),
+};
+
+static devclass_t myri10ge_devclass;
+
+/* Declare ourselves to be a child of the PCI bus.*/
+DRIVER_MODULE(myri10ge, pci, myri10ge_driver, myri10ge_devclass, 0, 0);
+MODULE_DEPEND(myri10ge, firmware, 1, 1, 1);
+
+static int
+myri10ge_probe(device_t dev)
+{
+ if ((pci_get_vendor(dev) == MYRI10GE_PCI_VENDOR_MYRICOM) &&
+ (pci_get_device(dev) == MYRI10GE_PCI_DEVICE_Z8E)) {
+ device_set_desc(dev, "Myri10G-PCIE-8A");
+ return 0;
+ }
+ return ENXIO;
+}
+
+static void
+myri10ge_enable_wc(myri10ge_softc_t *sc)
+{
+ struct mem_range_desc mrdesc;
+ vm_paddr_t pa;
+ vm_offset_t len;
+ int err, action;
+
+ pa = rman_get_start(sc->mem_res);
+ len = rman_get_size(sc->mem_res);
+ mrdesc.mr_base = pa;
+ mrdesc.mr_len = len;
+ mrdesc.mr_flags = MDF_WRITECOMBINE;
+ action = MEMRANGE_SET_UPDATE;
+ strcpy((char *)&mrdesc.mr_owner, "myri10ge");
+ err = mem_range_attr_set(&mrdesc, &action);
+ if (err != 0) {
+ device_printf(sc->dev,
+ "w/c failed for pa 0x%lx, len 0x%lx, err = %d\n",
+ (unsigned long)pa, (unsigned long)len, err);
+ } else {
+ sc->wc = 1;
+ }
+}
+
+
+/* callback to get our DMA address */
+static void
+myri10ge_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error)
+{
+ if (error == 0) {
+ *(bus_addr_t *) arg = segs->ds_addr;
+ }
+}
+
+static int
+myri10ge_dma_alloc(myri10ge_softc_t *sc, myri10ge_dma_t *dma, size_t bytes,
+ bus_size_t alignment)
+{
+ int err;
+ device_t dev = sc->dev;
+
+ /* allocate DMAable memory tags */
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ alignment, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ bytes, /* maxsize */
+ 1, /* num segs */
+ 4096, /* maxsegsize */
+ BUS_DMA_COHERENT, /* flags */
+ NULL, NULL, /* lock */
+ &dma->dmat); /* tag */
+ if (err != 0) {
+ device_printf(dev, "couldn't alloc tag (err = %d)\n", err);
+ return err;
+ }
+
+ /* allocate DMAable memory & map */
+ err = bus_dmamem_alloc(dma->dmat, &dma->addr,
+ (BUS_DMA_WAITOK | BUS_DMA_COHERENT
+ | BUS_DMA_ZERO), &dma->map);
+ if (err != 0) {
+ device_printf(dev, "couldn't alloc mem (err = %d)\n", err);
+ goto abort_with_dmat;
+ }
+
+ /* load the memory */
+ err = bus_dmamap_load(dma->dmat, dma->map, dma->addr, bytes,
+ myri10ge_dmamap_callback,
+ (void *)&dma->bus_addr, 0);
+ if (err != 0) {
+ device_printf(dev, "couldn't load map (err = %d)\n", err);
+ goto abort_with_mem;
+ }
+ return 0;
+
+abort_with_mem:
+ bus_dmamem_free(dma->dmat, dma->addr, dma->map);
+abort_with_dmat:
+ (void)bus_dma_tag_destroy(dma->dmat);
+ return err;
+}
+
+
+static void
+myri10ge_dma_free(myri10ge_dma_t *dma)
+{
+ bus_dmamap_unload(dma->dmat, dma->map);
+ bus_dmamem_free(dma->dmat, dma->addr, dma->map);
+ (void)bus_dma_tag_destroy(dma->dmat);
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PC=text\0
+ */
+
+static int
+myri10ge_parse_strings(myri10ge_softc_t *sc)
+{
+#define MYRI10GE_NEXT_STRING(p) while(ptr < limit && *ptr++)
+
+ char *ptr, *limit;
+ int i, found_mac;
+
+ ptr = sc->eeprom_strings;
+ limit = sc->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+ found_mac = 0;
+ while (ptr < limit && *ptr != '\0') {
+ if (memcmp(ptr, "MAC=", 4) == 0) {
+ ptr+=4;
+ sc->mac_addr_string = ptr;
+ for (i = 0; i < 6; i++) {
+ if ((ptr + 2) > limit)
+ goto abort;
+ sc->mac_addr[i] = strtoul(ptr, NULL, 16);
+ found_mac = 1;
+ ptr += 3;
+ }
+ } else if (memcmp(ptr, "PC=", 4) == 0) {
+ sc->product_code_string = ptr;
+ }
+ MYRI10GE_NEXT_STRING(ptr);
+ }
+
+ if (found_mac)
+ return 0;
+
+ abort:
+ device_printf(sc->dev, "failed to parse eeprom_strings\n");
+
+ return ENXIO;
+}
+
+#if #cpu(i386) || defined __i386 || defined i386 || defined __i386__ || #cpu(x86_64) || defined __x86_64__
+static int
+myri10ge_enable_nvidia_ecrc(myri10ge_softc_t *sc, device_t pdev)
+{
+ uint32_t val;
+ unsigned long off;
+ char *va, *cfgptr;
+ uint16_t vendor_id, device_id;
+ uintptr_t bus, slot, func, ivend, idev;
+ uint32_t *ptr32;
+
+ /* XXXX
+ Test below is commented because it is believed that doing
+ config read/write beyond 0xff will access the config space
+ for the next larger function. Uncomment this and remove
+ the hacky pmap_mapdev() way of accessing config space when
+ FreeBSD grows support for extended pcie config space access
+ */
+#if 0
+ /* See if we can, by some miracle, access the extended
+ config space */
+ val = pci_read_config(pdev, 0x178, 4);
+ if (val != 0xffffffff) {
+ val |= 0x40;
+ pci_write_config(pdev, 0x178, val, 4);
+ return 0;
+ }
+#endif
+ /* Rather than using normal pci config space writes, we must
+ * map the Nvidia config space ourselves. This is because on
+ * opteron/nvidia class machine the 0xe000000 mapping is
+ * handled by the nvidia chipset, that means the internal PCI
+ * device (the on-chip northbridge), or the amd-8131 bridge
+ * and things behind them are not visible by this method.
+ */
+
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_BUS, &bus);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_SLOT, &slot);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_FUNCTION, &func);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_VENDOR, &ivend);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_DEVICE, &idev);
+
+ off = 0xe0000000UL
+ + 0x00100000UL * (unsigned long)bus
+ + 0x00001000UL * (unsigned long)(func
+ + 8 * slot);
+
+ /* map it into the kernel */
+ va = pmap_mapdev(trunc_page((vm_paddr_t)off), PAGE_SIZE);
+
+
+ if (va == NULL) {
+ device_printf(sc->dev, "pmap_kenter_temporary didn't\n");
+ return EIO;
+ }
+ /* get a pointer to the config space mapped into the kernel */
+ cfgptr = va + (off & PAGE_MASK);
+
+ /* make sure that we can really access it */
+ vendor_id = *(uint16_t *)(cfgptr + PCIR_VENDOR);
+ device_id = *(uint16_t *)(cfgptr + PCIR_DEVICE);
+ if (! (vendor_id == ivend && device_id == idev)) {
+ device_printf(sc->dev, "mapping failed: 0x%x:0x%x\n",
+ vendor_id, device_id);
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ return EIO;
+ }
+
+ ptr32 = (uint32_t*)(cfgptr + 0x178);
+ val = *ptr32;
+
+ if (val == 0xffffffff) {
+ device_printf(sc->dev, "extended mapping failed\n");
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ return EIO;
+ }
+ *ptr32 = val | 0x40;
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ device_printf(sc->dev,
+ "Enabled ECRC on upstream Nvidia bridge at %d:%d:%d\n",
+ (int)bus, (int)slot, (int)func);
+ return 0;
+}
+#else
+static int
+myri10ge_enable_nvidia_ecrc(myri10ge_softc_t *sc, device_t pdev)
+{
+ device_printf(sc->dev,
+ "Nforce 4 chipset on non-x86/amd64!?!?!\n");
+ return ENXIO;
+}
+#endif
+/*
+ * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
+ * when the PCI-E Completion packets are aligned on an 8-byte
+ * boundary. Some PCI-E chip sets always align Completion packets; on
+ * the ones that do not, the alignment can be enforced by enabling
+ * ECRC generation (if supported).
+ *
+ * When PCI-E Completion packets are not aligned, it is actually more
+ * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
+ *
+ * If the driver can neither enable ECRC nor verify that it has
+ * already been enabled, then it must use a firmware image which works
+ * around unaligned completion packets (ethp_z8e.dat), and it should
+ * also ensure that it never gives the device a Read-DMA which is
+ * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is
+ * enabled, then the driver should use the aligned (eth_z8e.dat)
+ * firmware image, and set tx.boundary to 4KB.
+ */
+
+static void
+myri10ge_select_firmware(myri10ge_softc_t *sc)
+{
+ int err, aligned = 0;
+ device_t pdev;
+ uint16_t pvend, pdid;
+
+ pdev = device_get_parent(device_get_parent(sc->dev));
+ if (pdev == NULL) {
+ device_printf(sc->dev, "could not find parent?\n");
+ goto abort;
+ }
+ pvend = pci_read_config(pdev, PCIR_VENDOR, 2);
+ pdid = pci_read_config(pdev, PCIR_DEVICE, 2);
+
+ /* see if we can enable ECRC's on an upstream
+ Nvidia bridge */
+ if (myri10ge_nvidia_ecrc_enable &&
+ (pvend == 0x10de && pdid == 0x005d)) {
+ err = myri10ge_enable_nvidia_ecrc(sc, pdev);
+ if (err == 0) {
+ aligned = 1;
+ device_printf(sc->dev,
+ "Assuming aligned completions (ECRC)\n");
+ }
+ }
+ /* see if the upstream bridge is known to
+ provided aligned completions */
+ if (/* HT2000 */ (pvend == 0x1166 && pdid == 0x0132) ||
+ /* Ontario */ (pvend == 0x10b5 && pdid == 0x8532)) {
+ device_printf(sc->dev,
+ "Assuming aligned completions (0x%x:0x%x)\n",
+ pvend, pdid);
+ }
+
+abort:
+ if (aligned) {
+ sc->fw_name = myri10ge_fw_aligned;
+ sc->tx.boundary = 4096;
+ } else {
+ sc->fw_name = myri10ge_fw_unaligned;
+ sc->tx.boundary = 2048;
+ }
+}
+
+union qualhack
+{
+ const char *ro_char;
+ char *rw_char;
+};
+
+
+static int
+myri10ge_load_firmware_helper(myri10ge_softc_t *sc, uint32_t *limit)
+{
+ struct firmware *fw;
+ const mcp_gen_header_t *hdr;
+ unsigned hdr_offset;
+ const char *fw_data;
+ union qualhack hack;
+ int status;
+
+
+ fw = firmware_get(sc->fw_name);
+
+ if (fw == NULL) {
+ device_printf(sc->dev, "Could not find firmware image %s\n",
+ sc->fw_name);
+ return ENOENT;
+ }
+ if (fw->datasize > *limit ||
+ fw->datasize < MCP_HEADER_PTR_OFFSET + 4) {
+ device_printf(sc->dev, "Firmware image %s too large (%d/%d)\n",
+ sc->fw_name, (int)fw->datasize, (int) *limit);
+ status = ENOSPC;
+ goto abort_with_fw;
+ }
+ *limit = fw->datasize;
+
+ /* check id */
+ fw_data = (const char *)fw->data;
+ hdr_offset = htobe32(*(const uint32_t *)
+ (fw_data + MCP_HEADER_PTR_OFFSET));
+ if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->datasize) {
+ device_printf(sc->dev, "Bad firmware file");
+ status = EIO;
+ goto abort_with_fw;
+ }
+ hdr = (const void*)(fw_data + hdr_offset);
+ if (be32toh(hdr->mcp_type) != MCP_TYPE_ETH) {
+ device_printf(sc->dev, "Bad firmware type: 0x%x\n",
+ be32toh(hdr->mcp_type));
+ status = EIO;
+ goto abort_with_fw;
+ }
+
+ /* save firmware version for sysctl */
+ strncpy(sc->fw_version, hdr->version, sizeof (sc->fw_version));
+ device_printf(sc->dev, "firmware id: %s\n", hdr->version);
+
+ hack.ro_char = fw_data;
+ /* Copy the inflated firmware to NIC SRAM. */
+ myri10ge_pio_copy(&sc->sram[MYRI10GE_FW_OFFSET],
+ hack.rw_char, *limit);
+
+ status = 0;
+abort_with_fw:
+ firmware_put(fw, FIRMWARE_UNLOAD);
+ return status;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void
+myri10ge_dummy_rdma(myri10ge_softc_t *sc, int enable)
+{
+ char buf_bytes[72];
+ volatile uint32_t *confirm;
+ volatile char *submit;
+ uint32_t *buf, dma_low, dma_high;
+ int i;
+
+ buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ /* clear confirmation addr */
+ confirm = (volatile uint32_t *)sc->cmd;
+ *confirm = 0;
+ mb();
+
+ /* send an rdma command to the PCIe engine, and wait for the
+ response in the confirmation address. The firmware should
+ write a -1 there to indicate it is alive and well
+ */
+
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+ buf[0] = htobe32(dma_high); /* confirm addr MSW */
+ buf[1] = htobe32(dma_low); /* confirm addr LSW */
+ buf[2] = htobe32(0xffffffff); /* confirm data */
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->zeropad_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->zeropad_dma.bus_addr);
+ buf[3] = htobe32(dma_high); /* dummy addr MSW */
+ buf[4] = htobe32(dma_low); /* dummy addr LSW */
+ buf[5] = htobe32(enable); /* enable? */
+
+
+ submit = (volatile char *)(sc->sram + 0xfc01c0);
+
+ myri10ge_pio_copy(submit, buf, 64);
+ mb();
+ DELAY(1000);
+ mb();
+ i = 0;
+ while (*confirm != 0xffffffff && i < 20) {
+ DELAY(1000);
+ i++;
+ }
+ if (*confirm != 0xffffffff) {
+ device_printf(sc->dev, "dummy rdma %s failed (%p = 0x%x)",
+ (enable ? "enable" : "disable"), confirm,
+ *confirm);
+ }
+ return;
+}
+
+static int
+myri10ge_send_cmd(myri10ge_softc_t *sc, uint32_t cmd,
+ myri10ge_cmd_t *data)
+{
+ mcp_cmd_t *buf;
+ char buf_bytes[sizeof(*buf) + 8];
+ volatile mcp_cmd_response_t *response = sc->cmd;
+ volatile char *cmd_addr = sc->sram + MYRI10GE_MCP_CMD_OFFSET;
+ uint32_t dma_low, dma_high;
+ int sleep_total = 0;
+
+ /* ensure buf is aligned to 8 bytes */
+ buf = (mcp_cmd_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ buf->data0 = htobe32(data->data0);
+ buf->data1 = htobe32(data->data1);
+ buf->data2 = htobe32(data->data2);
+ buf->cmd = htobe32(cmd);
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+
+ buf->response_addr.low = htobe32(dma_low);
+ buf->response_addr.high = htobe32(dma_high);
+ mtx_lock(&sc->cmd_lock);
+ response->result = 0xffffffff;
+ mb();
+ myri10ge_pio_copy((volatile void *)cmd_addr, buf, sizeof (*buf));
+
+ /* wait up to 2 seconds */
+ for (sleep_total = 0; sleep_total < (2 * 1000); sleep_total += 10) {
+ bus_dmamap_sync(sc->cmd_dma.dmat,
+ sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
+ mb();
+ if (response->result != 0xffffffff) {
+ if (response->result == 0) {
+ data->data0 = be32toh(response->data);
+ mtx_unlock(&sc->cmd_lock);
+ return 0;
+ } else {
+ device_printf(sc->dev,
+ "myri10ge: command %d "
+ "failed, result = %d\n",
+ cmd, be32toh(response->result));
+ mtx_unlock(&sc->cmd_lock);
+ return ENXIO;
+ }
+ }
+ DELAY(1000 * 10);
+ }
+ mtx_unlock(&sc->cmd_lock);
+ device_printf(sc->dev, "myri10ge: command %d timed out"
+ "result = %d\n",
+ cmd, be32toh(response->result));
+ return EAGAIN;
+}
+
+
+static int
+myri10ge_load_firmware(myri10ge_softc_t *sc)
+{
+ volatile uint32_t *confirm;
+ volatile char *submit;
+ char buf_bytes[72];
+ uint32_t *buf, size, dma_low, dma_high;
+ int status, i;
+
+ buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ size = sc->sram_size;
+ status = myri10ge_load_firmware_helper(sc, &size);
+ if (status) {
+ device_printf(sc->dev, "firmware loading failed\n");
+ return status;
+ }
+ /* clear confirmation addr */
+ confirm = (volatile uint32_t *)sc->cmd;
+ *confirm = 0;
+ mb();
+ /* send a reload command to the bootstrap MCP, and wait for the
+ response in the confirmation address. The firmware should
+ write a -1 there to indicate it is alive and well
+ */
+
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+
+ buf[0] = htobe32(dma_high); /* confirm addr MSW */
+ buf[1] = htobe32(dma_low); /* confirm addr LSW */
+ buf[2] = htobe32(0xffffffff); /* confirm data */
+
+ /* FIX: All newest firmware should un-protect the bottom of
+ the sram before handoff. However, the very first interfaces
+ do not. Therefore the handoff copy must skip the first 8 bytes
+ */
+ /* where the code starts*/
+ buf[3] = htobe32(MYRI10GE_FW_OFFSET + 8);
+ buf[4] = htobe32(size - 8); /* length of code */
+ buf[5] = htobe32(8); /* where to copy to */
+ buf[6] = htobe32(0); /* where to jump to */
+
+ submit = (volatile char *)(sc->sram + 0xfc0000);
+ myri10ge_pio_copy(submit, buf, 64);
+ mb();
+ DELAY(1000);
+ mb();
+ i = 0;
+ while (*confirm != 0xffffffff && i < 20) {
+ DELAY(1000*10);
+ i++;
+ bus_dmamap_sync(sc->cmd_dma.dmat,
+ sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
+ }
+ if (*confirm != 0xffffffff) {
+ device_printf(sc->dev,"handoff failed (%p = 0x%x)",
+ confirm, *confirm);
+
+ return ENXIO;
+ }
+ myri10ge_dummy_rdma(sc, 1);
+ return 0;
+}
+
+static int
+myri10ge_update_mac_address(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ uint8_t *addr = sc->mac_addr;
+ int status;
+
+
+ cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+ | (addr[2] << 8) | addr[3]);
+
+ cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_SET_MAC_ADDRESS, &cmd);
+ return status;
+}
+
+static int
+myri10ge_change_pause(myri10ge_softc_t *sc, int pause)
+{
+ myri10ge_cmd_t cmd;
+ int status;
+
+ if (pause)
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_ENABLE_FLOW_CONTROL,
+ &cmd);
+ else
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_DISABLE_FLOW_CONTROL,
+ &cmd);
+
+ if (status) {
+ device_printf(sc->dev, "Failed to set flow control mode\n");
+ return ENXIO;
+ }
+ sc->pause = pause;
+ return 0;
+}
+
+static void
+myri10ge_change_promisc(myri10ge_softc_t *sc, int promisc)
+{
+ myri10ge_cmd_t cmd;
+ int status;
+
+ if (promisc)
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_ENABLE_PROMISC,
+ &cmd);
+ else
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_DISABLE_PROMISC,
+ &cmd);
+
+ if (status) {
+ device_printf(sc->dev, "Failed to set promisc mode\n");
+ }
+}
+
+static int
+myri10ge_reset(myri10ge_softc_t *sc)
+{
+
+ myri10ge_cmd_t cmd;
+ int status, i;
+
+ /* try to send a reset command to the card to see if it
+ is alive */
+ memset(&cmd, 0, sizeof (cmd));
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_RESET, &cmd);
+ if (status != 0) {
+ device_printf(sc->dev, "failed reset\n");
+ return ENXIO;
+ }
+
+ /* Now exchange information about interrupts */
+
+ cmd.data0 = (uint32_t)
+ (myri10ge_max_intr_slots * sizeof (*sc->intr.q[0]));
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_INTRQ_SIZE, &cmd);
+ for (i = 0; (status == 0) && (i < MYRI10GE_NUM_INTRQS); i++) {
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(sc->intr.dma[i].bus_addr);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(sc->intr.dma[i].bus_addr);
+ status |=
+ myri10ge_send_cmd(sc, (i +
+ MYRI10GE_MCP_CMD_SET_INTRQ0_DMA),
+ &cmd);
+ }
+
+ cmd.data0 = sc->intr_coal_delay = myri10ge_intr_coal_delay;
+ status |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY, &cmd);
+
+ if (sc->msi_enabled) {
+ status |= myri10ge_send_cmd
+ (sc, MYRI10GE_MCP_CMD_GET_IRQ_ACK_OFFSET, &cmd);
+ } else {
+ status |= myri10ge_send_cmd
+ (sc, MYRI10GE_MCP_CMD_GET_IRQ_ACK_DEASSERT_OFFSET,
+ &cmd);
+ }
+ if (status != 0) {
+ device_printf(sc->dev, "failed set interrupt parameters\n");
+ return status;
+ }
+ sc->irq_claim = (volatile uint32_t *)(sc->sram + cmd.data0);
+
+ /* reset mcp/driver shared state back to 0 */
+ sc->intr.seqnum = 0;
+ sc->intr.intrq = 0;
+ sc->intr.slot = 0;
+ sc->tx.req = 0;
+ sc->tx.done = 0;
+ sc->rx_big.cnt = 0;
+ sc->rx_small.cnt = 0;
+ sc->rdma_tags_available = 15;
+ status = myri10ge_update_mac_address(sc);
+ myri10ge_change_promisc(sc, 0);
+ myri10ge_change_pause(sc, sc->pause);
+ return status;
+}
+
+static int
+myri10ge_change_intr_coal(SYSCTL_HANDLER_ARGS)
+{
+ myri10ge_cmd_t cmd;
+ myri10ge_softc_t *sc;
+ unsigned int intr_coal_delay;
+ int err;
+
+ sc = arg1;
+ intr_coal_delay = sc->intr_coal_delay;
+ err = sysctl_handle_int(oidp, &intr_coal_delay, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (intr_coal_delay == sc->intr_coal_delay)
+ return 0;
+
+ if (intr_coal_delay == 0 || intr_coal_delay > 1000*1000)
+ return EINVAL;
+
+ sx_xlock(&sc->driver_lock);
+ cmd.data0 = intr_coal_delay;
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY,
+ &cmd);
+ if (err == 0) {
+ sc->intr_coal_delay = intr_coal_delay;
+ }
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static int
+myri10ge_change_flow_control(SYSCTL_HANDLER_ARGS)
+{
+ myri10ge_softc_t *sc;
+ unsigned int enabled;
+ int err;
+
+ sc = arg1;
+ enabled = sc->pause;
+ err = sysctl_handle_int(oidp, &enabled, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (enabled == sc->pause)
+ return 0;
+
+ sx_xlock(&sc->driver_lock);
+ err = myri10ge_change_pause(sc, enabled);
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static int
+myri10ge_handle_be32(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+
+ if (arg1 == NULL)
+ return EFAULT;
+ arg2 = be32toh(*(int *)arg1);
+ arg1 = NULL;
+ err = sysctl_handle_int(oidp, arg1, arg2, req);
+
+ return err;
+}
+
+static void
+myri10ge_add_sysctls(myri10ge_softc_t *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *children;
+ mcp_stats_t *fw;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+ fw = sc->fw_stats;
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "intr_coal_delay",
+ CTLTYPE_INT|CTLFLAG_RW, sc,
+ 0, myri10ge_change_intr_coal,
+ "I", "interrupt coalescing delay in usecs");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "flow_control_enabled",
+ CTLTYPE_INT|CTLFLAG_RW, sc,
+ 0, myri10ge_change_flow_control,
+ "I", "interrupt coalescing delay in usecs");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "skip_pio_read",
+ CTLFLAG_RW, &myri10ge_skip_pio_read,
+ 0, "Skip pio read in interrupt handler");
+
+ /* stats block from firmware is in network byte order.
+ Need to swap it */
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "link_up",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->link_up,
+ 0, myri10ge_handle_be32,
+ "I", "link up");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "rdma_tags_available",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->rdma_tags_available,
+ 0, myri10ge_handle_be32,
+ "I", "rdma_tags_available");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_link_overflow",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_link_overflow,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_link_overflow");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_link_error_or_filtered",
+ CTLTYPE_INT|CTLFLAG_RD,
+ &fw->dropped_link_error_or_filtered,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_link_error_or_filtered");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_runt",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_runt,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_runt");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_overrun",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_overrun,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_overrun");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_no_small_buffer",
+ CTLTYPE_INT|CTLFLAG_RD,
+ &fw->dropped_no_small_buffer,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_no_small_buffer");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_no_big_buffer",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_no_big_buffer,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_no_big_buffer");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_interrupt_busy",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_interrupt_busy,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_interrupt_busy");
+
+ /* host counters exported for debugging */
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tx_req",
+ CTLFLAG_RD, &sc->tx.req,
+ 0, "tx_req");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tx_done",
+ CTLFLAG_RD, &sc->tx.done,
+ 0, "tx_done");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "rx_small_cnt",
+ CTLFLAG_RD, &sc->rx_small.cnt,
+ 0, "rx_small_cnt");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "rx_big_cnt",
+ CTLFLAG_RD, &sc->rx_big.cnt,
+ 0, "rx_small_cnt");
+
+}
+
+/* copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
+ backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(myri10ge_tx_buf_t *tx,
+ mcp_kreq_ether_send_t *src, int cnt)
+{
+ int idx, starting_slot;
+ starting_slot = tx->req;
+ while (cnt > 1) {
+ cnt--;
+ idx = (starting_slot + cnt) & tx->mask;
+ myri10ge_pio_copy(&tx->lanai[idx],
+ &src[cnt], sizeof(*src));
+ mb();
+ }
+}
+
+/*
+ * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic. We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain
+ */
+
+static inline void
+myri10ge_submit_req(myri10ge_tx_buf_t *tx, mcp_kreq_ether_send_t *src,
+ int cnt)
+{
+ int idx, i;
+ uint32_t *src_ints;
+ volatile uint32_t *dst_ints;
+ mcp_kreq_ether_send_t *srcp;
+ volatile mcp_kreq_ether_send_t *dstp, *dst;
+
+
+ idx = tx->req & tx->mask;
+
+ src->flags &= ~(htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID));
+ mb();
+ dst = dstp = &tx->lanai[idx];
+ srcp = src;
+
+ if ((idx + cnt) < tx->mask) {
+ for (i = 0; i < (cnt - 1); i += 2) {
+ myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+ mb(); /* force write every 32 bytes */
+ srcp += 2;
+ dstp += 2;
+ }
+ } else {
+ /* submit all but the first request, and ensure
+ that it is submitted below */
+ myri10ge_submit_req_backwards(tx, src, cnt);
+ i = 0;
+ }
+ if (i < cnt) {
+ /* submit the first request */
+ myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+ mb(); /* barrier before setting valid flag */
+ }
+
+ /* re-write the last 32-bits with the valid flags */
+ src->flags |= htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID);
+ src_ints = (uint32_t *)src;
+ src_ints+=3;
+ dst_ints = (volatile uint32_t *)dst;
+ dst_ints+=3;
+ *dst_ints = *src_ints;
+ tx->req += cnt;
+ mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(myri10ge_tx_buf_t *tx,
+ mcp_kreq_ether_send_t *src, int cnt)
+{
+ tx->req += cnt;
+ mb();
+ while (cnt >= 4) {
+ myri10ge_pio_copy((volatile char *)tx->wc_fifo, src, 64);
+ mb();
+ src += 4;
+ cnt -= 4;
+ }
+ if (cnt > 0) {
+ /* pad it to 64 bytes. The src is 64 bytes bigger than it
+ needs to be so that we don't overrun it */
+ myri10ge_pio_copy(tx->wc_fifo + (cnt<<18), src, 64);
+ mb();
+ }
+}
+
+static void
+myri10ge_encap(myri10ge_softc_t *sc, struct mbuf *m)
+{
+ mcp_kreq_ether_send_t *req;
+ bus_dma_segment_t seg_list[MYRI10GE_MCP_ETHER_MAX_SEND_DESC];
+ bus_dma_segment_t *seg;
+ struct mbuf *m_tmp;
+ struct ifnet *ifp;
+ myri10ge_tx_buf_t *tx;
+ struct ether_header *eh;
+ struct ip *ip;
+ int cnt, cum_len, err, i, idx;
+ uint16_t flags, pseudo_hdr_offset;
+ uint8_t cksum_offset;
+
+
+
+ ifp = sc->ifp;
+ tx = &sc->tx;
+
+ /* (try to) map the frame for DMA */
+ idx = tx->req & tx->mask;
+ err = bus_dmamap_load_mbuf_sg(tx->dmat, tx->info[idx].map,
+ m, seg_list, &cnt,
+ BUS_DMA_NOWAIT);
+ if (err == EFBIG) {
+ /* Too many segments in the chain. Try
+ to defrag */
+ m_tmp = m_defrag(m, M_NOWAIT);
+ if (m_tmp == NULL) {
+ goto drop;
+ }
+ m = m_tmp;
+ err = bus_dmamap_load_mbuf_sg(tx->dmat,
+ tx->info[idx].map,
+ m, seg_list, &cnt,
+ BUS_DMA_NOWAIT);
+ }
+ if (err != 0) {
+ device_printf(sc->dev, "bus_dmamap_load_mbuf_sg returned %d\n",
+ err);
+ goto drop;
+ }
+ bus_dmamap_sync(tx->dmat, tx->info[idx].map,
+ BUS_DMASYNC_PREWRITE);
+
+ req = tx->req_list;
+ cksum_offset = 0;
+ flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID |
+ MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST);
+
+ /* checksum offloading? */
+ if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) {
+ eh = mtod(m, struct ether_header *);
+ ip = (struct ip *) (eh + 1);
+ cksum_offset = sizeof(*eh) + (ip->ip_hl << 2);
+ pseudo_hdr_offset = cksum_offset + m->m_pkthdr.csum_data;
+ req->pseudo_hdr_offset = htobe16(pseudo_hdr_offset);
+ req->cksum_offset = cksum_offset;
+ flags |= htobe16(MYRI10GE_MCP_ETHER_FLAGS_CKSUM);
+ }
+ if (m->m_pkthdr.len < 512)
+ req->flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_FIRST |
+ MYRI10GE_MCP_ETHER_FLAGS_SMALL);
+ else
+ req->flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_FIRST);
+
+ /* convert segments into a request list */
+ cum_len = 0;
+ seg = seg_list;
+ for (i = 0; i < cnt; i++) {
+ req->addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg->ds_addr));
+ req->addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg->ds_addr));
+ req->length = htobe16(seg->ds_len);
+ req->cksum_offset = cksum_offset;
+ if (cksum_offset > seg->ds_len)
+ cksum_offset -= seg->ds_len;
+ else
+ cksum_offset = 0;
+ req->flags |= flags | ((cum_len & 1) *
+ htobe16(MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD));
+ cum_len += seg->ds_len;
+ seg++;
+ req++;
+ req->flags = 0;
+ }
+ req--;
+ /* pad runts to 60 bytes */
+ if (cum_len < 60) {
+ req++;
+ req->addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(sc->zeropad_dma.bus_addr));
+ req->addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(sc->zeropad_dma.bus_addr));
+ req->length = htobe16(60 - cum_len);
+ req->cksum_offset = cksum_offset;
+ req->flags |= flags | ((cum_len & 1) *
+ htobe16(MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD));
+ cnt++;
+ }
+ req->flags &= ~(htobe16(MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST));
+ tx->info[idx].m = m;
+ if (tx->wc_fifo == NULL)
+ myri10ge_submit_req(tx, tx->req_list, cnt);
+ else
+ myri10ge_submit_req_wc(tx, tx->req_list, cnt);
+ return;
+
+drop:
+ m_freem(m);
+ ifp->if_oerrors++;
+ return;
+}
+
+
+static void
+myri10ge_start_locked(myri10ge_softc_t *sc)
+{
+ int avail;
+ struct mbuf *m;
+ struct ifnet *ifp;
+
+
+ ifp = sc->ifp;
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ /* dequeue the packet */
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+
+ /* let BPF see it */
+ BPF_MTAP(ifp, m);
+
+ /* give it to the nic */
+ myri10ge_encap(sc, m);
+
+ /* leave an extra slot keep the ring from wrapping */
+ avail = sc->tx.mask - (sc->tx.req - sc->tx.done);
+ if (avail < MYRI10GE_MCP_ETHER_MAX_SEND_DESC) {
+ sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ }
+ }
+}
+
+static void
+myri10ge_start(struct ifnet *ifp)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+
+
+ mtx_lock(&sc->tx_lock);
+ myri10ge_start_locked(sc);
+ mtx_unlock(&sc->tx_lock);
+}
+
+static int
+myri10ge_get_buf_small(myri10ge_softc_t *sc, bus_dmamap_t map, int idx)
+{
+ bus_dma_segment_t seg;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx = &sc->rx_small;
+ int cnt, err;
+
+ m = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ rx->alloc_fail++;
+ err = ENOBUFS;
+ goto done;
+ }
+ m->m_len = MHLEN;
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ &seg, &cnt, BUS_DMA_NOWAIT);
+ if (err != 0) {
+ m_free(m);
+ goto done;
+ }
+ rx->info[idx].m = m;
+ rx->shadow[idx].addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg.ds_addr));
+ rx->shadow[idx].addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg.ds_addr));
+
+done:
+ if ((idx & 7) == 7) {
+ myri10ge_pio_copy(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7],
+ 8 * sizeof (*rx->lanai));
+ mb();
+ }
+ return err;
+}
+
+static int
+myri10ge_get_buf_big(myri10ge_softc_t *sc, bus_dmamap_t map, int idx)
+{
+ bus_dma_segment_t seg;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx = &sc->rx_big;
+ int cnt, err;
+
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, sc->big_bytes);
+ if (m == NULL) {
+ rx->alloc_fail++;
+ err = ENOBUFS;
+ goto done;
+ }
+ m->m_len = sc->big_bytes;
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ &seg, &cnt, BUS_DMA_NOWAIT);
+ if (err != 0) {
+ m_free(m);
+ goto done;
+ }
+ rx->info[idx].m = m;
+ rx->shadow[idx].addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg.ds_addr));
+ rx->shadow[idx].addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg.ds_addr));
+
+done:
+ if ((idx & 7) == 7) {
+ myri10ge_pio_copy(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7],
+ 8 * sizeof (*rx->lanai));
+ mb();
+ }
+ return err;
+}
+
+static inline void
+myri10ge_rx_done_big(myri10ge_softc_t *sc, int len, int csum, int flags)
+{
+ struct ifnet *ifp;
+ struct mbuf *m = 0; /* -Wunitialized */
+ struct mbuf *m_prev = 0; /* -Wunitialized */
+ struct mbuf *m_head = 0;
+ bus_dmamap_t old_map;
+ myri10ge_rx_buf_t *rx;
+ int idx;
+
+
+ rx = &sc->rx_big;
+ ifp = sc->ifp;
+ while (len > 0) {
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ /* save a pointer to the received mbuf */
+ m = rx->info[idx].m;
+ /* try to replace the received mbuf */
+ if (myri10ge_get_buf_big(sc, rx->extra_map, idx)) {
+ goto drop;
+ }
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+
+ /* chain multiple segments together */
+ if (!m_head) {
+ m_head = m;
+ /* mcp implicitly skips 1st bytes so that
+ * packet is properly aligned */
+ m->m_data += MYRI10GE_MCP_ETHER_PAD;
+ m->m_pkthdr.len = len;
+ m->m_len = sc->big_bytes - MYRI10GE_MCP_ETHER_PAD;
+ } else {
+ m->m_len = sc->big_bytes;
+ m->m_flags &= ~M_PKTHDR;
+ m_prev->m_next = m;
+ }
+ len -= m->m_len;
+ m_prev = m;
+ }
+
+ /* trim trailing garbage from the last mbuf in the chain. If
+ * there is any garbage, len will be negative */
+ m->m_len += len;
+
+ /* if the checksum is valid, mark it in the mbuf header */
+ if (sc->csum_flag & flags) {
+ m_head->m_pkthdr.csum_data = csum;
+ m_head->m_pkthdr.csum_flags = CSUM_DATA_VALID;
+ }
+
+ /* pass the frame up the stack */
+ m_head->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+ (*ifp->if_input)(ifp, m_head);
+ return;
+
+drop:
+ /* drop the frame -- the old mbuf(s) are re-cycled by running
+ every slot through the allocator */
+ if (m_head) {
+ len -= sc->big_bytes;
+ m_freem(m_head);
+ } else {
+ len -= (sc->big_bytes + MYRI10GE_MCP_ETHER_PAD);
+ }
+ while ((int)len > 0) {
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ m = rx->info[idx].m;
+ if (0 == (myri10ge_get_buf_big(sc, rx->extra_map, idx))) {
+ m_freem(m);
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+ }
+ len -= sc->big_bytes;
+ }
+
+ ifp->if_ierrors++;
+
+}
+
+
+static inline void
+myri10ge_rx_done_small(myri10ge_softc_t *sc, uint32_t len,
+ uint32_t csum, uint32_t flags)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx;
+ bus_dmamap_t old_map;
+ int idx;
+
+ ifp = sc->ifp;
+ rx = &sc->rx_small;
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ /* save a pointer to the received mbuf */
+ m = rx->info[idx].m;
+ /* try to replace the received mbuf */
+ if (myri10ge_get_buf_small(sc, rx->extra_map, idx)) {
+ /* drop the frame -- the old mbuf is re-cycled */
+ ifp->if_ierrors++;
+ return;
+ }
+
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+
+ /* mcp implicitly skips 1st 2 bytes so that packet is properly
+ * aligned */
+ m->m_data += MYRI10GE_MCP_ETHER_PAD;
+
+ /* if the checksum is valid, mark it in the mbuf header */
+ if (sc->csum_flag & flags) {
+ m->m_pkthdr.csum_data = csum;
+ m->m_pkthdr.csum_flags = CSUM_DATA_VALID;
+ }
+
+ /* pass the frame up the stack */
+ m->m_pkthdr.rcvif = ifp;
+ m->m_len = m->m_pkthdr.len = len;
+ ifp->if_ipackets++;
+ (*ifp->if_input)(ifp, m);
+}
+
+static inline void
+myri10ge_tx_done(myri10ge_softc_t *sc, uint32_t mcp_idx)
+{
+ struct ifnet *ifp;
+ myri10ge_tx_buf_t *tx;
+ struct mbuf *m;
+ bus_dmamap_t map;
+ int idx;
+
+ tx = &sc->tx;
+ ifp = sc->ifp;
+ while (tx->done != mcp_idx) {
+ idx = tx->done & tx->mask;
+ tx->done++;
+ m = tx->info[idx].m;
+ /* mbuf and DMA map only attached to the first
+ segment per-mbuf */
+ if (m != NULL) {
+ ifp->if_opackets++;
+ tx->info[idx].m = NULL;
+ map = tx->info[idx].map;
+ bus_dmamap_unload(tx->dmat, map);
+ m_freem(m);
+ }
+ }
+
+ /* If we have space, clear IFF_OACTIVE to tell the stack that
+ its OK to send packets */
+
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE &&
+ tx->req - tx->done < (tx->mask + 1)/4) {
+ mtx_lock(&sc->tx_lock);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ myri10ge_start_locked(sc);
+ mtx_unlock(&sc->tx_lock);
+ }
+}
+
+static void
+myri10ge_dump_interrupt_queues(myri10ge_softc_t *sc, int maxslot)
+{
+ int intrq, slot, type;
+ static int call_cnt = 0;
+
+ /* only do it a few times to avoid filling the message buffer */
+ if (call_cnt > 10)
+ return;
+
+ call_cnt++;
+
+ device_printf(sc->dev, "--------- Dumping interrupt queue state ----- \n");
+ device_printf(sc->dev, "currently expecting interrupts on queue %d\n",
+ sc->intr.intrq);
+ device_printf(sc->dev, " q slot status \n");
+ device_printf(sc->dev, "--- ---- -------- \n");
+ for (intrq = 0; intrq < 2; intrq++) {
+ for (slot = 0; slot <= maxslot; slot++) {
+ type = sc->intr.q[intrq][slot].type;
+#if 0
+ if (type == 0 && slot != 0)
+ continue;
+#endif
+ device_printf(sc->dev, "[%d]:[%d]: type = 0x%x\n", intrq, slot,
+ type);
+ device_printf(sc->dev, "[%d]:[%d]: flag = 0x%x\n", intrq, slot,
+ sc->intr.q[intrq][slot].flag);
+ device_printf(sc->dev, "[%d]:[%d]: index = 0x%x\n", intrq, slot,
+ be16toh(sc->intr.q[intrq][slot].index));
+ device_printf(sc->dev, "[%d]:[%d]: seqnum = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].seqnum));
+ device_printf(sc->dev, "[%d]:[%d]: data0 = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].data0));
+ device_printf(sc->dev, "[%d]:[%d]: data1 = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].data1));
+
+ }
+ }
+
+}
+
+static inline void
+myri10ge_claim_irq(myri10ge_softc_t *sc)
+{
+ volatile uint32_t dontcare;
+
+
+ *sc->irq_claim = 0;
+ mb();
+
+ /* do a PIO read to ensure that PIO write to claim the irq has
+ hit the nic before we exit the interrupt handler */
+ if (!myri10ge_skip_pio_read) {
+ dontcare = *(volatile uint32_t *)sc->sram;
+ mb();
+ }
+}
+
+static void
+myri10ge_intr(void *arg)
+{
+ myri10ge_softc_t *sc = arg;
+ int intrq, claimed, flags, count, length, ip_csum;
+ uint32_t raw, slot;
+ uint8_t type;
+
+
+ intrq = sc->intr.intrq;
+ claimed = 0;
+ bus_dmamap_sync(sc->intr.dma[intrq].dmat,
+ sc->intr.dma[intrq].map, BUS_DMASYNC_POSTREAD);
+ if (sc->msi_enabled) {
+ /* We know we can immediately claim the interrupt */
+ myri10ge_claim_irq(sc);
+ claimed = 1;
+ } else {
+ /* Check to see if we have the last event in the queue
+ ready. If so, ack it as early as possible. This
+ allows more time to get the interrupt line
+ de-asserted prior to the EOI and reduces the chance
+ of seeing a spurious irq caused by the interrupt
+ line remaining high after EOI */
+
+ slot = be16toh(sc->intr.q[intrq][0].index) - 1;
+ if (slot < myri10ge_max_intr_slots &&
+ sc->intr.q[intrq][slot].type != 0 &&
+ sc->intr.q[intrq][slot].flag != 0) {
+ myri10ge_claim_irq(sc);
+ claimed = 1;
+ }
+ }
+
+ /* walk each slot in the current queue, processing events until
+ we reach an event with a zero type */
+ for (slot = sc->intr.slot; slot < myri10ge_max_intr_slots; slot++) {
+ type = sc->intr.q[intrq][slot].type;
+
+ /* check for partially completed DMA of events when
+ using non-MSI interrupts */
+ if (__predict_false(!claimed)) {
+ mb();
+ /* look if there is somscing in the queue */
+ if (type == 0) {
+ /* save the current slot for the next
+ * time we (re-)enter this routine */
+ if (sc->intr.slot == slot) {
+ sc->intr.spurious++;
+ }
+ sc->intr.slot = slot;
+ return;
+ }
+ }
+ if (__predict_false(htobe32(sc->intr.q[intrq][slot].seqnum) !=
+ sc->intr.seqnum++)) {
+ device_printf(sc->dev, "Bad interrupt!\n");
+ device_printf(sc->dev,
+ "bad irq seqno"
+ "(got 0x%x, expected 0x%x) \n",
+ (unsigned int)htobe32(sc->intr.q[intrq][slot].seqnum),
+ sc->intr.seqnum);
+ device_printf(sc->dev, "intrq = %d, slot = %d\n",
+ intrq, slot);
+ myri10ge_dump_interrupt_queues(sc, slot);
+ device_printf(sc->dev,
+ "Disabling futher interrupt handling\n");
+ bus_teardown_intr(sc->dev, sc->irq_res,
+ sc->ih);
+ sc->ih = NULL;
+ return;
+ }
+
+ switch (type) {
+ case MYRI10GE_MCP_INTR_ETHER_SEND_DONE:
+ myri10ge_tx_done(sc, be32toh(sc->intr.q[intrq][slot].data0));
+
+ if (__predict_true(sc->intr.q[intrq][slot].data1 == 0))
+ break;
+
+ /* check the link state. Don't bother to
+ * byteswap, since it can just be 0 or 1 */
+ if (sc->link_state != sc->fw_stats->link_up) {
+ sc->link_state = sc->fw_stats->link_up;
+ if (sc->link_state) {
+ if_link_state_change(sc->ifp,
+ LINK_STATE_UP);
+ device_printf(sc->dev,
+ "link up\n");
+ } else {
+ if_link_state_change(sc->ifp,
+ LINK_STATE_DOWN);
+ device_printf(sc->dev,
+ "link down\n");
+ }
+ }
+ if (sc->rdma_tags_available !=
+ be32toh(sc->fw_stats->rdma_tags_available)) {
+ sc->rdma_tags_available =
+ be32toh(sc->fw_stats->rdma_tags_available);
+ device_printf(sc->dev, "RDMA timed out!"
+ " %d tags left\n",
+ sc->rdma_tags_available);
+ }
+
+ break;
+
+
+ case MYRI10GE_MCP_INTR_ETHER_RECV_SMALL:
+ raw = be32toh(sc->intr.q[intrq][slot].data0);
+ count = 0xff & raw;
+ flags = raw >> 8;
+ raw = be32toh(sc->intr.q[intrq][slot].data1);
+ ip_csum = raw >> 16;
+ length = 0xffff & raw;
+ myri10ge_rx_done_small(sc, length, ip_csum,
+ flags);
+ break;
+
+ case MYRI10GE_MCP_INTR_ETHER_RECV_BIG:
+ raw = be32toh(sc->intr.q[intrq][slot].data0);
+ count = 0xff & raw;
+ flags = raw >> 8;
+ raw = be32toh(sc->intr.q[intrq][slot].data1);
+ ip_csum = raw >> 16;
+ length = 0xffff & raw;
+ myri10ge_rx_done_big(sc, length, ip_csum,
+ flags);
+
+ break;
+
+ case MYRI10GE_MCP_INTR_LINK_CHANGE:
+ /* not yet implemented in firmware */
+ break;
+
+ case MYRI10GE_MCP_INTR_ETHER_DOWN:
+ sc->down_cnt++;
+ wakeup(&sc->down_cnt);
+ break;
+
+ default:
+ device_printf(sc->dev, "Unknown interrupt type %d\n",
+ type);
+ }
+ sc->intr.q[intrq][slot].type = 0;
+ if (sc->intr.q[intrq][slot].flag != 0) {
+ if (!claimed) {
+ myri10ge_claim_irq(sc);
+ }
+ sc->intr.slot = 0;
+ sc->intr.q[intrq][slot].flag = 0;
+ sc->intr.intrq = ((intrq + 1) & 1);
+ return;
+ }
+ }
+
+ /* we should never be here unless we're on a shared irq and we have
+ not finished setting up the device */
+ return;
+}
+
+static void
+myri10ge_watchdog(struct ifnet *ifp)
+{
+ printf("%s called\n", __FUNCTION__);
+}
+
+static void
+myri10ge_init(void *arg)
+{
+}
+
+
+
+static void
+myri10ge_free_mbufs(myri10ge_softc_t *sc)
+{
+ int i;
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ m_freem(sc->rx_big.info[i].m);
+ sc->rx_big.info[i].m = NULL;
+ }
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ m_freem(sc->rx_big.info[i].m);
+ sc->rx_big.info[i].m = NULL;
+ }
+
+ for (i = 0; i <= sc->tx.mask; i++) {
+ if (sc->tx.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->tx.dmat,
+ sc->tx.info[i].map);
+ m_freem(sc->tx.info[i].m);
+ sc->tx.info[i].m = NULL;
+ }
+}
+
+static void
+myri10ge_free_rings(myri10ge_softc_t *sc)
+{
+ int i;
+
+ if (sc->tx.req_bytes != NULL) {
+ free(sc->tx.req_bytes, M_DEVBUF);
+ }
+ if (sc->rx_small.shadow != NULL)
+ free(sc->rx_small.shadow, M_DEVBUF);
+ if (sc->rx_big.shadow != NULL)
+ free(sc->rx_big.shadow, M_DEVBUF);
+ if (sc->tx.info != NULL) {
+ for (i = 0; i <= sc->tx.mask; i++) {
+ if (sc->tx.info[i].map != NULL)
+ bus_dmamap_destroy(sc->tx.dmat,
+ sc->tx.info[i].map);
+ }
+ free(sc->tx.info, M_DEVBUF);
+ }
+ if (sc->rx_small.info != NULL) {
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ if (sc->rx_small.info[i].map != NULL)
+ bus_dmamap_destroy(sc->rx_small.dmat,
+ sc->rx_small.info[i].map);
+ }
+ free(sc->rx_small.info, M_DEVBUF);
+ }
+ if (sc->rx_big.info != NULL) {
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].map != NULL)
+ bus_dmamap_destroy(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ }
+ free(sc->rx_big.info, M_DEVBUF);
+ }
+ if (sc->rx_big.extra_map != NULL)
+ bus_dmamap_destroy(sc->rx_big.dmat,
+ sc->rx_big.extra_map);
+ if (sc->rx_small.extra_map != NULL)
+ bus_dmamap_destroy(sc->rx_small.dmat,
+ sc->rx_small.extra_map);
+ if (sc->tx.dmat != NULL)
+ bus_dma_tag_destroy(sc->tx.dmat);
+ if (sc->rx_small.dmat != NULL)
+ bus_dma_tag_destroy(sc->rx_small.dmat);
+ if (sc->rx_big.dmat != NULL)
+ bus_dma_tag_destroy(sc->rx_big.dmat);
+}
+
+static int
+myri10ge_alloc_rings(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int tx_ring_size, rx_ring_size;
+ int tx_ring_entries, rx_ring_entries;
+ int i, err;
+ unsigned long bytes;
+
+ /* get ring sizes */
+ err = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_SEND_RING_SIZE,
+ &cmd);
+ tx_ring_size = cmd.data0;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_RX_RING_SIZE,
+ &cmd);
+ if (err != 0) {
+ device_printf(sc->dev, "Cannot determine ring sizes\n");
+ goto abort_with_nothing;
+ }
+
+ rx_ring_size = cmd.data0;
+
+ tx_ring_entries = tx_ring_size / sizeof (mcp_kreq_ether_send_t);
+ rx_ring_entries = rx_ring_size / sizeof (mcp_dma_addr_t);
+ sc->ifp->if_snd.ifq_maxlen = tx_ring_entries - 1;
+ sc->ifp->if_snd.ifq_drv_maxlen = sc->ifp->if_snd.ifq_maxlen;
+
+ sc->tx.mask = tx_ring_entries - 1;
+ sc->rx_small.mask = sc->rx_big.mask = rx_ring_entries - 1;
+
+ err = ENOMEM;
+
+ /* allocate the tx request copy block */
+ bytes = 8 +
+ sizeof (*sc->tx.req_list) * (MYRI10GE_MCP_ETHER_MAX_SEND_DESC + 4);
+ sc->tx.req_bytes = malloc(bytes, M_DEVBUF, M_WAITOK);
+ if (sc->tx.req_bytes == NULL)
+ goto abort_with_nothing;
+ /* ensure req_list entries are aligned to 8 bytes */
+ sc->tx.req_list = (mcp_kreq_ether_send_t *)
+ ((unsigned long)(sc->tx.req_bytes + 7) & ~7UL);
+
+ /* allocate the rx shadow rings */
+ bytes = rx_ring_entries * sizeof (*sc->rx_small.shadow);
+ sc->rx_small.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_small.shadow == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_big.shadow);
+ sc->rx_big.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_big.shadow == NULL)
+ goto abort_with_alloc;
+
+ /* allocate the host info rings */
+ bytes = tx_ring_entries * sizeof (*sc->tx.info);
+ sc->tx.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->tx.info == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_small.info);
+ sc->rx_small.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_small.info == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_big.info);
+ sc->rx_big.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_big.info == NULL)
+ goto abort_with_alloc;
+
+ /* allocate the busdma resources */
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ sc->tx.boundary, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MYRI10GE_MAX_ETHER_MTU,/* maxsize */
+ MYRI10GE_MCP_ETHER_MAX_SEND_DESC,/* num segs */
+ sc->tx.boundary, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->tx.dmat); /* tag */
+
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating tx dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MHLEN, /* maxsize */
+ 1, /* num segs */
+ MHLEN, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->rx_small.dmat); /* tag */
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating rx_small dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ 4096, /* maxsize */
+ 1, /* num segs */
+ 4096, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->rx_big.dmat); /* tag */
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating rx_big dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ /* now use these tags to setup dmamaps for each slot
+ in each ring */
+ for (i = 0; i <= sc->tx.mask; i++) {
+ err = bus_dmamap_create(sc->tx.dmat, 0,
+ &sc->tx.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d tx dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ err = bus_dmamap_create(sc->rx_small.dmat, 0,
+ &sc->rx_small.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d rx_small dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ err = bus_dmamap_create(sc->rx_small.dmat, 0,
+ &sc->rx_small.extra_map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d extra rx_small dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ err = bus_dmamap_create(sc->rx_big.dmat, 0,
+ &sc->rx_big.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d rx_big dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ err = bus_dmamap_create(sc->rx_big.dmat, 0,
+ &sc->rx_big.extra_map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d extra rx_big dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ return 0;
+
+abort_with_alloc:
+ myri10ge_free_rings(sc);
+
+abort_with_nothing:
+ return err;
+}
+
+static int
+myri10ge_open(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int i, err;
+ bus_dmamap_t map;
+
+
+ err = myri10ge_reset(sc);
+ if (err != 0) {
+ device_printf(sc->dev, "failed to reset\n");
+ return EIO;
+ }
+
+ if (MCLBYTES >=
+ sc->ifp->if_mtu + ETHER_HDR_LEN + MYRI10GE_MCP_ETHER_PAD)
+ sc->big_bytes = MCLBYTES;
+ else
+ sc->big_bytes = MJUMPAGESIZE;
+
+ err = myri10ge_alloc_rings(sc);
+ if (err != 0) {
+ device_printf(sc->dev, "failed to allocate rings\n");
+ return err;
+ }
+
+ err = bus_setup_intr(sc->dev, sc->irq_res,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ myri10ge_intr, sc, &sc->ih);
+ if (err != 0) {
+ goto abort_with_rings;
+ }
+
+ /* get the lanai pointers to the send and receive rings */
+
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_GET_SEND_OFFSET, &cmd);
+ sc->tx.lanai =
+ (volatile mcp_kreq_ether_send_t *)(sc->sram + cmd.data0);
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_SMALL_RX_OFFSET, &cmd);
+ sc->rx_small.lanai =
+ (volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
+ err |= myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_GET_BIG_RX_OFFSET, &cmd);
+ sc->rx_big.lanai =
+ (volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
+
+ if (err != 0) {
+ device_printf(sc->dev,
+ "failed to get ring sizes or locations\n");
+ err = EIO;
+ goto abort_with_irq;
+ }
+
+ if (sc->wc) {
+ sc->tx.wc_fifo = sc->sram + 0x200000;
+ sc->rx_small.wc_fifo = sc->sram + 0x300000;
+ sc->rx_big.wc_fifo = sc->sram + 0x340000;
+ } else {
+ sc->tx.wc_fifo = 0;
+ sc->rx_small.wc_fifo = 0;
+ sc->rx_big.wc_fifo = 0;
+ }
+
+
+ /* stock receive rings */
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ map = sc->rx_small.info[i].map;
+ err = myri10ge_get_buf_small(sc, map, i);
+ if (err) {
+ device_printf(sc->dev, "alloced %d/%d smalls\n",
+ i, sc->rx_small.mask + 1);
+ goto abort;
+ }
+ }
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ map = sc->rx_big.info[i].map;
+ err = myri10ge_get_buf_big(sc, map, i);
+ if (err) {
+ device_printf(sc->dev, "alloced %d/%d bigs\n",
+ i, sc->rx_big.mask + 1);
+ goto abort;
+ }
+ }
+
+ /* Give the firmware the mtu and the big and small buffer
+ sizes. The firmware wants the big buf size to be a power
+ of two. Luckily, FreeBSD's clusters are powers of two */
+ cmd.data0 = sc->ifp->if_mtu + ETHER_HDR_LEN;
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_MTU, &cmd);
+ cmd.data0 = MHLEN;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_SMALL_BUFFER_SIZE,
+ &cmd);
+ cmd.data0 = sc->big_bytes;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_BIG_BUFFER_SIZE,
+ &cmd);
+ /* Now give him the pointer to the stats block */
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(sc->fw_stats_dma.bus_addr);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(sc->fw_stats_dma.bus_addr);
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_STATS_DMA, &cmd);
+
+ if (err != 0) {
+ device_printf(sc->dev, "failed to setup params\n");
+ goto abort;
+ }
+
+ /* Finally, start the firmware running */
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_ETHERNET_UP, &cmd);
+ if (err) {
+ device_printf(sc->dev, "Couldn't bring up link\n");
+ goto abort;
+ }
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ return 0;
+
+
+abort:
+ myri10ge_free_mbufs(sc);
+abort_with_irq:
+ bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+abort_with_rings:
+ myri10ge_free_rings(sc);
+ return err;
+}
+
+static int
+myri10ge_close(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int err, old_down_cnt;
+
+ sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ old_down_cnt = sc->down_cnt;
+ mb();
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_ETHERNET_DOWN, &cmd);
+ if (err) {
+ device_printf(sc->dev, "Couldn't bring down link\n");
+ }
+ if (old_down_cnt == sc->down_cnt) {
+ /* wait for down irq */
+ (void)tsleep(&sc->down_cnt, PWAIT, "down myri10ge", hz);
+ }
+ if (old_down_cnt == sc->down_cnt) {
+ device_printf(sc->dev, "never got down irq\n");
+ }
+ if (sc->ih != NULL)
+ bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+ myri10ge_free_mbufs(sc);
+ myri10ge_free_rings(sc);
+ return 0;
+}
+
+
+static int
+myri10ge_media_change(struct ifnet *ifp)
+{
+ return EINVAL;
+}
+
+static int
+myri10ge_change_mtu(myri10ge_softc_t *sc, int mtu)
+{
+ struct ifnet *ifp = sc->ifp;
+ int real_mtu, old_mtu;
+ int err = 0;
+
+
+ real_mtu = mtu + ETHER_HDR_LEN;
+ if ((real_mtu > MYRI10GE_MAX_ETHER_MTU) ||
+ real_mtu < 60)
+ return EINVAL;
+ sx_xlock(&sc->driver_lock);
+ old_mtu = ifp->if_mtu;
+ ifp->if_mtu = mtu;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ myri10ge_close(sc);
+ err = myri10ge_open(sc);
+ if (err != 0) {
+ ifp->if_mtu = old_mtu;
+ myri10ge_close(sc);
+ (void) myri10ge_open(sc);
+ }
+ }
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static void
+myri10ge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+
+
+ if (sc == NULL)
+ return;
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_status |= sc->fw_stats->link_up ? IFM_ACTIVE : 0;
+ ifmr->ifm_active = IFM_AUTO | IFM_ETHER;
+ ifmr->ifm_active |= sc->fw_stats->link_up ? IFM_FDX : 0;
+}
+
+static int
+myri10ge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int err, mask;
+
+ err = 0;
+ switch (command) {
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ err = ether_ioctl(ifp, command, data);
+ break;
+
+ case SIOCSIFMTU:
+ err = myri10ge_change_mtu(sc, ifr->ifr_mtu);
+ break;
+
+ case SIOCSIFFLAGS:
+ sx_xlock(&sc->driver_lock);
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ err = myri10ge_open(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ myri10ge_close(sc);
+ }
+ sx_xunlock(&sc->driver_lock);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ err = 0;
+ break;
+
+ case SIOCSIFCAP:
+ sx_xlock(&sc->driver_lock);
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+ if (mask & IFCAP_TXCSUM) {
+ if (IFCAP_TXCSUM & ifp->if_capenable) {
+ ifp->if_capenable &= ~IFCAP_TXCSUM;
+ ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP);
+ } else {
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+ }
+ } else if (mask & IFCAP_RXCSUM) {
+ if (IFCAP_RXCSUM & ifp->if_capenable) {
+ ifp->if_capenable &= ~IFCAP_RXCSUM;
+ sc->csum_flag &= ~MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ } else {
+ ifp->if_capenable |= IFCAP_RXCSUM;
+ sc->csum_flag |= MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ }
+ }
+ sx_xunlock(&sc->driver_lock);
+ break;
+
+ case SIOCGIFMEDIA:
+ err = ifmedia_ioctl(ifp, (struct ifreq *)data,
+ &sc->media, command);
+ break;
+
+ default:
+ err = ENOTTY;
+ }
+ return err;
+}
+
+static void
+myri10ge_fetch_tunables(myri10ge_softc_t *sc)
+{
+
+ TUNABLE_INT_FETCH("hw.myri10ge.flow_control_enabled",
+ &myri10ge_flow_control);
+ TUNABLE_INT_FETCH("hw.myri10ge.intr_coal_delay",
+ &myri10ge_intr_coal_delay);
+ TUNABLE_INT_FETCH("hw.myri10ge.nvidia_ecrc_enable",
+ &myri10ge_nvidia_ecrc_enable);
+ TUNABLE_INT_FETCH("hw.myri10ge.skip_pio_read",
+ &myri10ge_skip_pio_read);
+
+ if (myri10ge_intr_coal_delay < 0 ||
+ myri10ge_intr_coal_delay > 10*1000)
+ myri10ge_intr_coal_delay = 30;
+ sc->pause = myri10ge_flow_control;
+}
+
+static int
+myri10ge_attach(device_t dev)
+{
+ myri10ge_softc_t *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ size_t bytes;
+ int rid, err, i;
+ uint16_t cmd;
+
+ sc->dev = dev;
+ myri10ge_fetch_tunables(sc);
+
+ err = bus_dma_tag_create(NULL, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MYRI10GE_MAX_ETHER_MTU,/* maxsize */
+ MYRI10GE_MCP_ETHER_MAX_SEND_DESC, /* num segs */
+ 4096, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lock */
+ &sc->parent_dmat); /* tag */
+
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating parent dmat\n",
+ err);
+ goto abort_with_nothing;
+ }
+
+ ifp = sc->ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ err = ENOSPC;
+ goto abort_with_parent_dmat;
+ }
+ mtx_init(&sc->cmd_lock, NULL,
+ MTX_NETWORK_LOCK, MTX_DEF);
+ mtx_init(&sc->tx_lock, device_get_nameunit(dev),
+ MTX_NETWORK_LOCK, MTX_DEF);
+ sx_init(&sc->driver_lock, device_get_nameunit(dev));
+
+ /* Enable DMA and Memory space access */
+ pci_enable_busmaster(dev);
+ cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ cmd |= PCIM_CMD_MEMEN;
+ pci_write_config(dev, PCIR_COMMAND, cmd, 2);
+
+ /* Map the board into the kernel */
+ rid = PCIR_BARS;
+ sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
+ ~0, 1, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not map memory\n");
+ err = ENXIO;
+ goto abort_with_lock;
+ }
+ sc->sram = rman_get_virtual(sc->mem_res);
+ sc->sram_size = 2*1024*1024 - (2*(48*1024)+(32*1024)) - 0x100;
+ if (sc->sram_size > rman_get_size(sc->mem_res)) {
+ device_printf(dev, "impossible memory region size %ld\n",
+ rman_get_size(sc->mem_res));
+ err = ENXIO;
+ goto abort_with_mem_res;
+ }
+
+ /* make NULL terminated copy of the EEPROM strings section of
+ lanai SRAM */
+ bzero(sc->eeprom_strings, MYRI10GE_EEPROM_STRINGS_SIZE);
+ bus_space_read_region_1(rman_get_bustag(sc->mem_res),
+ rman_get_bushandle(sc->mem_res),
+ sc->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
+ sc->eeprom_strings,
+ MYRI10GE_EEPROM_STRINGS_SIZE - 2);
+ err = myri10ge_parse_strings(sc);
+ if (err != 0)
+ goto abort_with_mem_res;
+
+ /* Enable write combining for efficient use of PCIe bus */
+ myri10ge_enable_wc(sc);
+
+ /* Allocate the out of band dma memory */
+ err = myri10ge_dma_alloc(sc, &sc->cmd_dma,
+ sizeof (myri10ge_cmd_t), 64);
+ if (err != 0)
+ goto abort_with_mem_res;
+ sc->cmd = (mcp_cmd_response_t *) sc->cmd_dma.addr;
+ err = myri10ge_dma_alloc(sc, &sc->zeropad_dma, 64, 64);
+ if (err != 0)
+ goto abort_with_cmd_dma;
+
+ err = myri10ge_dma_alloc(sc, &sc->fw_stats_dma,
+ sizeof (*sc->fw_stats), 64);
+ if (err != 0)
+ goto abort_with_zeropad_dma;
+ sc->fw_stats = (mcp_stats_t *)sc->fw_stats_dma.addr;
+
+
+ /* allocate interrupt queues */
+ bytes = myri10ge_max_intr_slots * sizeof (*sc->intr.q[0]);
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ err = myri10ge_dma_alloc(sc, &sc->intr.dma[i],
+ bytes, 4096);
+ if (err != 0)
+ goto abort_with_intrq;
+ sc->intr.q[i] = (mcp_slot_t *)sc->intr.dma[i].addr;
+ }
+
+ /* Add our ithread */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,
+ 1, RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not alloc interrupt\n");
+ goto abort_with_intrq;
+ }
+
+ /* load the firmware */
+ myri10ge_select_firmware(sc);
+
+ err = myri10ge_load_firmware(sc);
+ if (err != 0)
+ goto abort_with_irq_res;
+ err = myri10ge_reset(sc);
+ if (err != 0)
+ goto abort_with_irq_res;
+
+ /* hook into the network stack */
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_baudrate = 100000000;
+ ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM;
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+ ifp->if_capenable = ifp->if_capabilities;
+ sc->csum_flag |= MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ ifp->if_init = myri10ge_init;
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = myri10ge_ioctl;
+ ifp->if_start = myri10ge_start;
+ ifp->if_watchdog = myri10ge_watchdog;
+ ether_ifattach(ifp, sc->mac_addr);
+ /* ether_ifattach sets mtu to 1500 */
+ ifp->if_mtu = MYRI10GE_MAX_ETHER_MTU - ETHER_HDR_LEN;
+
+ /* Initialise the ifmedia structure */
+ ifmedia_init(&sc->media, 0, myri10ge_media_change,
+ myri10ge_media_status);
+ ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
+ myri10ge_add_sysctls(sc);
+ return 0;
+
+abort_with_irq_res:
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+abort_with_intrq:
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ if (sc->intr.q[i] == NULL)
+ continue;
+ sc->intr.q[i] = NULL;
+ myri10ge_dma_free(&sc->intr.dma[i]);
+ }
+ myri10ge_dma_free(&sc->fw_stats_dma);
+abort_with_zeropad_dma:
+ myri10ge_dma_free(&sc->zeropad_dma);
+abort_with_cmd_dma:
+ myri10ge_dma_free(&sc->cmd_dma);
+abort_with_mem_res:
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
+abort_with_lock:
+ pci_disable_busmaster(dev);
+ mtx_destroy(&sc->cmd_lock);
+ mtx_destroy(&sc->tx_lock);
+ sx_destroy(&sc->driver_lock);
+ if_free(ifp);
+abort_with_parent_dmat:
+ bus_dma_tag_destroy(sc->parent_dmat);
+
+abort_with_nothing:
+ return err;
+}
+
+static int
+myri10ge_detach(device_t dev)
+{
+ myri10ge_softc_t *sc = device_get_softc(dev);
+ int i;
+
+ sx_xlock(&sc->driver_lock);
+ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING)
+ myri10ge_close(sc);
+ sx_xunlock(&sc->driver_lock);
+ ether_ifdetach(sc->ifp);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ if (sc->intr.q[i] == NULL)
+ continue;
+ sc->intr.q[i] = NULL;
+ myri10ge_dma_free(&sc->intr.dma[i]);
+ }
+ myri10ge_dma_free(&sc->fw_stats_dma);
+ myri10ge_dma_free(&sc->zeropad_dma);
+ myri10ge_dma_free(&sc->cmd_dma);
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
+ pci_disable_busmaster(dev);
+ mtx_destroy(&sc->cmd_lock);
+ mtx_destroy(&sc->tx_lock);
+ sx_destroy(&sc->driver_lock);
+ if_free(sc->ifp);
+ bus_dma_tag_destroy(sc->parent_dmat);
+ return 0;
+}
+
+static int
+myri10ge_shutdown(device_t dev)
+{
+ return 0;
+}
+
+/*
+ This file uses Myri10GE driver indentation.
+
+ Local Variables:
+ c-file-style:"linux"
+ tab-width:8
+ End:
+*/
diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h
new file mode 100644
index 0000000..e4ce955
--- /dev/null
+++ b/sys/dev/mxge/if_mxge_var.h
@@ -0,0 +1,203 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+
+***************************************************************************/
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_NUM_INTRQS 2
+
+typedef struct {
+ void *addr;
+ bus_addr_t bus_addr;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t map;
+} myri10ge_dma_t;
+
+typedef struct myri10ge_intrq
+{
+ mcp_slot_t *q[MYRI10GE_NUM_INTRQS];
+ int intrq;
+ int slot;
+ int maxslots;
+ uint32_t seqnum;
+ uint32_t spurious;
+ uint32_t cnt;
+ myri10ge_dma_t dma[MYRI10GE_NUM_INTRQS];
+} myri10ge_intrq_t;
+
+
+typedef struct
+{
+ uint32_t data0;
+ uint32_t data1;
+ uint32_t data2;
+} myri10ge_cmd_t;
+
+struct myri10ge_buffer_state {
+ struct mbuf *m;
+ bus_dmamap_t map;
+};
+
+typedef struct
+{
+ volatile mcp_kreq_ether_recv_t *lanai; /* lanai ptr for recv ring */
+ volatile uint8_t *wc_fifo; /* w/c rx dma addr fifo address */
+ mcp_kreq_ether_recv_t *shadow; /* host shadow of recv ring */
+ struct myri10ge_buffer_state *info;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t extra_map;
+ int cnt;
+ int alloc_fail;
+ int mask; /* number of rx slots -1 */
+} myri10ge_rx_buf_t;
+
+typedef struct
+{
+ volatile mcp_kreq_ether_send_t *lanai; /* lanai ptr for sendq */
+ volatile uint8_t *wc_fifo; /* w/c send fifo address */
+ mcp_kreq_ether_send_t *req_list; /* host shadow of sendq */
+ char *req_bytes;
+ struct myri10ge_buffer_state *info;
+ bus_dma_tag_t dmat;
+ int req; /* transmits submitted */
+ int mask; /* number of transmit slots -1 */
+ int done; /* transmits completed */
+ int boundary; /* boundary transmits cannot cross*/
+} myri10ge_tx_buf_t;
+
+typedef struct {
+ struct ifnet* ifp;
+ int big_bytes;
+ struct mtx tx_lock;
+ int csum_flag; /* rx_csums? */
+ uint8_t mac_addr[6]; /* eeprom mac address */
+ myri10ge_tx_buf_t tx; /* transmit ring */
+ myri10ge_rx_buf_t rx_small;
+ myri10ge_rx_buf_t rx_big;
+ bus_dma_tag_t parent_dmat;
+ volatile uint8_t *sram;
+ int sram_size;
+ volatile uint32_t *irq_claim;
+ char *mac_addr_string;
+ char *product_code_string;
+ mcp_cmd_response_t *cmd;
+ myri10ge_dma_t cmd_dma;
+ myri10ge_dma_t zeropad_dma;
+ mcp_stats_t *fw_stats;
+ myri10ge_dma_t fw_stats_dma;
+ struct pci_dev *pdev;
+ int msi_enabled;
+ myri10ge_intrq_t intr;
+ int link_state;
+ unsigned int rdma_tags_available;
+ int intr_coal_delay;
+ int wc;
+ struct mtx cmd_lock;
+ struct sx driver_lock;
+ int wake_queue;
+ int stop_queue;
+ int down_cnt;
+ int watchdog_resets;
+ int tx_defragged;
+ int pause;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *ih;
+ char *fw_name;
+ char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+ char fw_version[128];
+ device_t dev;
+ struct ifmedia media;
+
+} myri10ge_softc_t;
+
+#define MYRI10GE_PCI_VENDOR_MYRICOM 0x14c1
+#define MYRI10GE_PCI_DEVICE_Z8E 0x0008
+
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((uint32_t)((uint64_t)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((uint32_t)(X))
+
+
+/* implement our own memory barriers, since bus_space_barrier
+ cannot handle write-combining regions */
+
+#if defined (__GNUC__)
+ #if #cpu(i386) || defined __i386 || defined i386 || defined __i386__ || #cpu(x86_64) || defined __x86_64__
+ #define mb() __asm__ __volatile__ ("sfence;": : :"memory")
+ #elif #cpu(sparc64) || defined sparc64 || defined __sparcv9
+ #define mb() __asm__ __volatile__ ("membar #MemIssue": : :"memory")
+ #elif #cpu(sparc) || defined sparc || defined __sparc__
+ #define mb() __asm__ __volatile__ ("stbar;": : :"memory")
+ #else
+ #define mb() /* XXX just to make this compile */
+ #endif
+#else
+ #error "unknown compiler"
+#endif
+
+static inline void
+myri10ge_pio_copy(volatile void *to_v, void *from_v, size_t size)
+{
+ register volatile uintptr_t *to;
+ volatile uintptr_t *from;
+ size_t i;
+
+ to = (volatile uintptr_t *) to_v;
+ from = from_v;
+ for (i = (size / sizeof (uintptr_t)); i; i--) {
+ *to = *from;
+ to++;
+ from++;
+ }
+
+}
+
+
+/*
+ This file uses Myri10GE driver indentation.
+
+ Local Variables:
+ c-file-style:"linux"
+ tab-width:8
+ End:
+*/
diff --git a/sys/dev/mxge/mcp_gen_header.h b/sys/dev/mxge/mcp_gen_header.h
new file mode 100644
index 0000000..7cb4491
--- /dev/null
+++ b/sys/dev/mxge/mcp_gen_header.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+#ifndef _mcp_gen_header_h
+#define _mcp_gen_header_h
+
+/* this file define a standard header used as a first entry point to
+ exchange information between firmware/driver and driver. The
+ header structure can be anywhere in the mcp. It will usually be in
+ the .data section, because some fields needs to be initialized at
+ compile time.
+ The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must
+ contains the location of the header.
+
+ Typically a MCP will start with the following:
+ .text
+ .space 52 ! to help catch MEMORY_INT errors
+ bt start ! jump to real code
+ nop
+ .long _gen_mcp_header
+
+ The source will have a definition like:
+
+ mcp_gen_header_t gen_mcp_header = {
+ .header_length = sizeof(mcp_gen_header_t),
+ .mcp_type = MCP_TYPE_XXX,
+ .version = "something $Id: mcp_gen_header.h,v 1.1 2005/12/23 02:10:44 gallatin Exp $",
+ .mcp_globals = (unsigned)&Globals
+ };
+*/
+
+
+#define MCP_HEADER_PTR_OFFSET 0x3c
+
+#define MCP_TYPE_MX 0x4d582020 /* "MX " */
+#define MCP_TYPE_PCIE 0x70636965 /* "PCIE" pcie-only MCP */
+#define MCP_TYPE_ETH 0x45544820 /* "ETH " */
+#define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */
+
+
+typedef struct mcp_gen_header {
+ /* the first 4 fields are filled at compile time */
+ unsigned header_length;
+ unsigned mcp_type;
+ char version[128];
+ unsigned mcp_globals; /* pointer to mcp-type specific structure */
+
+ /* filled by the MCP at run-time */
+ unsigned sram_size;
+ unsigned string_specs; /* either the original STRING_SPECS or a superset */
+ unsigned string_specs_len;
+
+ /* Fields above this comment are guaranteed to be present.
+
+ Fields below this comment are extensions added in later versions
+ of this struct, drivers should compare the header_length against
+ offsetof(field) to check wether a given MCP implements them.
+
+ Never remove any field. Keep everything naturally align.
+ */
+} mcp_gen_header_t;
+
+/* Macro to create a simple mcp header */
+#define MCP_GEN_HEADER_DECL(type, version_str, global_ptr) \
+ struct mcp_gen_header mcp_gen_header = { \
+ sizeof (struct mcp_gen_header), \
+ (type), \
+ version_str, \
+ (global_ptr), \
+ SRAM_SIZE, \
+ (unsigned int) STRING_SPECS, \
+ 256 \
+ }
+
+
+#endif /* _mcp_gen_header_h */
diff --git a/sys/dev/mxge/mxge_mcp.h b/sys/dev/mxge/mxge_mcp.h
new file mode 100644
index 0000000..de85fde
--- /dev/null
+++ b/sys/dev/mxge/mxge_mcp.h
@@ -0,0 +1,265 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+#ifndef _myri10ge_mcp_h
+#define _myri10ge_mcp_h
+
+#ifdef MYRI10GE_MCP
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#endif
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t high;
+ uint32_t low;
+} mcp_dma_addr_t;
+
+/* 16 Bytes */
+typedef struct
+{
+ uint32_t data0;
+ uint32_t data1;
+ uint32_t seqnum;
+ uint16_t index;
+ uint8_t flag;
+ uint8_t type;
+} mcp_slot_t;
+
+/* 64 Bytes */
+typedef struct
+{
+ uint32_t cmd;
+ uint32_t data0; /* will be low portion if data > 32 bits */
+ /* 8 */
+ uint32_t data1; /* will be high portion if data > 32 bits */
+ uint32_t data2; /* currently unused.. */
+ /* 16 */
+ mcp_dma_addr_t response_addr;
+ /* 24 */
+ uint8_t pad[40];
+} mcp_cmd_t;
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t data;
+ uint32_t result;
+} mcp_cmd_response_t;
+
+
+
+/*
+ flags used in mcp_kreq_ether_send_t:
+
+ The SMALL flag is only needed in the first segment. It is raised
+ for packets that are total less or equal 512 bytes.
+
+ The CKSUM flag must be set in all segments.
+
+ The PADDED flags is set if the packet needs to be padded, and it
+ must be set for all segments.
+
+ The MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD must be set if the cumulative
+ length of all previous segments was odd.
+*/
+
+
+#define MYRI10GE_MCP_ETHER_FLAGS_VALID 0x1
+#define MYRI10GE_MCP_ETHER_FLAGS_FIRST 0x2
+#define MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD 0x4
+#define MYRI10GE_MCP_ETHER_FLAGS_CKSUM 0x8
+#define MYRI10GE_MCP_ETHER_FLAGS_SMALL 0x10
+#define MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST 0x100
+#define MYRI10GE_MCP_ETHER_FLAGS_TSO_HDR 0x200
+#define MYRI10GE_MCP_ETHER_FLAGS_TSO 0x400
+
+#define MYRI10GE_MCP_ETHER_SEND_SMALL_SIZE 1520
+#define MYRI10GE_MCP_ETHER_MAX_MTU 9400
+
+typedef union mcp_pso_or_cumlen
+{
+ uint16_t pseudo_hdr_offset;
+ uint16_t cum_len;
+} mcp_pso_or_cumlen_t;
+
+#define MYRI10GE_MCP_ETHER_MAX_SEND_DESC 12
+#define MYRI10GE_MCP_ETHER_PAD 2
+
+/* 16 Bytes */
+typedef struct
+{
+ uint32_t addr_high;
+ uint32_t addr_low;
+ uint16_t length;
+ uint8_t pad;
+ uint8_t cksum_offset; /* where to start computing cksum */
+ uint16_t pseudo_hdr_offset;
+ uint16_t flags; /* as defined above */
+} mcp_kreq_ether_send_t;
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t addr_high;
+ uint32_t addr_low;
+} mcp_kreq_ether_recv_t;
+
+
+/* Commands */
+
+#define MYRI10GE_MCP_CMD_OFFSET 0xf80000
+
+typedef enum {
+ MYRI10GE_MCP_CMD_NONE = 0,
+ /* Reset the mcp, it is left in a safe state, waiting
+ for the driver to set all its parameters */
+ MYRI10GE_MCP_CMD_RESET,
+
+ /* get the version number of the current firmware..
+ (may be available in the eeprom strings..? */
+ MYRI10GE_MCP_GET_MCP_VERSION,
+
+
+ /* Parameters which must be set by the driver before it can
+ issue MYRI10GE_MCP_CMD_ETHERNET_UP. They persist until the next
+ MYRI10GE_MCP_CMD_RESET is issued */
+
+ MYRI10GE_MCP_CMD_SET_INTRQ0_DMA,
+ MYRI10GE_MCP_CMD_SET_INTRQ1_DMA,
+ MYRI10GE_MCP_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */
+ MYRI10GE_MCP_CMD_SET_SMALL_BUFFER_SIZE, /* in bytes */
+
+
+ /* Parameters which refer to lanai SRAM addresses where the
+ driver must issue PIO writes for various things */
+
+ MYRI10GE_MCP_CMD_GET_SEND_OFFSET,
+ MYRI10GE_MCP_CMD_GET_SMALL_RX_OFFSET,
+ MYRI10GE_MCP_CMD_GET_BIG_RX_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_ACK_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_DEASSERT_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_ACK_DEASSERT_OFFSET,
+
+ /* Parameters which refer to rings stored on the MCP,
+ and whose size is controlled by the mcp */
+
+ MYRI10GE_MCP_CMD_GET_SEND_RING_SIZE, /* in bytes */
+ MYRI10GE_MCP_CMD_GET_RX_RING_SIZE, /* in bytes */
+
+ /* Parameters which refer to rings stored in the host,
+ and whose size is controlled by the host. Note that
+ all must be physically contiguous and must contain
+ a power of 2 number of entries. */
+
+ MYRI10GE_MCP_CMD_SET_INTRQ_SIZE, /* in bytes */
+
+ /* command to bring ethernet interface up. Above parameters
+ (plus mtu & mac address) must have been exchanged prior
+ to issuing this command */
+ MYRI10GE_MCP_CMD_ETHERNET_UP,
+
+ /* command to bring ethernet interface down. No further sends
+ or receives may be processed until an MYRI10GE_MCP_CMD_ETHERNET_UP
+ is issued, and all interrupt queues must be flushed prior
+ to ack'ing this command */
+
+ MYRI10GE_MCP_CMD_ETHERNET_DOWN,
+
+ /* commands the driver may issue live, without resetting
+ the nic. Note that increasing the mtu "live" should
+ only be done if the driver has already supplied buffers
+ sufficiently large to handle the new mtu. Decreasing
+ the mtu live is safe */
+
+ MYRI10GE_MCP_CMD_SET_MTU,
+ MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY, /* in microseconds */
+ MYRI10GE_MCP_CMD_SET_STATS_INTERVAL, /* in microseconds */
+ MYRI10GE_MCP_CMD_SET_STATS_DMA,
+
+ MYRI10GE_MCP_ENABLE_PROMISC,
+ MYRI10GE_MCP_DISABLE_PROMISC,
+ MYRI10GE_MCP_SET_MAC_ADDRESS,
+
+ MYRI10GE_MCP_ENABLE_FLOW_CONTROL,
+ MYRI10GE_MCP_DISABLE_FLOW_CONTROL
+} myri10ge_mcp_cmd_type_t;
+
+
+typedef enum {
+ MYRI10GE_MCP_CMD_OK = 0,
+ MYRI10GE_MCP_CMD_UNKNOWN,
+ MYRI10GE_MCP_CMD_ERROR_RANGE,
+ MYRI10GE_MCP_CMD_ERROR_BUSY,
+ MYRI10GE_MCP_CMD_ERROR_EMPTY,
+ MYRI10GE_MCP_CMD_ERROR_CLOSED,
+ MYRI10GE_MCP_CMD_ERROR_HASH_ERROR,
+ MYRI10GE_MCP_CMD_ERROR_BAD_PORT,
+ MYRI10GE_MCP_CMD_ERROR_RESOURCES
+} myri10ge_mcp_cmd_status_t;
+
+typedef enum {
+ MYRI10GE_MCP_INTR_NONE = 0,
+ MYRI10GE_MCP_INTR_ETHER_SEND_DONE,
+ MYRI10GE_MCP_INTR_ETHER_RECV_SMALL,
+ MYRI10GE_MCP_INTR_ETHER_RECV_BIG,
+ MYRI10GE_MCP_INTR_LINK_CHANGE,
+ MYRI10GE_MCP_INTR_STATS_UPDATE,
+ MYRI10GE_MCP_INTR_ETHER_DOWN
+} myri10ge_mcp_intr_type_t;
+
+
+/* 32 Bytes */
+typedef struct
+{
+ uint32_t link_up;
+ uint32_t dropped_link_overflow;
+ uint32_t dropped_link_error_or_filtered;
+ uint32_t dropped_runt;
+ uint32_t dropped_overrun;
+ uint32_t dropped_no_small_buffer;
+ uint32_t dropped_no_big_buffer;
+ uint32_t dropped_interrupt_busy;
+ uint32_t rdma_tags_available;
+} mcp_stats_t;
+
+
+#endif /* _myri10ge_mcp_h */
diff --git a/sys/dev/myri10ge/eth_z8e.dat.gz.uu b/sys/dev/myri10ge/eth_z8e.dat.gz.uu
new file mode 100644
index 0000000..6f9f310
--- /dev/null
+++ b/sys/dev/myri10ge/eth_z8e.dat.gz.uu
@@ -0,0 +1,633 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+begin 644 eth_z8e.dat.gz
+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
+:H`>XA3R!"DX3\NT@B'.)5?X_S^VI\1AH`0``
+`
+end
diff --git a/sys/dev/myri10ge/ethp_z8e.dat.gz.uu b/sys/dev/myri10ge/ethp_z8e.dat.gz.uu
new file mode 100644
index 0000000..ad582ba
--- /dev/null
+++ b/sys/dev/myri10ge/ethp_z8e.dat.gz.uu
@@ -0,0 +1,639 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+begin 644 ethp_z8e.dat.gz
+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
+6`2"L\@DF&03#SO@J_P]CB=E(^'`!````
+`
+end
diff --git a/sys/dev/myri10ge/if_myri10ge.c b/sys/dev/myri10ge/if_myri10ge.c
new file mode 100644
index 0000000..96a063f
--- /dev/null
+++ b/sys/dev/myri10ge/if_myri10ge.c
@@ -0,0 +1,2489 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/linker.h>
+#include <sys/firmware.h>
+#include <sys/endian.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/memrange.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <net/bpf.h>
+
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+#include <net/zlib.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include <machine/clock.h> /* for DELAY */
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <vm/vm.h> /* for pmap_mapdev() */
+#include <vm/pmap.h>
+
+#include <dev/myri10ge/myri10ge_mcp.h>
+#include <dev/myri10ge/mcp_gen_header.h>
+#include <dev/myri10ge/if_myri10ge_var.h>
+
+/* tunable params */
+static int myri10ge_nvidia_ecrc_enable = 1;
+static int myri10ge_max_intr_slots = 128;
+static int myri10ge_intr_coal_delay = 30;
+static int myri10ge_skip_pio_read = 0;
+static int myri10ge_flow_control = 1;
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e";
+
+static int myri10ge_probe(device_t dev);
+static int myri10ge_attach(device_t dev);
+static int myri10ge_detach(device_t dev);
+static int myri10ge_shutdown(device_t dev);
+static void myri10ge_intr(void *arg);
+
+static device_method_t myri10ge_methods[] =
+{
+ /* Device interface */
+ DEVMETHOD(device_probe, myri10ge_probe),
+ DEVMETHOD(device_attach, myri10ge_attach),
+ DEVMETHOD(device_detach, myri10ge_detach),
+ DEVMETHOD(device_shutdown, myri10ge_shutdown),
+ {0, 0}
+};
+
+static driver_t myri10ge_driver =
+{
+ "myri10ge",
+ myri10ge_methods,
+ sizeof(myri10ge_softc_t),
+};
+
+static devclass_t myri10ge_devclass;
+
+/* Declare ourselves to be a child of the PCI bus.*/
+DRIVER_MODULE(myri10ge, pci, myri10ge_driver, myri10ge_devclass, 0, 0);
+MODULE_DEPEND(myri10ge, firmware, 1, 1, 1);
+
+static int
+myri10ge_probe(device_t dev)
+{
+ if ((pci_get_vendor(dev) == MYRI10GE_PCI_VENDOR_MYRICOM) &&
+ (pci_get_device(dev) == MYRI10GE_PCI_DEVICE_Z8E)) {
+ device_set_desc(dev, "Myri10G-PCIE-8A");
+ return 0;
+ }
+ return ENXIO;
+}
+
+static void
+myri10ge_enable_wc(myri10ge_softc_t *sc)
+{
+ struct mem_range_desc mrdesc;
+ vm_paddr_t pa;
+ vm_offset_t len;
+ int err, action;
+
+ pa = rman_get_start(sc->mem_res);
+ len = rman_get_size(sc->mem_res);
+ mrdesc.mr_base = pa;
+ mrdesc.mr_len = len;
+ mrdesc.mr_flags = MDF_WRITECOMBINE;
+ action = MEMRANGE_SET_UPDATE;
+ strcpy((char *)&mrdesc.mr_owner, "myri10ge");
+ err = mem_range_attr_set(&mrdesc, &action);
+ if (err != 0) {
+ device_printf(sc->dev,
+ "w/c failed for pa 0x%lx, len 0x%lx, err = %d\n",
+ (unsigned long)pa, (unsigned long)len, err);
+ } else {
+ sc->wc = 1;
+ }
+}
+
+
+/* callback to get our DMA address */
+static void
+myri10ge_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error)
+{
+ if (error == 0) {
+ *(bus_addr_t *) arg = segs->ds_addr;
+ }
+}
+
+static int
+myri10ge_dma_alloc(myri10ge_softc_t *sc, myri10ge_dma_t *dma, size_t bytes,
+ bus_size_t alignment)
+{
+ int err;
+ device_t dev = sc->dev;
+
+ /* allocate DMAable memory tags */
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ alignment, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ bytes, /* maxsize */
+ 1, /* num segs */
+ 4096, /* maxsegsize */
+ BUS_DMA_COHERENT, /* flags */
+ NULL, NULL, /* lock */
+ &dma->dmat); /* tag */
+ if (err != 0) {
+ device_printf(dev, "couldn't alloc tag (err = %d)\n", err);
+ return err;
+ }
+
+ /* allocate DMAable memory & map */
+ err = bus_dmamem_alloc(dma->dmat, &dma->addr,
+ (BUS_DMA_WAITOK | BUS_DMA_COHERENT
+ | BUS_DMA_ZERO), &dma->map);
+ if (err != 0) {
+ device_printf(dev, "couldn't alloc mem (err = %d)\n", err);
+ goto abort_with_dmat;
+ }
+
+ /* load the memory */
+ err = bus_dmamap_load(dma->dmat, dma->map, dma->addr, bytes,
+ myri10ge_dmamap_callback,
+ (void *)&dma->bus_addr, 0);
+ if (err != 0) {
+ device_printf(dev, "couldn't load map (err = %d)\n", err);
+ goto abort_with_mem;
+ }
+ return 0;
+
+abort_with_mem:
+ bus_dmamem_free(dma->dmat, dma->addr, dma->map);
+abort_with_dmat:
+ (void)bus_dma_tag_destroy(dma->dmat);
+ return err;
+}
+
+
+static void
+myri10ge_dma_free(myri10ge_dma_t *dma)
+{
+ bus_dmamap_unload(dma->dmat, dma->map);
+ bus_dmamem_free(dma->dmat, dma->addr, dma->map);
+ (void)bus_dma_tag_destroy(dma->dmat);
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PC=text\0
+ */
+
+static int
+myri10ge_parse_strings(myri10ge_softc_t *sc)
+{
+#define MYRI10GE_NEXT_STRING(p) while(ptr < limit && *ptr++)
+
+ char *ptr, *limit;
+ int i, found_mac;
+
+ ptr = sc->eeprom_strings;
+ limit = sc->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+ found_mac = 0;
+ while (ptr < limit && *ptr != '\0') {
+ if (memcmp(ptr, "MAC=", 4) == 0) {
+ ptr+=4;
+ sc->mac_addr_string = ptr;
+ for (i = 0; i < 6; i++) {
+ if ((ptr + 2) > limit)
+ goto abort;
+ sc->mac_addr[i] = strtoul(ptr, NULL, 16);
+ found_mac = 1;
+ ptr += 3;
+ }
+ } else if (memcmp(ptr, "PC=", 4) == 0) {
+ sc->product_code_string = ptr;
+ }
+ MYRI10GE_NEXT_STRING(ptr);
+ }
+
+ if (found_mac)
+ return 0;
+
+ abort:
+ device_printf(sc->dev, "failed to parse eeprom_strings\n");
+
+ return ENXIO;
+}
+
+#if #cpu(i386) || defined __i386 || defined i386 || defined __i386__ || #cpu(x86_64) || defined __x86_64__
+static int
+myri10ge_enable_nvidia_ecrc(myri10ge_softc_t *sc, device_t pdev)
+{
+ uint32_t val;
+ unsigned long off;
+ char *va, *cfgptr;
+ uint16_t vendor_id, device_id;
+ uintptr_t bus, slot, func, ivend, idev;
+ uint32_t *ptr32;
+
+ /* XXXX
+ Test below is commented because it is believed that doing
+ config read/write beyond 0xff will access the config space
+ for the next larger function. Uncomment this and remove
+ the hacky pmap_mapdev() way of accessing config space when
+ FreeBSD grows support for extended pcie config space access
+ */
+#if 0
+ /* See if we can, by some miracle, access the extended
+ config space */
+ val = pci_read_config(pdev, 0x178, 4);
+ if (val != 0xffffffff) {
+ val |= 0x40;
+ pci_write_config(pdev, 0x178, val, 4);
+ return 0;
+ }
+#endif
+ /* Rather than using normal pci config space writes, we must
+ * map the Nvidia config space ourselves. This is because on
+ * opteron/nvidia class machine the 0xe000000 mapping is
+ * handled by the nvidia chipset, that means the internal PCI
+ * device (the on-chip northbridge), or the amd-8131 bridge
+ * and things behind them are not visible by this method.
+ */
+
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_BUS, &bus);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_SLOT, &slot);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_FUNCTION, &func);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_VENDOR, &ivend);
+ BUS_READ_IVAR(device_get_parent(pdev), pdev,
+ PCI_IVAR_DEVICE, &idev);
+
+ off = 0xe0000000UL
+ + 0x00100000UL * (unsigned long)bus
+ + 0x00001000UL * (unsigned long)(func
+ + 8 * slot);
+
+ /* map it into the kernel */
+ va = pmap_mapdev(trunc_page((vm_paddr_t)off), PAGE_SIZE);
+
+
+ if (va == NULL) {
+ device_printf(sc->dev, "pmap_kenter_temporary didn't\n");
+ return EIO;
+ }
+ /* get a pointer to the config space mapped into the kernel */
+ cfgptr = va + (off & PAGE_MASK);
+
+ /* make sure that we can really access it */
+ vendor_id = *(uint16_t *)(cfgptr + PCIR_VENDOR);
+ device_id = *(uint16_t *)(cfgptr + PCIR_DEVICE);
+ if (! (vendor_id == ivend && device_id == idev)) {
+ device_printf(sc->dev, "mapping failed: 0x%x:0x%x\n",
+ vendor_id, device_id);
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ return EIO;
+ }
+
+ ptr32 = (uint32_t*)(cfgptr + 0x178);
+ val = *ptr32;
+
+ if (val == 0xffffffff) {
+ device_printf(sc->dev, "extended mapping failed\n");
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ return EIO;
+ }
+ *ptr32 = val | 0x40;
+ pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
+ device_printf(sc->dev,
+ "Enabled ECRC on upstream Nvidia bridge at %d:%d:%d\n",
+ (int)bus, (int)slot, (int)func);
+ return 0;
+}
+#else
+static int
+myri10ge_enable_nvidia_ecrc(myri10ge_softc_t *sc, device_t pdev)
+{
+ device_printf(sc->dev,
+ "Nforce 4 chipset on non-x86/amd64!?!?!\n");
+ return ENXIO;
+}
+#endif
+/*
+ * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
+ * when the PCI-E Completion packets are aligned on an 8-byte
+ * boundary. Some PCI-E chip sets always align Completion packets; on
+ * the ones that do not, the alignment can be enforced by enabling
+ * ECRC generation (if supported).
+ *
+ * When PCI-E Completion packets are not aligned, it is actually more
+ * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
+ *
+ * If the driver can neither enable ECRC nor verify that it has
+ * already been enabled, then it must use a firmware image which works
+ * around unaligned completion packets (ethp_z8e.dat), and it should
+ * also ensure that it never gives the device a Read-DMA which is
+ * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is
+ * enabled, then the driver should use the aligned (eth_z8e.dat)
+ * firmware image, and set tx.boundary to 4KB.
+ */
+
+static void
+myri10ge_select_firmware(myri10ge_softc_t *sc)
+{
+ int err, aligned = 0;
+ device_t pdev;
+ uint16_t pvend, pdid;
+
+ pdev = device_get_parent(device_get_parent(sc->dev));
+ if (pdev == NULL) {
+ device_printf(sc->dev, "could not find parent?\n");
+ goto abort;
+ }
+ pvend = pci_read_config(pdev, PCIR_VENDOR, 2);
+ pdid = pci_read_config(pdev, PCIR_DEVICE, 2);
+
+ /* see if we can enable ECRC's on an upstream
+ Nvidia bridge */
+ if (myri10ge_nvidia_ecrc_enable &&
+ (pvend == 0x10de && pdid == 0x005d)) {
+ err = myri10ge_enable_nvidia_ecrc(sc, pdev);
+ if (err == 0) {
+ aligned = 1;
+ device_printf(sc->dev,
+ "Assuming aligned completions (ECRC)\n");
+ }
+ }
+ /* see if the upstream bridge is known to
+ provided aligned completions */
+ if (/* HT2000 */ (pvend == 0x1166 && pdid == 0x0132) ||
+ /* Ontario */ (pvend == 0x10b5 && pdid == 0x8532)) {
+ device_printf(sc->dev,
+ "Assuming aligned completions (0x%x:0x%x)\n",
+ pvend, pdid);
+ }
+
+abort:
+ if (aligned) {
+ sc->fw_name = myri10ge_fw_aligned;
+ sc->tx.boundary = 4096;
+ } else {
+ sc->fw_name = myri10ge_fw_unaligned;
+ sc->tx.boundary = 2048;
+ }
+}
+
+union qualhack
+{
+ const char *ro_char;
+ char *rw_char;
+};
+
+
+static int
+myri10ge_load_firmware_helper(myri10ge_softc_t *sc, uint32_t *limit)
+{
+ struct firmware *fw;
+ const mcp_gen_header_t *hdr;
+ unsigned hdr_offset;
+ const char *fw_data;
+ union qualhack hack;
+ int status;
+
+
+ fw = firmware_get(sc->fw_name);
+
+ if (fw == NULL) {
+ device_printf(sc->dev, "Could not find firmware image %s\n",
+ sc->fw_name);
+ return ENOENT;
+ }
+ if (fw->datasize > *limit ||
+ fw->datasize < MCP_HEADER_PTR_OFFSET + 4) {
+ device_printf(sc->dev, "Firmware image %s too large (%d/%d)\n",
+ sc->fw_name, (int)fw->datasize, (int) *limit);
+ status = ENOSPC;
+ goto abort_with_fw;
+ }
+ *limit = fw->datasize;
+
+ /* check id */
+ fw_data = (const char *)fw->data;
+ hdr_offset = htobe32(*(const uint32_t *)
+ (fw_data + MCP_HEADER_PTR_OFFSET));
+ if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->datasize) {
+ device_printf(sc->dev, "Bad firmware file");
+ status = EIO;
+ goto abort_with_fw;
+ }
+ hdr = (const void*)(fw_data + hdr_offset);
+ if (be32toh(hdr->mcp_type) != MCP_TYPE_ETH) {
+ device_printf(sc->dev, "Bad firmware type: 0x%x\n",
+ be32toh(hdr->mcp_type));
+ status = EIO;
+ goto abort_with_fw;
+ }
+
+ /* save firmware version for sysctl */
+ strncpy(sc->fw_version, hdr->version, sizeof (sc->fw_version));
+ device_printf(sc->dev, "firmware id: %s\n", hdr->version);
+
+ hack.ro_char = fw_data;
+ /* Copy the inflated firmware to NIC SRAM. */
+ myri10ge_pio_copy(&sc->sram[MYRI10GE_FW_OFFSET],
+ hack.rw_char, *limit);
+
+ status = 0;
+abort_with_fw:
+ firmware_put(fw, FIRMWARE_UNLOAD);
+ return status;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void
+myri10ge_dummy_rdma(myri10ge_softc_t *sc, int enable)
+{
+ char buf_bytes[72];
+ volatile uint32_t *confirm;
+ volatile char *submit;
+ uint32_t *buf, dma_low, dma_high;
+ int i;
+
+ buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ /* clear confirmation addr */
+ confirm = (volatile uint32_t *)sc->cmd;
+ *confirm = 0;
+ mb();
+
+ /* send an rdma command to the PCIe engine, and wait for the
+ response in the confirmation address. The firmware should
+ write a -1 there to indicate it is alive and well
+ */
+
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+ buf[0] = htobe32(dma_high); /* confirm addr MSW */
+ buf[1] = htobe32(dma_low); /* confirm addr LSW */
+ buf[2] = htobe32(0xffffffff); /* confirm data */
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->zeropad_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->zeropad_dma.bus_addr);
+ buf[3] = htobe32(dma_high); /* dummy addr MSW */
+ buf[4] = htobe32(dma_low); /* dummy addr LSW */
+ buf[5] = htobe32(enable); /* enable? */
+
+
+ submit = (volatile char *)(sc->sram + 0xfc01c0);
+
+ myri10ge_pio_copy(submit, buf, 64);
+ mb();
+ DELAY(1000);
+ mb();
+ i = 0;
+ while (*confirm != 0xffffffff && i < 20) {
+ DELAY(1000);
+ i++;
+ }
+ if (*confirm != 0xffffffff) {
+ device_printf(sc->dev, "dummy rdma %s failed (%p = 0x%x)",
+ (enable ? "enable" : "disable"), confirm,
+ *confirm);
+ }
+ return;
+}
+
+static int
+myri10ge_send_cmd(myri10ge_softc_t *sc, uint32_t cmd,
+ myri10ge_cmd_t *data)
+{
+ mcp_cmd_t *buf;
+ char buf_bytes[sizeof(*buf) + 8];
+ volatile mcp_cmd_response_t *response = sc->cmd;
+ volatile char *cmd_addr = sc->sram + MYRI10GE_MCP_CMD_OFFSET;
+ uint32_t dma_low, dma_high;
+ int sleep_total = 0;
+
+ /* ensure buf is aligned to 8 bytes */
+ buf = (mcp_cmd_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ buf->data0 = htobe32(data->data0);
+ buf->data1 = htobe32(data->data1);
+ buf->data2 = htobe32(data->data2);
+ buf->cmd = htobe32(cmd);
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+
+ buf->response_addr.low = htobe32(dma_low);
+ buf->response_addr.high = htobe32(dma_high);
+ mtx_lock(&sc->cmd_lock);
+ response->result = 0xffffffff;
+ mb();
+ myri10ge_pio_copy((volatile void *)cmd_addr, buf, sizeof (*buf));
+
+ /* wait up to 2 seconds */
+ for (sleep_total = 0; sleep_total < (2 * 1000); sleep_total += 10) {
+ bus_dmamap_sync(sc->cmd_dma.dmat,
+ sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
+ mb();
+ if (response->result != 0xffffffff) {
+ if (response->result == 0) {
+ data->data0 = be32toh(response->data);
+ mtx_unlock(&sc->cmd_lock);
+ return 0;
+ } else {
+ device_printf(sc->dev,
+ "myri10ge: command %d "
+ "failed, result = %d\n",
+ cmd, be32toh(response->result));
+ mtx_unlock(&sc->cmd_lock);
+ return ENXIO;
+ }
+ }
+ DELAY(1000 * 10);
+ }
+ mtx_unlock(&sc->cmd_lock);
+ device_printf(sc->dev, "myri10ge: command %d timed out"
+ "result = %d\n",
+ cmd, be32toh(response->result));
+ return EAGAIN;
+}
+
+
+static int
+myri10ge_load_firmware(myri10ge_softc_t *sc)
+{
+ volatile uint32_t *confirm;
+ volatile char *submit;
+ char buf_bytes[72];
+ uint32_t *buf, size, dma_low, dma_high;
+ int status, i;
+
+ buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL);
+
+ size = sc->sram_size;
+ status = myri10ge_load_firmware_helper(sc, &size);
+ if (status) {
+ device_printf(sc->dev, "firmware loading failed\n");
+ return status;
+ }
+ /* clear confirmation addr */
+ confirm = (volatile uint32_t *)sc->cmd;
+ *confirm = 0;
+ mb();
+ /* send a reload command to the bootstrap MCP, and wait for the
+ response in the confirmation address. The firmware should
+ write a -1 there to indicate it is alive and well
+ */
+
+ dma_low = MYRI10GE_LOWPART_TO_U32(sc->cmd_dma.bus_addr);
+ dma_high = MYRI10GE_HIGHPART_TO_U32(sc->cmd_dma.bus_addr);
+
+ buf[0] = htobe32(dma_high); /* confirm addr MSW */
+ buf[1] = htobe32(dma_low); /* confirm addr LSW */
+ buf[2] = htobe32(0xffffffff); /* confirm data */
+
+ /* FIX: All newest firmware should un-protect the bottom of
+ the sram before handoff. However, the very first interfaces
+ do not. Therefore the handoff copy must skip the first 8 bytes
+ */
+ /* where the code starts*/
+ buf[3] = htobe32(MYRI10GE_FW_OFFSET + 8);
+ buf[4] = htobe32(size - 8); /* length of code */
+ buf[5] = htobe32(8); /* where to copy to */
+ buf[6] = htobe32(0); /* where to jump to */
+
+ submit = (volatile char *)(sc->sram + 0xfc0000);
+ myri10ge_pio_copy(submit, buf, 64);
+ mb();
+ DELAY(1000);
+ mb();
+ i = 0;
+ while (*confirm != 0xffffffff && i < 20) {
+ DELAY(1000*10);
+ i++;
+ bus_dmamap_sync(sc->cmd_dma.dmat,
+ sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
+ }
+ if (*confirm != 0xffffffff) {
+ device_printf(sc->dev,"handoff failed (%p = 0x%x)",
+ confirm, *confirm);
+
+ return ENXIO;
+ }
+ myri10ge_dummy_rdma(sc, 1);
+ return 0;
+}
+
+static int
+myri10ge_update_mac_address(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ uint8_t *addr = sc->mac_addr;
+ int status;
+
+
+ cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+ | (addr[2] << 8) | addr[3]);
+
+ cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_SET_MAC_ADDRESS, &cmd);
+ return status;
+}
+
+static int
+myri10ge_change_pause(myri10ge_softc_t *sc, int pause)
+{
+ myri10ge_cmd_t cmd;
+ int status;
+
+ if (pause)
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_ENABLE_FLOW_CONTROL,
+ &cmd);
+ else
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_DISABLE_FLOW_CONTROL,
+ &cmd);
+
+ if (status) {
+ device_printf(sc->dev, "Failed to set flow control mode\n");
+ return ENXIO;
+ }
+ sc->pause = pause;
+ return 0;
+}
+
+static void
+myri10ge_change_promisc(myri10ge_softc_t *sc, int promisc)
+{
+ myri10ge_cmd_t cmd;
+ int status;
+
+ if (promisc)
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_ENABLE_PROMISC,
+ &cmd);
+ else
+ status = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_DISABLE_PROMISC,
+ &cmd);
+
+ if (status) {
+ device_printf(sc->dev, "Failed to set promisc mode\n");
+ }
+}
+
+static int
+myri10ge_reset(myri10ge_softc_t *sc)
+{
+
+ myri10ge_cmd_t cmd;
+ int status, i;
+
+ /* try to send a reset command to the card to see if it
+ is alive */
+ memset(&cmd, 0, sizeof (cmd));
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_RESET, &cmd);
+ if (status != 0) {
+ device_printf(sc->dev, "failed reset\n");
+ return ENXIO;
+ }
+
+ /* Now exchange information about interrupts */
+
+ cmd.data0 = (uint32_t)
+ (myri10ge_max_intr_slots * sizeof (*sc->intr.q[0]));
+ status = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_INTRQ_SIZE, &cmd);
+ for (i = 0; (status == 0) && (i < MYRI10GE_NUM_INTRQS); i++) {
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(sc->intr.dma[i].bus_addr);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(sc->intr.dma[i].bus_addr);
+ status |=
+ myri10ge_send_cmd(sc, (i +
+ MYRI10GE_MCP_CMD_SET_INTRQ0_DMA),
+ &cmd);
+ }
+
+ cmd.data0 = sc->intr_coal_delay = myri10ge_intr_coal_delay;
+ status |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY, &cmd);
+
+ if (sc->msi_enabled) {
+ status |= myri10ge_send_cmd
+ (sc, MYRI10GE_MCP_CMD_GET_IRQ_ACK_OFFSET, &cmd);
+ } else {
+ status |= myri10ge_send_cmd
+ (sc, MYRI10GE_MCP_CMD_GET_IRQ_ACK_DEASSERT_OFFSET,
+ &cmd);
+ }
+ if (status != 0) {
+ device_printf(sc->dev, "failed set interrupt parameters\n");
+ return status;
+ }
+ sc->irq_claim = (volatile uint32_t *)(sc->sram + cmd.data0);
+
+ /* reset mcp/driver shared state back to 0 */
+ sc->intr.seqnum = 0;
+ sc->intr.intrq = 0;
+ sc->intr.slot = 0;
+ sc->tx.req = 0;
+ sc->tx.done = 0;
+ sc->rx_big.cnt = 0;
+ sc->rx_small.cnt = 0;
+ sc->rdma_tags_available = 15;
+ status = myri10ge_update_mac_address(sc);
+ myri10ge_change_promisc(sc, 0);
+ myri10ge_change_pause(sc, sc->pause);
+ return status;
+}
+
+static int
+myri10ge_change_intr_coal(SYSCTL_HANDLER_ARGS)
+{
+ myri10ge_cmd_t cmd;
+ myri10ge_softc_t *sc;
+ unsigned int intr_coal_delay;
+ int err;
+
+ sc = arg1;
+ intr_coal_delay = sc->intr_coal_delay;
+ err = sysctl_handle_int(oidp, &intr_coal_delay, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (intr_coal_delay == sc->intr_coal_delay)
+ return 0;
+
+ if (intr_coal_delay == 0 || intr_coal_delay > 1000*1000)
+ return EINVAL;
+
+ sx_xlock(&sc->driver_lock);
+ cmd.data0 = intr_coal_delay;
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY,
+ &cmd);
+ if (err == 0) {
+ sc->intr_coal_delay = intr_coal_delay;
+ }
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static int
+myri10ge_change_flow_control(SYSCTL_HANDLER_ARGS)
+{
+ myri10ge_softc_t *sc;
+ unsigned int enabled;
+ int err;
+
+ sc = arg1;
+ enabled = sc->pause;
+ err = sysctl_handle_int(oidp, &enabled, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (enabled == sc->pause)
+ return 0;
+
+ sx_xlock(&sc->driver_lock);
+ err = myri10ge_change_pause(sc, enabled);
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static int
+myri10ge_handle_be32(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+
+ if (arg1 == NULL)
+ return EFAULT;
+ arg2 = be32toh(*(int *)arg1);
+ arg1 = NULL;
+ err = sysctl_handle_int(oidp, arg1, arg2, req);
+
+ return err;
+}
+
+static void
+myri10ge_add_sysctls(myri10ge_softc_t *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *children;
+ mcp_stats_t *fw;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+ fw = sc->fw_stats;
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "intr_coal_delay",
+ CTLTYPE_INT|CTLFLAG_RW, sc,
+ 0, myri10ge_change_intr_coal,
+ "I", "interrupt coalescing delay in usecs");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "flow_control_enabled",
+ CTLTYPE_INT|CTLFLAG_RW, sc,
+ 0, myri10ge_change_flow_control,
+ "I", "interrupt coalescing delay in usecs");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "skip_pio_read",
+ CTLFLAG_RW, &myri10ge_skip_pio_read,
+ 0, "Skip pio read in interrupt handler");
+
+ /* stats block from firmware is in network byte order.
+ Need to swap it */
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "link_up",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->link_up,
+ 0, myri10ge_handle_be32,
+ "I", "link up");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "rdma_tags_available",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->rdma_tags_available,
+ 0, myri10ge_handle_be32,
+ "I", "rdma_tags_available");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_link_overflow",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_link_overflow,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_link_overflow");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_link_error_or_filtered",
+ CTLTYPE_INT|CTLFLAG_RD,
+ &fw->dropped_link_error_or_filtered,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_link_error_or_filtered");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_runt",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_runt,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_runt");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_overrun",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_overrun,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_overrun");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_no_small_buffer",
+ CTLTYPE_INT|CTLFLAG_RD,
+ &fw->dropped_no_small_buffer,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_no_small_buffer");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_no_big_buffer",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_no_big_buffer,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_no_big_buffer");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "dropped_interrupt_busy",
+ CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_interrupt_busy,
+ 0, myri10ge_handle_be32,
+ "I", "dropped_interrupt_busy");
+
+ /* host counters exported for debugging */
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tx_req",
+ CTLFLAG_RD, &sc->tx.req,
+ 0, "tx_req");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tx_done",
+ CTLFLAG_RD, &sc->tx.done,
+ 0, "tx_done");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "rx_small_cnt",
+ CTLFLAG_RD, &sc->rx_small.cnt,
+ 0, "rx_small_cnt");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "rx_big_cnt",
+ CTLFLAG_RD, &sc->rx_big.cnt,
+ 0, "rx_small_cnt");
+
+}
+
+/* copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
+ backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(myri10ge_tx_buf_t *tx,
+ mcp_kreq_ether_send_t *src, int cnt)
+{
+ int idx, starting_slot;
+ starting_slot = tx->req;
+ while (cnt > 1) {
+ cnt--;
+ idx = (starting_slot + cnt) & tx->mask;
+ myri10ge_pio_copy(&tx->lanai[idx],
+ &src[cnt], sizeof(*src));
+ mb();
+ }
+}
+
+/*
+ * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic. We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain
+ */
+
+static inline void
+myri10ge_submit_req(myri10ge_tx_buf_t *tx, mcp_kreq_ether_send_t *src,
+ int cnt)
+{
+ int idx, i;
+ uint32_t *src_ints;
+ volatile uint32_t *dst_ints;
+ mcp_kreq_ether_send_t *srcp;
+ volatile mcp_kreq_ether_send_t *dstp, *dst;
+
+
+ idx = tx->req & tx->mask;
+
+ src->flags &= ~(htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID));
+ mb();
+ dst = dstp = &tx->lanai[idx];
+ srcp = src;
+
+ if ((idx + cnt) < tx->mask) {
+ for (i = 0; i < (cnt - 1); i += 2) {
+ myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+ mb(); /* force write every 32 bytes */
+ srcp += 2;
+ dstp += 2;
+ }
+ } else {
+ /* submit all but the first request, and ensure
+ that it is submitted below */
+ myri10ge_submit_req_backwards(tx, src, cnt);
+ i = 0;
+ }
+ if (i < cnt) {
+ /* submit the first request */
+ myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+ mb(); /* barrier before setting valid flag */
+ }
+
+ /* re-write the last 32-bits with the valid flags */
+ src->flags |= htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID);
+ src_ints = (uint32_t *)src;
+ src_ints+=3;
+ dst_ints = (volatile uint32_t *)dst;
+ dst_ints+=3;
+ *dst_ints = *src_ints;
+ tx->req += cnt;
+ mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(myri10ge_tx_buf_t *tx,
+ mcp_kreq_ether_send_t *src, int cnt)
+{
+ tx->req += cnt;
+ mb();
+ while (cnt >= 4) {
+ myri10ge_pio_copy((volatile char *)tx->wc_fifo, src, 64);
+ mb();
+ src += 4;
+ cnt -= 4;
+ }
+ if (cnt > 0) {
+ /* pad it to 64 bytes. The src is 64 bytes bigger than it
+ needs to be so that we don't overrun it */
+ myri10ge_pio_copy(tx->wc_fifo + (cnt<<18), src, 64);
+ mb();
+ }
+}
+
+static void
+myri10ge_encap(myri10ge_softc_t *sc, struct mbuf *m)
+{
+ mcp_kreq_ether_send_t *req;
+ bus_dma_segment_t seg_list[MYRI10GE_MCP_ETHER_MAX_SEND_DESC];
+ bus_dma_segment_t *seg;
+ struct mbuf *m_tmp;
+ struct ifnet *ifp;
+ myri10ge_tx_buf_t *tx;
+ struct ether_header *eh;
+ struct ip *ip;
+ int cnt, cum_len, err, i, idx;
+ uint16_t flags, pseudo_hdr_offset;
+ uint8_t cksum_offset;
+
+
+
+ ifp = sc->ifp;
+ tx = &sc->tx;
+
+ /* (try to) map the frame for DMA */
+ idx = tx->req & tx->mask;
+ err = bus_dmamap_load_mbuf_sg(tx->dmat, tx->info[idx].map,
+ m, seg_list, &cnt,
+ BUS_DMA_NOWAIT);
+ if (err == EFBIG) {
+ /* Too many segments in the chain. Try
+ to defrag */
+ m_tmp = m_defrag(m, M_NOWAIT);
+ if (m_tmp == NULL) {
+ goto drop;
+ }
+ m = m_tmp;
+ err = bus_dmamap_load_mbuf_sg(tx->dmat,
+ tx->info[idx].map,
+ m, seg_list, &cnt,
+ BUS_DMA_NOWAIT);
+ }
+ if (err != 0) {
+ device_printf(sc->dev, "bus_dmamap_load_mbuf_sg returned %d\n",
+ err);
+ goto drop;
+ }
+ bus_dmamap_sync(tx->dmat, tx->info[idx].map,
+ BUS_DMASYNC_PREWRITE);
+
+ req = tx->req_list;
+ cksum_offset = 0;
+ flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_VALID |
+ MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST);
+
+ /* checksum offloading? */
+ if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) {
+ eh = mtod(m, struct ether_header *);
+ ip = (struct ip *) (eh + 1);
+ cksum_offset = sizeof(*eh) + (ip->ip_hl << 2);
+ pseudo_hdr_offset = cksum_offset + m->m_pkthdr.csum_data;
+ req->pseudo_hdr_offset = htobe16(pseudo_hdr_offset);
+ req->cksum_offset = cksum_offset;
+ flags |= htobe16(MYRI10GE_MCP_ETHER_FLAGS_CKSUM);
+ }
+ if (m->m_pkthdr.len < 512)
+ req->flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_FIRST |
+ MYRI10GE_MCP_ETHER_FLAGS_SMALL);
+ else
+ req->flags = htobe16(MYRI10GE_MCP_ETHER_FLAGS_FIRST);
+
+ /* convert segments into a request list */
+ cum_len = 0;
+ seg = seg_list;
+ for (i = 0; i < cnt; i++) {
+ req->addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg->ds_addr));
+ req->addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg->ds_addr));
+ req->length = htobe16(seg->ds_len);
+ req->cksum_offset = cksum_offset;
+ if (cksum_offset > seg->ds_len)
+ cksum_offset -= seg->ds_len;
+ else
+ cksum_offset = 0;
+ req->flags |= flags | ((cum_len & 1) *
+ htobe16(MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD));
+ cum_len += seg->ds_len;
+ seg++;
+ req++;
+ req->flags = 0;
+ }
+ req--;
+ /* pad runts to 60 bytes */
+ if (cum_len < 60) {
+ req++;
+ req->addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(sc->zeropad_dma.bus_addr));
+ req->addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(sc->zeropad_dma.bus_addr));
+ req->length = htobe16(60 - cum_len);
+ req->cksum_offset = cksum_offset;
+ req->flags |= flags | ((cum_len & 1) *
+ htobe16(MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD));
+ cnt++;
+ }
+ req->flags &= ~(htobe16(MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST));
+ tx->info[idx].m = m;
+ if (tx->wc_fifo == NULL)
+ myri10ge_submit_req(tx, tx->req_list, cnt);
+ else
+ myri10ge_submit_req_wc(tx, tx->req_list, cnt);
+ return;
+
+drop:
+ m_freem(m);
+ ifp->if_oerrors++;
+ return;
+}
+
+
+static void
+myri10ge_start_locked(myri10ge_softc_t *sc)
+{
+ int avail;
+ struct mbuf *m;
+ struct ifnet *ifp;
+
+
+ ifp = sc->ifp;
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ /* dequeue the packet */
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+
+ /* let BPF see it */
+ BPF_MTAP(ifp, m);
+
+ /* give it to the nic */
+ myri10ge_encap(sc, m);
+
+ /* leave an extra slot keep the ring from wrapping */
+ avail = sc->tx.mask - (sc->tx.req - sc->tx.done);
+ if (avail < MYRI10GE_MCP_ETHER_MAX_SEND_DESC) {
+ sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ }
+ }
+}
+
+static void
+myri10ge_start(struct ifnet *ifp)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+
+
+ mtx_lock(&sc->tx_lock);
+ myri10ge_start_locked(sc);
+ mtx_unlock(&sc->tx_lock);
+}
+
+static int
+myri10ge_get_buf_small(myri10ge_softc_t *sc, bus_dmamap_t map, int idx)
+{
+ bus_dma_segment_t seg;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx = &sc->rx_small;
+ int cnt, err;
+
+ m = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ rx->alloc_fail++;
+ err = ENOBUFS;
+ goto done;
+ }
+ m->m_len = MHLEN;
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ &seg, &cnt, BUS_DMA_NOWAIT);
+ if (err != 0) {
+ m_free(m);
+ goto done;
+ }
+ rx->info[idx].m = m;
+ rx->shadow[idx].addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg.ds_addr));
+ rx->shadow[idx].addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg.ds_addr));
+
+done:
+ if ((idx & 7) == 7) {
+ myri10ge_pio_copy(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7],
+ 8 * sizeof (*rx->lanai));
+ mb();
+ }
+ return err;
+}
+
+static int
+myri10ge_get_buf_big(myri10ge_softc_t *sc, bus_dmamap_t map, int idx)
+{
+ bus_dma_segment_t seg;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx = &sc->rx_big;
+ int cnt, err;
+
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, sc->big_bytes);
+ if (m == NULL) {
+ rx->alloc_fail++;
+ err = ENOBUFS;
+ goto done;
+ }
+ m->m_len = sc->big_bytes;
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ &seg, &cnt, BUS_DMA_NOWAIT);
+ if (err != 0) {
+ m_free(m);
+ goto done;
+ }
+ rx->info[idx].m = m;
+ rx->shadow[idx].addr_low =
+ htobe32(MYRI10GE_LOWPART_TO_U32(seg.ds_addr));
+ rx->shadow[idx].addr_high =
+ htobe32(MYRI10GE_HIGHPART_TO_U32(seg.ds_addr));
+
+done:
+ if ((idx & 7) == 7) {
+ myri10ge_pio_copy(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7],
+ 8 * sizeof (*rx->lanai));
+ mb();
+ }
+ return err;
+}
+
+static inline void
+myri10ge_rx_done_big(myri10ge_softc_t *sc, int len, int csum, int flags)
+{
+ struct ifnet *ifp;
+ struct mbuf *m = 0; /* -Wunitialized */
+ struct mbuf *m_prev = 0; /* -Wunitialized */
+ struct mbuf *m_head = 0;
+ bus_dmamap_t old_map;
+ myri10ge_rx_buf_t *rx;
+ int idx;
+
+
+ rx = &sc->rx_big;
+ ifp = sc->ifp;
+ while (len > 0) {
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ /* save a pointer to the received mbuf */
+ m = rx->info[idx].m;
+ /* try to replace the received mbuf */
+ if (myri10ge_get_buf_big(sc, rx->extra_map, idx)) {
+ goto drop;
+ }
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+
+ /* chain multiple segments together */
+ if (!m_head) {
+ m_head = m;
+ /* mcp implicitly skips 1st bytes so that
+ * packet is properly aligned */
+ m->m_data += MYRI10GE_MCP_ETHER_PAD;
+ m->m_pkthdr.len = len;
+ m->m_len = sc->big_bytes - MYRI10GE_MCP_ETHER_PAD;
+ } else {
+ m->m_len = sc->big_bytes;
+ m->m_flags &= ~M_PKTHDR;
+ m_prev->m_next = m;
+ }
+ len -= m->m_len;
+ m_prev = m;
+ }
+
+ /* trim trailing garbage from the last mbuf in the chain. If
+ * there is any garbage, len will be negative */
+ m->m_len += len;
+
+ /* if the checksum is valid, mark it in the mbuf header */
+ if (sc->csum_flag & flags) {
+ m_head->m_pkthdr.csum_data = csum;
+ m_head->m_pkthdr.csum_flags = CSUM_DATA_VALID;
+ }
+
+ /* pass the frame up the stack */
+ m_head->m_pkthdr.rcvif = ifp;
+ ifp->if_ipackets++;
+ (*ifp->if_input)(ifp, m_head);
+ return;
+
+drop:
+ /* drop the frame -- the old mbuf(s) are re-cycled by running
+ every slot through the allocator */
+ if (m_head) {
+ len -= sc->big_bytes;
+ m_freem(m_head);
+ } else {
+ len -= (sc->big_bytes + MYRI10GE_MCP_ETHER_PAD);
+ }
+ while ((int)len > 0) {
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ m = rx->info[idx].m;
+ if (0 == (myri10ge_get_buf_big(sc, rx->extra_map, idx))) {
+ m_freem(m);
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+ }
+ len -= sc->big_bytes;
+ }
+
+ ifp->if_ierrors++;
+
+}
+
+
+static inline void
+myri10ge_rx_done_small(myri10ge_softc_t *sc, uint32_t len,
+ uint32_t csum, uint32_t flags)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ myri10ge_rx_buf_t *rx;
+ bus_dmamap_t old_map;
+ int idx;
+
+ ifp = sc->ifp;
+ rx = &sc->rx_small;
+ idx = rx->cnt & rx->mask;
+ rx->cnt++;
+ /* save a pointer to the received mbuf */
+ m = rx->info[idx].m;
+ /* try to replace the received mbuf */
+ if (myri10ge_get_buf_small(sc, rx->extra_map, idx)) {
+ /* drop the frame -- the old mbuf is re-cycled */
+ ifp->if_ierrors++;
+ return;
+ }
+
+ /* unmap the received buffer */
+ old_map = rx->info[idx].map;
+ bus_dmamap_sync(rx->dmat, old_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rx->dmat, old_map);
+
+ /* swap the bus_dmamap_t's */
+ rx->info[idx].map = rx->extra_map;
+ rx->extra_map = old_map;
+
+ /* mcp implicitly skips 1st 2 bytes so that packet is properly
+ * aligned */
+ m->m_data += MYRI10GE_MCP_ETHER_PAD;
+
+ /* if the checksum is valid, mark it in the mbuf header */
+ if (sc->csum_flag & flags) {
+ m->m_pkthdr.csum_data = csum;
+ m->m_pkthdr.csum_flags = CSUM_DATA_VALID;
+ }
+
+ /* pass the frame up the stack */
+ m->m_pkthdr.rcvif = ifp;
+ m->m_len = m->m_pkthdr.len = len;
+ ifp->if_ipackets++;
+ (*ifp->if_input)(ifp, m);
+}
+
+static inline void
+myri10ge_tx_done(myri10ge_softc_t *sc, uint32_t mcp_idx)
+{
+ struct ifnet *ifp;
+ myri10ge_tx_buf_t *tx;
+ struct mbuf *m;
+ bus_dmamap_t map;
+ int idx;
+
+ tx = &sc->tx;
+ ifp = sc->ifp;
+ while (tx->done != mcp_idx) {
+ idx = tx->done & tx->mask;
+ tx->done++;
+ m = tx->info[idx].m;
+ /* mbuf and DMA map only attached to the first
+ segment per-mbuf */
+ if (m != NULL) {
+ ifp->if_opackets++;
+ tx->info[idx].m = NULL;
+ map = tx->info[idx].map;
+ bus_dmamap_unload(tx->dmat, map);
+ m_freem(m);
+ }
+ }
+
+ /* If we have space, clear IFF_OACTIVE to tell the stack that
+ its OK to send packets */
+
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE &&
+ tx->req - tx->done < (tx->mask + 1)/4) {
+ mtx_lock(&sc->tx_lock);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ myri10ge_start_locked(sc);
+ mtx_unlock(&sc->tx_lock);
+ }
+}
+
+static void
+myri10ge_dump_interrupt_queues(myri10ge_softc_t *sc, int maxslot)
+{
+ int intrq, slot, type;
+ static int call_cnt = 0;
+
+ /* only do it a few times to avoid filling the message buffer */
+ if (call_cnt > 10)
+ return;
+
+ call_cnt++;
+
+ device_printf(sc->dev, "--------- Dumping interrupt queue state ----- \n");
+ device_printf(sc->dev, "currently expecting interrupts on queue %d\n",
+ sc->intr.intrq);
+ device_printf(sc->dev, " q slot status \n");
+ device_printf(sc->dev, "--- ---- -------- \n");
+ for (intrq = 0; intrq < 2; intrq++) {
+ for (slot = 0; slot <= maxslot; slot++) {
+ type = sc->intr.q[intrq][slot].type;
+#if 0
+ if (type == 0 && slot != 0)
+ continue;
+#endif
+ device_printf(sc->dev, "[%d]:[%d]: type = 0x%x\n", intrq, slot,
+ type);
+ device_printf(sc->dev, "[%d]:[%d]: flag = 0x%x\n", intrq, slot,
+ sc->intr.q[intrq][slot].flag);
+ device_printf(sc->dev, "[%d]:[%d]: index = 0x%x\n", intrq, slot,
+ be16toh(sc->intr.q[intrq][slot].index));
+ device_printf(sc->dev, "[%d]:[%d]: seqnum = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].seqnum));
+ device_printf(sc->dev, "[%d]:[%d]: data0 = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].data0));
+ device_printf(sc->dev, "[%d]:[%d]: data1 = 0x%x\n", intrq, slot,
+ (unsigned int)be32toh(sc->intr.q[intrq][slot].data1));
+
+ }
+ }
+
+}
+
+static inline void
+myri10ge_claim_irq(myri10ge_softc_t *sc)
+{
+ volatile uint32_t dontcare;
+
+
+ *sc->irq_claim = 0;
+ mb();
+
+ /* do a PIO read to ensure that PIO write to claim the irq has
+ hit the nic before we exit the interrupt handler */
+ if (!myri10ge_skip_pio_read) {
+ dontcare = *(volatile uint32_t *)sc->sram;
+ mb();
+ }
+}
+
+static void
+myri10ge_intr(void *arg)
+{
+ myri10ge_softc_t *sc = arg;
+ int intrq, claimed, flags, count, length, ip_csum;
+ uint32_t raw, slot;
+ uint8_t type;
+
+
+ intrq = sc->intr.intrq;
+ claimed = 0;
+ bus_dmamap_sync(sc->intr.dma[intrq].dmat,
+ sc->intr.dma[intrq].map, BUS_DMASYNC_POSTREAD);
+ if (sc->msi_enabled) {
+ /* We know we can immediately claim the interrupt */
+ myri10ge_claim_irq(sc);
+ claimed = 1;
+ } else {
+ /* Check to see if we have the last event in the queue
+ ready. If so, ack it as early as possible. This
+ allows more time to get the interrupt line
+ de-asserted prior to the EOI and reduces the chance
+ of seeing a spurious irq caused by the interrupt
+ line remaining high after EOI */
+
+ slot = be16toh(sc->intr.q[intrq][0].index) - 1;
+ if (slot < myri10ge_max_intr_slots &&
+ sc->intr.q[intrq][slot].type != 0 &&
+ sc->intr.q[intrq][slot].flag != 0) {
+ myri10ge_claim_irq(sc);
+ claimed = 1;
+ }
+ }
+
+ /* walk each slot in the current queue, processing events until
+ we reach an event with a zero type */
+ for (slot = sc->intr.slot; slot < myri10ge_max_intr_slots; slot++) {
+ type = sc->intr.q[intrq][slot].type;
+
+ /* check for partially completed DMA of events when
+ using non-MSI interrupts */
+ if (__predict_false(!claimed)) {
+ mb();
+ /* look if there is somscing in the queue */
+ if (type == 0) {
+ /* save the current slot for the next
+ * time we (re-)enter this routine */
+ if (sc->intr.slot == slot) {
+ sc->intr.spurious++;
+ }
+ sc->intr.slot = slot;
+ return;
+ }
+ }
+ if (__predict_false(htobe32(sc->intr.q[intrq][slot].seqnum) !=
+ sc->intr.seqnum++)) {
+ device_printf(sc->dev, "Bad interrupt!\n");
+ device_printf(sc->dev,
+ "bad irq seqno"
+ "(got 0x%x, expected 0x%x) \n",
+ (unsigned int)htobe32(sc->intr.q[intrq][slot].seqnum),
+ sc->intr.seqnum);
+ device_printf(sc->dev, "intrq = %d, slot = %d\n",
+ intrq, slot);
+ myri10ge_dump_interrupt_queues(sc, slot);
+ device_printf(sc->dev,
+ "Disabling futher interrupt handling\n");
+ bus_teardown_intr(sc->dev, sc->irq_res,
+ sc->ih);
+ sc->ih = NULL;
+ return;
+ }
+
+ switch (type) {
+ case MYRI10GE_MCP_INTR_ETHER_SEND_DONE:
+ myri10ge_tx_done(sc, be32toh(sc->intr.q[intrq][slot].data0));
+
+ if (__predict_true(sc->intr.q[intrq][slot].data1 == 0))
+ break;
+
+ /* check the link state. Don't bother to
+ * byteswap, since it can just be 0 or 1 */
+ if (sc->link_state != sc->fw_stats->link_up) {
+ sc->link_state = sc->fw_stats->link_up;
+ if (sc->link_state) {
+ if_link_state_change(sc->ifp,
+ LINK_STATE_UP);
+ device_printf(sc->dev,
+ "link up\n");
+ } else {
+ if_link_state_change(sc->ifp,
+ LINK_STATE_DOWN);
+ device_printf(sc->dev,
+ "link down\n");
+ }
+ }
+ if (sc->rdma_tags_available !=
+ be32toh(sc->fw_stats->rdma_tags_available)) {
+ sc->rdma_tags_available =
+ be32toh(sc->fw_stats->rdma_tags_available);
+ device_printf(sc->dev, "RDMA timed out!"
+ " %d tags left\n",
+ sc->rdma_tags_available);
+ }
+
+ break;
+
+
+ case MYRI10GE_MCP_INTR_ETHER_RECV_SMALL:
+ raw = be32toh(sc->intr.q[intrq][slot].data0);
+ count = 0xff & raw;
+ flags = raw >> 8;
+ raw = be32toh(sc->intr.q[intrq][slot].data1);
+ ip_csum = raw >> 16;
+ length = 0xffff & raw;
+ myri10ge_rx_done_small(sc, length, ip_csum,
+ flags);
+ break;
+
+ case MYRI10GE_MCP_INTR_ETHER_RECV_BIG:
+ raw = be32toh(sc->intr.q[intrq][slot].data0);
+ count = 0xff & raw;
+ flags = raw >> 8;
+ raw = be32toh(sc->intr.q[intrq][slot].data1);
+ ip_csum = raw >> 16;
+ length = 0xffff & raw;
+ myri10ge_rx_done_big(sc, length, ip_csum,
+ flags);
+
+ break;
+
+ case MYRI10GE_MCP_INTR_LINK_CHANGE:
+ /* not yet implemented in firmware */
+ break;
+
+ case MYRI10GE_MCP_INTR_ETHER_DOWN:
+ sc->down_cnt++;
+ wakeup(&sc->down_cnt);
+ break;
+
+ default:
+ device_printf(sc->dev, "Unknown interrupt type %d\n",
+ type);
+ }
+ sc->intr.q[intrq][slot].type = 0;
+ if (sc->intr.q[intrq][slot].flag != 0) {
+ if (!claimed) {
+ myri10ge_claim_irq(sc);
+ }
+ sc->intr.slot = 0;
+ sc->intr.q[intrq][slot].flag = 0;
+ sc->intr.intrq = ((intrq + 1) & 1);
+ return;
+ }
+ }
+
+ /* we should never be here unless we're on a shared irq and we have
+ not finished setting up the device */
+ return;
+}
+
+static void
+myri10ge_watchdog(struct ifnet *ifp)
+{
+ printf("%s called\n", __FUNCTION__);
+}
+
+static void
+myri10ge_init(void *arg)
+{
+}
+
+
+
+static void
+myri10ge_free_mbufs(myri10ge_softc_t *sc)
+{
+ int i;
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ m_freem(sc->rx_big.info[i].m);
+ sc->rx_big.info[i].m = NULL;
+ }
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ m_freem(sc->rx_big.info[i].m);
+ sc->rx_big.info[i].m = NULL;
+ }
+
+ for (i = 0; i <= sc->tx.mask; i++) {
+ if (sc->tx.info[i].m == NULL)
+ continue;
+ bus_dmamap_unload(sc->tx.dmat,
+ sc->tx.info[i].map);
+ m_freem(sc->tx.info[i].m);
+ sc->tx.info[i].m = NULL;
+ }
+}
+
+static void
+myri10ge_free_rings(myri10ge_softc_t *sc)
+{
+ int i;
+
+ if (sc->tx.req_bytes != NULL) {
+ free(sc->tx.req_bytes, M_DEVBUF);
+ }
+ if (sc->rx_small.shadow != NULL)
+ free(sc->rx_small.shadow, M_DEVBUF);
+ if (sc->rx_big.shadow != NULL)
+ free(sc->rx_big.shadow, M_DEVBUF);
+ if (sc->tx.info != NULL) {
+ for (i = 0; i <= sc->tx.mask; i++) {
+ if (sc->tx.info[i].map != NULL)
+ bus_dmamap_destroy(sc->tx.dmat,
+ sc->tx.info[i].map);
+ }
+ free(sc->tx.info, M_DEVBUF);
+ }
+ if (sc->rx_small.info != NULL) {
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ if (sc->rx_small.info[i].map != NULL)
+ bus_dmamap_destroy(sc->rx_small.dmat,
+ sc->rx_small.info[i].map);
+ }
+ free(sc->rx_small.info, M_DEVBUF);
+ }
+ if (sc->rx_big.info != NULL) {
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ if (sc->rx_big.info[i].map != NULL)
+ bus_dmamap_destroy(sc->rx_big.dmat,
+ sc->rx_big.info[i].map);
+ }
+ free(sc->rx_big.info, M_DEVBUF);
+ }
+ if (sc->rx_big.extra_map != NULL)
+ bus_dmamap_destroy(sc->rx_big.dmat,
+ sc->rx_big.extra_map);
+ if (sc->rx_small.extra_map != NULL)
+ bus_dmamap_destroy(sc->rx_small.dmat,
+ sc->rx_small.extra_map);
+ if (sc->tx.dmat != NULL)
+ bus_dma_tag_destroy(sc->tx.dmat);
+ if (sc->rx_small.dmat != NULL)
+ bus_dma_tag_destroy(sc->rx_small.dmat);
+ if (sc->rx_big.dmat != NULL)
+ bus_dma_tag_destroy(sc->rx_big.dmat);
+}
+
+static int
+myri10ge_alloc_rings(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int tx_ring_size, rx_ring_size;
+ int tx_ring_entries, rx_ring_entries;
+ int i, err;
+ unsigned long bytes;
+
+ /* get ring sizes */
+ err = myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_SEND_RING_SIZE,
+ &cmd);
+ tx_ring_size = cmd.data0;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_RX_RING_SIZE,
+ &cmd);
+ if (err != 0) {
+ device_printf(sc->dev, "Cannot determine ring sizes\n");
+ goto abort_with_nothing;
+ }
+
+ rx_ring_size = cmd.data0;
+
+ tx_ring_entries = tx_ring_size / sizeof (mcp_kreq_ether_send_t);
+ rx_ring_entries = rx_ring_size / sizeof (mcp_dma_addr_t);
+ sc->ifp->if_snd.ifq_maxlen = tx_ring_entries - 1;
+ sc->ifp->if_snd.ifq_drv_maxlen = sc->ifp->if_snd.ifq_maxlen;
+
+ sc->tx.mask = tx_ring_entries - 1;
+ sc->rx_small.mask = sc->rx_big.mask = rx_ring_entries - 1;
+
+ err = ENOMEM;
+
+ /* allocate the tx request copy block */
+ bytes = 8 +
+ sizeof (*sc->tx.req_list) * (MYRI10GE_MCP_ETHER_MAX_SEND_DESC + 4);
+ sc->tx.req_bytes = malloc(bytes, M_DEVBUF, M_WAITOK);
+ if (sc->tx.req_bytes == NULL)
+ goto abort_with_nothing;
+ /* ensure req_list entries are aligned to 8 bytes */
+ sc->tx.req_list = (mcp_kreq_ether_send_t *)
+ ((unsigned long)(sc->tx.req_bytes + 7) & ~7UL);
+
+ /* allocate the rx shadow rings */
+ bytes = rx_ring_entries * sizeof (*sc->rx_small.shadow);
+ sc->rx_small.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_small.shadow == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_big.shadow);
+ sc->rx_big.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_big.shadow == NULL)
+ goto abort_with_alloc;
+
+ /* allocate the host info rings */
+ bytes = tx_ring_entries * sizeof (*sc->tx.info);
+ sc->tx.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->tx.info == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_small.info);
+ sc->rx_small.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_small.info == NULL)
+ goto abort_with_alloc;
+
+ bytes = rx_ring_entries * sizeof (*sc->rx_big.info);
+ sc->rx_big.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK);
+ if (sc->rx_big.info == NULL)
+ goto abort_with_alloc;
+
+ /* allocate the busdma resources */
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ sc->tx.boundary, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MYRI10GE_MAX_ETHER_MTU,/* maxsize */
+ MYRI10GE_MCP_ETHER_MAX_SEND_DESC,/* num segs */
+ sc->tx.boundary, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->tx.dmat); /* tag */
+
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating tx dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MHLEN, /* maxsize */
+ 1, /* num segs */
+ MHLEN, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->rx_small.dmat); /* tag */
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating rx_small dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ err = bus_dma_tag_create(sc->parent_dmat, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ 4096, /* maxsize */
+ 1, /* num segs */
+ 4096, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, NULL, /* lock */
+ &sc->rx_big.dmat); /* tag */
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating rx_big dmat\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ /* now use these tags to setup dmamaps for each slot
+ in each ring */
+ for (i = 0; i <= sc->tx.mask; i++) {
+ err = bus_dmamap_create(sc->tx.dmat, 0,
+ &sc->tx.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d tx dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ err = bus_dmamap_create(sc->rx_small.dmat, 0,
+ &sc->rx_small.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d rx_small dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ err = bus_dmamap_create(sc->rx_small.dmat, 0,
+ &sc->rx_small.extra_map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d extra rx_small dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ err = bus_dmamap_create(sc->rx_big.dmat, 0,
+ &sc->rx_big.info[i].map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d rx_big dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ }
+ err = bus_dmamap_create(sc->rx_big.dmat, 0,
+ &sc->rx_big.extra_map);
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d extra rx_big dmamap\n",
+ err);
+ goto abort_with_alloc;
+ }
+ return 0;
+
+abort_with_alloc:
+ myri10ge_free_rings(sc);
+
+abort_with_nothing:
+ return err;
+}
+
+static int
+myri10ge_open(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int i, err;
+ bus_dmamap_t map;
+
+
+ err = myri10ge_reset(sc);
+ if (err != 0) {
+ device_printf(sc->dev, "failed to reset\n");
+ return EIO;
+ }
+
+ if (MCLBYTES >=
+ sc->ifp->if_mtu + ETHER_HDR_LEN + MYRI10GE_MCP_ETHER_PAD)
+ sc->big_bytes = MCLBYTES;
+ else
+ sc->big_bytes = MJUMPAGESIZE;
+
+ err = myri10ge_alloc_rings(sc);
+ if (err != 0) {
+ device_printf(sc->dev, "failed to allocate rings\n");
+ return err;
+ }
+
+ err = bus_setup_intr(sc->dev, sc->irq_res,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ myri10ge_intr, sc, &sc->ih);
+ if (err != 0) {
+ goto abort_with_rings;
+ }
+
+ /* get the lanai pointers to the send and receive rings */
+
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_GET_SEND_OFFSET, &cmd);
+ sc->tx.lanai =
+ (volatile mcp_kreq_ether_send_t *)(sc->sram + cmd.data0);
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_GET_SMALL_RX_OFFSET, &cmd);
+ sc->rx_small.lanai =
+ (volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
+ err |= myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_GET_BIG_RX_OFFSET, &cmd);
+ sc->rx_big.lanai =
+ (volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
+
+ if (err != 0) {
+ device_printf(sc->dev,
+ "failed to get ring sizes or locations\n");
+ err = EIO;
+ goto abort_with_irq;
+ }
+
+ if (sc->wc) {
+ sc->tx.wc_fifo = sc->sram + 0x200000;
+ sc->rx_small.wc_fifo = sc->sram + 0x300000;
+ sc->rx_big.wc_fifo = sc->sram + 0x340000;
+ } else {
+ sc->tx.wc_fifo = 0;
+ sc->rx_small.wc_fifo = 0;
+ sc->rx_big.wc_fifo = 0;
+ }
+
+
+ /* stock receive rings */
+ for (i = 0; i <= sc->rx_small.mask; i++) {
+ map = sc->rx_small.info[i].map;
+ err = myri10ge_get_buf_small(sc, map, i);
+ if (err) {
+ device_printf(sc->dev, "alloced %d/%d smalls\n",
+ i, sc->rx_small.mask + 1);
+ goto abort;
+ }
+ }
+ for (i = 0; i <= sc->rx_big.mask; i++) {
+ map = sc->rx_big.info[i].map;
+ err = myri10ge_get_buf_big(sc, map, i);
+ if (err) {
+ device_printf(sc->dev, "alloced %d/%d bigs\n",
+ i, sc->rx_big.mask + 1);
+ goto abort;
+ }
+ }
+
+ /* Give the firmware the mtu and the big and small buffer
+ sizes. The firmware wants the big buf size to be a power
+ of two. Luckily, FreeBSD's clusters are powers of two */
+ cmd.data0 = sc->ifp->if_mtu + ETHER_HDR_LEN;
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_MTU, &cmd);
+ cmd.data0 = MHLEN;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_SMALL_BUFFER_SIZE,
+ &cmd);
+ cmd.data0 = sc->big_bytes;
+ err |= myri10ge_send_cmd(sc,
+ MYRI10GE_MCP_CMD_SET_BIG_BUFFER_SIZE,
+ &cmd);
+ /* Now give him the pointer to the stats block */
+ cmd.data0 = MYRI10GE_LOWPART_TO_U32(sc->fw_stats_dma.bus_addr);
+ cmd.data1 = MYRI10GE_HIGHPART_TO_U32(sc->fw_stats_dma.bus_addr);
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_SET_STATS_DMA, &cmd);
+
+ if (err != 0) {
+ device_printf(sc->dev, "failed to setup params\n");
+ goto abort;
+ }
+
+ /* Finally, start the firmware running */
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_ETHERNET_UP, &cmd);
+ if (err) {
+ device_printf(sc->dev, "Couldn't bring up link\n");
+ goto abort;
+ }
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ return 0;
+
+
+abort:
+ myri10ge_free_mbufs(sc);
+abort_with_irq:
+ bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+abort_with_rings:
+ myri10ge_free_rings(sc);
+ return err;
+}
+
+static int
+myri10ge_close(myri10ge_softc_t *sc)
+{
+ myri10ge_cmd_t cmd;
+ int err, old_down_cnt;
+
+ sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ old_down_cnt = sc->down_cnt;
+ mb();
+ err = myri10ge_send_cmd(sc, MYRI10GE_MCP_CMD_ETHERNET_DOWN, &cmd);
+ if (err) {
+ device_printf(sc->dev, "Couldn't bring down link\n");
+ }
+ if (old_down_cnt == sc->down_cnt) {
+ /* wait for down irq */
+ (void)tsleep(&sc->down_cnt, PWAIT, "down myri10ge", hz);
+ }
+ if (old_down_cnt == sc->down_cnt) {
+ device_printf(sc->dev, "never got down irq\n");
+ }
+ if (sc->ih != NULL)
+ bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+ myri10ge_free_mbufs(sc);
+ myri10ge_free_rings(sc);
+ return 0;
+}
+
+
+static int
+myri10ge_media_change(struct ifnet *ifp)
+{
+ return EINVAL;
+}
+
+static int
+myri10ge_change_mtu(myri10ge_softc_t *sc, int mtu)
+{
+ struct ifnet *ifp = sc->ifp;
+ int real_mtu, old_mtu;
+ int err = 0;
+
+
+ real_mtu = mtu + ETHER_HDR_LEN;
+ if ((real_mtu > MYRI10GE_MAX_ETHER_MTU) ||
+ real_mtu < 60)
+ return EINVAL;
+ sx_xlock(&sc->driver_lock);
+ old_mtu = ifp->if_mtu;
+ ifp->if_mtu = mtu;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ myri10ge_close(sc);
+ err = myri10ge_open(sc);
+ if (err != 0) {
+ ifp->if_mtu = old_mtu;
+ myri10ge_close(sc);
+ (void) myri10ge_open(sc);
+ }
+ }
+ sx_xunlock(&sc->driver_lock);
+ return err;
+}
+
+static void
+myri10ge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+
+
+ if (sc == NULL)
+ return;
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_status |= sc->fw_stats->link_up ? IFM_ACTIVE : 0;
+ ifmr->ifm_active = IFM_AUTO | IFM_ETHER;
+ ifmr->ifm_active |= sc->fw_stats->link_up ? IFM_FDX : 0;
+}
+
+static int
+myri10ge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ myri10ge_softc_t *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int err, mask;
+
+ err = 0;
+ switch (command) {
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ err = ether_ioctl(ifp, command, data);
+ break;
+
+ case SIOCSIFMTU:
+ err = myri10ge_change_mtu(sc, ifr->ifr_mtu);
+ break;
+
+ case SIOCSIFFLAGS:
+ sx_xlock(&sc->driver_lock);
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ err = myri10ge_open(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ myri10ge_close(sc);
+ }
+ sx_xunlock(&sc->driver_lock);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ err = 0;
+ break;
+
+ case SIOCSIFCAP:
+ sx_xlock(&sc->driver_lock);
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+ if (mask & IFCAP_TXCSUM) {
+ if (IFCAP_TXCSUM & ifp->if_capenable) {
+ ifp->if_capenable &= ~IFCAP_TXCSUM;
+ ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP);
+ } else {
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+ }
+ } else if (mask & IFCAP_RXCSUM) {
+ if (IFCAP_RXCSUM & ifp->if_capenable) {
+ ifp->if_capenable &= ~IFCAP_RXCSUM;
+ sc->csum_flag &= ~MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ } else {
+ ifp->if_capenable |= IFCAP_RXCSUM;
+ sc->csum_flag |= MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ }
+ }
+ sx_xunlock(&sc->driver_lock);
+ break;
+
+ case SIOCGIFMEDIA:
+ err = ifmedia_ioctl(ifp, (struct ifreq *)data,
+ &sc->media, command);
+ break;
+
+ default:
+ err = ENOTTY;
+ }
+ return err;
+}
+
+static void
+myri10ge_fetch_tunables(myri10ge_softc_t *sc)
+{
+
+ TUNABLE_INT_FETCH("hw.myri10ge.flow_control_enabled",
+ &myri10ge_flow_control);
+ TUNABLE_INT_FETCH("hw.myri10ge.intr_coal_delay",
+ &myri10ge_intr_coal_delay);
+ TUNABLE_INT_FETCH("hw.myri10ge.nvidia_ecrc_enable",
+ &myri10ge_nvidia_ecrc_enable);
+ TUNABLE_INT_FETCH("hw.myri10ge.skip_pio_read",
+ &myri10ge_skip_pio_read);
+
+ if (myri10ge_intr_coal_delay < 0 ||
+ myri10ge_intr_coal_delay > 10*1000)
+ myri10ge_intr_coal_delay = 30;
+ sc->pause = myri10ge_flow_control;
+}
+
+static int
+myri10ge_attach(device_t dev)
+{
+ myri10ge_softc_t *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ size_t bytes;
+ int rid, err, i;
+ uint16_t cmd;
+
+ sc->dev = dev;
+ myri10ge_fetch_tunables(sc);
+
+ err = bus_dma_tag_create(NULL, /* parent */
+ 1, /* alignment */
+ 4096, /* boundary */
+ BUS_SPACE_MAXADDR, /* low */
+ BUS_SPACE_MAXADDR, /* high */
+ NULL, NULL, /* filter */
+ MYRI10GE_MAX_ETHER_MTU,/* maxsize */
+ MYRI10GE_MCP_ETHER_MAX_SEND_DESC, /* num segs */
+ 4096, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lock */
+ &sc->parent_dmat); /* tag */
+
+ if (err != 0) {
+ device_printf(sc->dev, "Err %d allocating parent dmat\n",
+ err);
+ goto abort_with_nothing;
+ }
+
+ ifp = sc->ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ err = ENOSPC;
+ goto abort_with_parent_dmat;
+ }
+ mtx_init(&sc->cmd_lock, NULL,
+ MTX_NETWORK_LOCK, MTX_DEF);
+ mtx_init(&sc->tx_lock, device_get_nameunit(dev),
+ MTX_NETWORK_LOCK, MTX_DEF);
+ sx_init(&sc->driver_lock, device_get_nameunit(dev));
+
+ /* Enable DMA and Memory space access */
+ pci_enable_busmaster(dev);
+ cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ cmd |= PCIM_CMD_MEMEN;
+ pci_write_config(dev, PCIR_COMMAND, cmd, 2);
+
+ /* Map the board into the kernel */
+ rid = PCIR_BARS;
+ sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
+ ~0, 1, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not map memory\n");
+ err = ENXIO;
+ goto abort_with_lock;
+ }
+ sc->sram = rman_get_virtual(sc->mem_res);
+ sc->sram_size = 2*1024*1024 - (2*(48*1024)+(32*1024)) - 0x100;
+ if (sc->sram_size > rman_get_size(sc->mem_res)) {
+ device_printf(dev, "impossible memory region size %ld\n",
+ rman_get_size(sc->mem_res));
+ err = ENXIO;
+ goto abort_with_mem_res;
+ }
+
+ /* make NULL terminated copy of the EEPROM strings section of
+ lanai SRAM */
+ bzero(sc->eeprom_strings, MYRI10GE_EEPROM_STRINGS_SIZE);
+ bus_space_read_region_1(rman_get_bustag(sc->mem_res),
+ rman_get_bushandle(sc->mem_res),
+ sc->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
+ sc->eeprom_strings,
+ MYRI10GE_EEPROM_STRINGS_SIZE - 2);
+ err = myri10ge_parse_strings(sc);
+ if (err != 0)
+ goto abort_with_mem_res;
+
+ /* Enable write combining for efficient use of PCIe bus */
+ myri10ge_enable_wc(sc);
+
+ /* Allocate the out of band dma memory */
+ err = myri10ge_dma_alloc(sc, &sc->cmd_dma,
+ sizeof (myri10ge_cmd_t), 64);
+ if (err != 0)
+ goto abort_with_mem_res;
+ sc->cmd = (mcp_cmd_response_t *) sc->cmd_dma.addr;
+ err = myri10ge_dma_alloc(sc, &sc->zeropad_dma, 64, 64);
+ if (err != 0)
+ goto abort_with_cmd_dma;
+
+ err = myri10ge_dma_alloc(sc, &sc->fw_stats_dma,
+ sizeof (*sc->fw_stats), 64);
+ if (err != 0)
+ goto abort_with_zeropad_dma;
+ sc->fw_stats = (mcp_stats_t *)sc->fw_stats_dma.addr;
+
+
+ /* allocate interrupt queues */
+ bytes = myri10ge_max_intr_slots * sizeof (*sc->intr.q[0]);
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ err = myri10ge_dma_alloc(sc, &sc->intr.dma[i],
+ bytes, 4096);
+ if (err != 0)
+ goto abort_with_intrq;
+ sc->intr.q[i] = (mcp_slot_t *)sc->intr.dma[i].addr;
+ }
+
+ /* Add our ithread */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,
+ 1, RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "could not alloc interrupt\n");
+ goto abort_with_intrq;
+ }
+
+ /* load the firmware */
+ myri10ge_select_firmware(sc);
+
+ err = myri10ge_load_firmware(sc);
+ if (err != 0)
+ goto abort_with_irq_res;
+ err = myri10ge_reset(sc);
+ if (err != 0)
+ goto abort_with_irq_res;
+
+ /* hook into the network stack */
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_baudrate = 100000000;
+ ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM;
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+ ifp->if_capenable = ifp->if_capabilities;
+ sc->csum_flag |= MYRI10GE_MCP_ETHER_FLAGS_CKSUM;
+ ifp->if_init = myri10ge_init;
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = myri10ge_ioctl;
+ ifp->if_start = myri10ge_start;
+ ifp->if_watchdog = myri10ge_watchdog;
+ ether_ifattach(ifp, sc->mac_addr);
+ /* ether_ifattach sets mtu to 1500 */
+ ifp->if_mtu = MYRI10GE_MAX_ETHER_MTU - ETHER_HDR_LEN;
+
+ /* Initialise the ifmedia structure */
+ ifmedia_init(&sc->media, 0, myri10ge_media_change,
+ myri10ge_media_status);
+ ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
+ myri10ge_add_sysctls(sc);
+ return 0;
+
+abort_with_irq_res:
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+abort_with_intrq:
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ if (sc->intr.q[i] == NULL)
+ continue;
+ sc->intr.q[i] = NULL;
+ myri10ge_dma_free(&sc->intr.dma[i]);
+ }
+ myri10ge_dma_free(&sc->fw_stats_dma);
+abort_with_zeropad_dma:
+ myri10ge_dma_free(&sc->zeropad_dma);
+abort_with_cmd_dma:
+ myri10ge_dma_free(&sc->cmd_dma);
+abort_with_mem_res:
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
+abort_with_lock:
+ pci_disable_busmaster(dev);
+ mtx_destroy(&sc->cmd_lock);
+ mtx_destroy(&sc->tx_lock);
+ sx_destroy(&sc->driver_lock);
+ if_free(ifp);
+abort_with_parent_dmat:
+ bus_dma_tag_destroy(sc->parent_dmat);
+
+abort_with_nothing:
+ return err;
+}
+
+static int
+myri10ge_detach(device_t dev)
+{
+ myri10ge_softc_t *sc = device_get_softc(dev);
+ int i;
+
+ sx_xlock(&sc->driver_lock);
+ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING)
+ myri10ge_close(sc);
+ sx_xunlock(&sc->driver_lock);
+ ether_ifdetach(sc->ifp);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ for (i = 0; i < MYRI10GE_NUM_INTRQS; i++) {
+ if (sc->intr.q[i] == NULL)
+ continue;
+ sc->intr.q[i] = NULL;
+ myri10ge_dma_free(&sc->intr.dma[i]);
+ }
+ myri10ge_dma_free(&sc->fw_stats_dma);
+ myri10ge_dma_free(&sc->zeropad_dma);
+ myri10ge_dma_free(&sc->cmd_dma);
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
+ pci_disable_busmaster(dev);
+ mtx_destroy(&sc->cmd_lock);
+ mtx_destroy(&sc->tx_lock);
+ sx_destroy(&sc->driver_lock);
+ if_free(sc->ifp);
+ bus_dma_tag_destroy(sc->parent_dmat);
+ return 0;
+}
+
+static int
+myri10ge_shutdown(device_t dev)
+{
+ return 0;
+}
+
+/*
+ This file uses Myri10GE driver indentation.
+
+ Local Variables:
+ c-file-style:"linux"
+ tab-width:8
+ End:
+*/
diff --git a/sys/dev/myri10ge/if_myri10ge_var.h b/sys/dev/myri10ge/if_myri10ge_var.h
new file mode 100644
index 0000000..e4ce955
--- /dev/null
+++ b/sys/dev/myri10ge/if_myri10ge_var.h
@@ -0,0 +1,203 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+
+***************************************************************************/
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_NUM_INTRQS 2
+
+typedef struct {
+ void *addr;
+ bus_addr_t bus_addr;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t map;
+} myri10ge_dma_t;
+
+typedef struct myri10ge_intrq
+{
+ mcp_slot_t *q[MYRI10GE_NUM_INTRQS];
+ int intrq;
+ int slot;
+ int maxslots;
+ uint32_t seqnum;
+ uint32_t spurious;
+ uint32_t cnt;
+ myri10ge_dma_t dma[MYRI10GE_NUM_INTRQS];
+} myri10ge_intrq_t;
+
+
+typedef struct
+{
+ uint32_t data0;
+ uint32_t data1;
+ uint32_t data2;
+} myri10ge_cmd_t;
+
+struct myri10ge_buffer_state {
+ struct mbuf *m;
+ bus_dmamap_t map;
+};
+
+typedef struct
+{
+ volatile mcp_kreq_ether_recv_t *lanai; /* lanai ptr for recv ring */
+ volatile uint8_t *wc_fifo; /* w/c rx dma addr fifo address */
+ mcp_kreq_ether_recv_t *shadow; /* host shadow of recv ring */
+ struct myri10ge_buffer_state *info;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t extra_map;
+ int cnt;
+ int alloc_fail;
+ int mask; /* number of rx slots -1 */
+} myri10ge_rx_buf_t;
+
+typedef struct
+{
+ volatile mcp_kreq_ether_send_t *lanai; /* lanai ptr for sendq */
+ volatile uint8_t *wc_fifo; /* w/c send fifo address */
+ mcp_kreq_ether_send_t *req_list; /* host shadow of sendq */
+ char *req_bytes;
+ struct myri10ge_buffer_state *info;
+ bus_dma_tag_t dmat;
+ int req; /* transmits submitted */
+ int mask; /* number of transmit slots -1 */
+ int done; /* transmits completed */
+ int boundary; /* boundary transmits cannot cross*/
+} myri10ge_tx_buf_t;
+
+typedef struct {
+ struct ifnet* ifp;
+ int big_bytes;
+ struct mtx tx_lock;
+ int csum_flag; /* rx_csums? */
+ uint8_t mac_addr[6]; /* eeprom mac address */
+ myri10ge_tx_buf_t tx; /* transmit ring */
+ myri10ge_rx_buf_t rx_small;
+ myri10ge_rx_buf_t rx_big;
+ bus_dma_tag_t parent_dmat;
+ volatile uint8_t *sram;
+ int sram_size;
+ volatile uint32_t *irq_claim;
+ char *mac_addr_string;
+ char *product_code_string;
+ mcp_cmd_response_t *cmd;
+ myri10ge_dma_t cmd_dma;
+ myri10ge_dma_t zeropad_dma;
+ mcp_stats_t *fw_stats;
+ myri10ge_dma_t fw_stats_dma;
+ struct pci_dev *pdev;
+ int msi_enabled;
+ myri10ge_intrq_t intr;
+ int link_state;
+ unsigned int rdma_tags_available;
+ int intr_coal_delay;
+ int wc;
+ struct mtx cmd_lock;
+ struct sx driver_lock;
+ int wake_queue;
+ int stop_queue;
+ int down_cnt;
+ int watchdog_resets;
+ int tx_defragged;
+ int pause;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *ih;
+ char *fw_name;
+ char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+ char fw_version[128];
+ device_t dev;
+ struct ifmedia media;
+
+} myri10ge_softc_t;
+
+#define MYRI10GE_PCI_VENDOR_MYRICOM 0x14c1
+#define MYRI10GE_PCI_DEVICE_Z8E 0x0008
+
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((uint32_t)((uint64_t)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((uint32_t)(X))
+
+
+/* implement our own memory barriers, since bus_space_barrier
+ cannot handle write-combining regions */
+
+#if defined (__GNUC__)
+ #if #cpu(i386) || defined __i386 || defined i386 || defined __i386__ || #cpu(x86_64) || defined __x86_64__
+ #define mb() __asm__ __volatile__ ("sfence;": : :"memory")
+ #elif #cpu(sparc64) || defined sparc64 || defined __sparcv9
+ #define mb() __asm__ __volatile__ ("membar #MemIssue": : :"memory")
+ #elif #cpu(sparc) || defined sparc || defined __sparc__
+ #define mb() __asm__ __volatile__ ("stbar;": : :"memory")
+ #else
+ #define mb() /* XXX just to make this compile */
+ #endif
+#else
+ #error "unknown compiler"
+#endif
+
+static inline void
+myri10ge_pio_copy(volatile void *to_v, void *from_v, size_t size)
+{
+ register volatile uintptr_t *to;
+ volatile uintptr_t *from;
+ size_t i;
+
+ to = (volatile uintptr_t *) to_v;
+ from = from_v;
+ for (i = (size / sizeof (uintptr_t)); i; i--) {
+ *to = *from;
+ to++;
+ from++;
+ }
+
+}
+
+
+/*
+ This file uses Myri10GE driver indentation.
+
+ Local Variables:
+ c-file-style:"linux"
+ tab-width:8
+ End:
+*/
diff --git a/sys/dev/myri10ge/mcp_gen_header.h b/sys/dev/myri10ge/mcp_gen_header.h
new file mode 100644
index 0000000..7cb4491
--- /dev/null
+++ b/sys/dev/myri10ge/mcp_gen_header.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+#ifndef _mcp_gen_header_h
+#define _mcp_gen_header_h
+
+/* this file define a standard header used as a first entry point to
+ exchange information between firmware/driver and driver. The
+ header structure can be anywhere in the mcp. It will usually be in
+ the .data section, because some fields needs to be initialized at
+ compile time.
+ The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must
+ contains the location of the header.
+
+ Typically a MCP will start with the following:
+ .text
+ .space 52 ! to help catch MEMORY_INT errors
+ bt start ! jump to real code
+ nop
+ .long _gen_mcp_header
+
+ The source will have a definition like:
+
+ mcp_gen_header_t gen_mcp_header = {
+ .header_length = sizeof(mcp_gen_header_t),
+ .mcp_type = MCP_TYPE_XXX,
+ .version = "something $Id: mcp_gen_header.h,v 1.1 2005/12/23 02:10:44 gallatin Exp $",
+ .mcp_globals = (unsigned)&Globals
+ };
+*/
+
+
+#define MCP_HEADER_PTR_OFFSET 0x3c
+
+#define MCP_TYPE_MX 0x4d582020 /* "MX " */
+#define MCP_TYPE_PCIE 0x70636965 /* "PCIE" pcie-only MCP */
+#define MCP_TYPE_ETH 0x45544820 /* "ETH " */
+#define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */
+
+
+typedef struct mcp_gen_header {
+ /* the first 4 fields are filled at compile time */
+ unsigned header_length;
+ unsigned mcp_type;
+ char version[128];
+ unsigned mcp_globals; /* pointer to mcp-type specific structure */
+
+ /* filled by the MCP at run-time */
+ unsigned sram_size;
+ unsigned string_specs; /* either the original STRING_SPECS or a superset */
+ unsigned string_specs_len;
+
+ /* Fields above this comment are guaranteed to be present.
+
+ Fields below this comment are extensions added in later versions
+ of this struct, drivers should compare the header_length against
+ offsetof(field) to check wether a given MCP implements them.
+
+ Never remove any field. Keep everything naturally align.
+ */
+} mcp_gen_header_t;
+
+/* Macro to create a simple mcp header */
+#define MCP_GEN_HEADER_DECL(type, version_str, global_ptr) \
+ struct mcp_gen_header mcp_gen_header = { \
+ sizeof (struct mcp_gen_header), \
+ (type), \
+ version_str, \
+ (global_ptr), \
+ SRAM_SIZE, \
+ (unsigned int) STRING_SPECS, \
+ 256 \
+ }
+
+
+#endif /* _mcp_gen_header_h */
diff --git a/sys/dev/myri10ge/myri10ge_mcp.h b/sys/dev/myri10ge/myri10ge_mcp.h
new file mode 100644
index 0000000..de85fde
--- /dev/null
+++ b/sys/dev/myri10ge/myri10ge_mcp.h
@@ -0,0 +1,265 @@
+/*******************************************************************************
+
+Copyright (c) 2006, Myricom Inc.
+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 the Myricom Inc, nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+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.
+
+$FreeBSD$
+***************************************************************************/
+
+#ifndef _myri10ge_mcp_h
+#define _myri10ge_mcp_h
+
+#ifdef MYRI10GE_MCP
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#endif
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t high;
+ uint32_t low;
+} mcp_dma_addr_t;
+
+/* 16 Bytes */
+typedef struct
+{
+ uint32_t data0;
+ uint32_t data1;
+ uint32_t seqnum;
+ uint16_t index;
+ uint8_t flag;
+ uint8_t type;
+} mcp_slot_t;
+
+/* 64 Bytes */
+typedef struct
+{
+ uint32_t cmd;
+ uint32_t data0; /* will be low portion if data > 32 bits */
+ /* 8 */
+ uint32_t data1; /* will be high portion if data > 32 bits */
+ uint32_t data2; /* currently unused.. */
+ /* 16 */
+ mcp_dma_addr_t response_addr;
+ /* 24 */
+ uint8_t pad[40];
+} mcp_cmd_t;
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t data;
+ uint32_t result;
+} mcp_cmd_response_t;
+
+
+
+/*
+ flags used in mcp_kreq_ether_send_t:
+
+ The SMALL flag is only needed in the first segment. It is raised
+ for packets that are total less or equal 512 bytes.
+
+ The CKSUM flag must be set in all segments.
+
+ The PADDED flags is set if the packet needs to be padded, and it
+ must be set for all segments.
+
+ The MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD must be set if the cumulative
+ length of all previous segments was odd.
+*/
+
+
+#define MYRI10GE_MCP_ETHER_FLAGS_VALID 0x1
+#define MYRI10GE_MCP_ETHER_FLAGS_FIRST 0x2
+#define MYRI10GE_MCP_ETHER_FLAGS_ALIGN_ODD 0x4
+#define MYRI10GE_MCP_ETHER_FLAGS_CKSUM 0x8
+#define MYRI10GE_MCP_ETHER_FLAGS_SMALL 0x10
+#define MYRI10GE_MCP_ETHER_FLAGS_NOT_LAST 0x100
+#define MYRI10GE_MCP_ETHER_FLAGS_TSO_HDR 0x200
+#define MYRI10GE_MCP_ETHER_FLAGS_TSO 0x400
+
+#define MYRI10GE_MCP_ETHER_SEND_SMALL_SIZE 1520
+#define MYRI10GE_MCP_ETHER_MAX_MTU 9400
+
+typedef union mcp_pso_or_cumlen
+{
+ uint16_t pseudo_hdr_offset;
+ uint16_t cum_len;
+} mcp_pso_or_cumlen_t;
+
+#define MYRI10GE_MCP_ETHER_MAX_SEND_DESC 12
+#define MYRI10GE_MCP_ETHER_PAD 2
+
+/* 16 Bytes */
+typedef struct
+{
+ uint32_t addr_high;
+ uint32_t addr_low;
+ uint16_t length;
+ uint8_t pad;
+ uint8_t cksum_offset; /* where to start computing cksum */
+ uint16_t pseudo_hdr_offset;
+ uint16_t flags; /* as defined above */
+} mcp_kreq_ether_send_t;
+
+/* 8 Bytes */
+typedef struct
+{
+ uint32_t addr_high;
+ uint32_t addr_low;
+} mcp_kreq_ether_recv_t;
+
+
+/* Commands */
+
+#define MYRI10GE_MCP_CMD_OFFSET 0xf80000
+
+typedef enum {
+ MYRI10GE_MCP_CMD_NONE = 0,
+ /* Reset the mcp, it is left in a safe state, waiting
+ for the driver to set all its parameters */
+ MYRI10GE_MCP_CMD_RESET,
+
+ /* get the version number of the current firmware..
+ (may be available in the eeprom strings..? */
+ MYRI10GE_MCP_GET_MCP_VERSION,
+
+
+ /* Parameters which must be set by the driver before it can
+ issue MYRI10GE_MCP_CMD_ETHERNET_UP. They persist until the next
+ MYRI10GE_MCP_CMD_RESET is issued */
+
+ MYRI10GE_MCP_CMD_SET_INTRQ0_DMA,
+ MYRI10GE_MCP_CMD_SET_INTRQ1_DMA,
+ MYRI10GE_MCP_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */
+ MYRI10GE_MCP_CMD_SET_SMALL_BUFFER_SIZE, /* in bytes */
+
+
+ /* Parameters which refer to lanai SRAM addresses where the
+ driver must issue PIO writes for various things */
+
+ MYRI10GE_MCP_CMD_GET_SEND_OFFSET,
+ MYRI10GE_MCP_CMD_GET_SMALL_RX_OFFSET,
+ MYRI10GE_MCP_CMD_GET_BIG_RX_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_ACK_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_DEASSERT_OFFSET,
+ MYRI10GE_MCP_CMD_GET_IRQ_ACK_DEASSERT_OFFSET,
+
+ /* Parameters which refer to rings stored on the MCP,
+ and whose size is controlled by the mcp */
+
+ MYRI10GE_MCP_CMD_GET_SEND_RING_SIZE, /* in bytes */
+ MYRI10GE_MCP_CMD_GET_RX_RING_SIZE, /* in bytes */
+
+ /* Parameters which refer to rings stored in the host,
+ and whose size is controlled by the host. Note that
+ all must be physically contiguous and must contain
+ a power of 2 number of entries. */
+
+ MYRI10GE_MCP_CMD_SET_INTRQ_SIZE, /* in bytes */
+
+ /* command to bring ethernet interface up. Above parameters
+ (plus mtu & mac address) must have been exchanged prior
+ to issuing this command */
+ MYRI10GE_MCP_CMD_ETHERNET_UP,
+
+ /* command to bring ethernet interface down. No further sends
+ or receives may be processed until an MYRI10GE_MCP_CMD_ETHERNET_UP
+ is issued, and all interrupt queues must be flushed prior
+ to ack'ing this command */
+
+ MYRI10GE_MCP_CMD_ETHERNET_DOWN,
+
+ /* commands the driver may issue live, without resetting
+ the nic. Note that increasing the mtu "live" should
+ only be done if the driver has already supplied buffers
+ sufficiently large to handle the new mtu. Decreasing
+ the mtu live is safe */
+
+ MYRI10GE_MCP_CMD_SET_MTU,
+ MYRI10GE_MCP_CMD_SET_INTR_COAL_DELAY, /* in microseconds */
+ MYRI10GE_MCP_CMD_SET_STATS_INTERVAL, /* in microseconds */
+ MYRI10GE_MCP_CMD_SET_STATS_DMA,
+
+ MYRI10GE_MCP_ENABLE_PROMISC,
+ MYRI10GE_MCP_DISABLE_PROMISC,
+ MYRI10GE_MCP_SET_MAC_ADDRESS,
+
+ MYRI10GE_MCP_ENABLE_FLOW_CONTROL,
+ MYRI10GE_MCP_DISABLE_FLOW_CONTROL
+} myri10ge_mcp_cmd_type_t;
+
+
+typedef enum {
+ MYRI10GE_MCP_CMD_OK = 0,
+ MYRI10GE_MCP_CMD_UNKNOWN,
+ MYRI10GE_MCP_CMD_ERROR_RANGE,
+ MYRI10GE_MCP_CMD_ERROR_BUSY,
+ MYRI10GE_MCP_CMD_ERROR_EMPTY,
+ MYRI10GE_MCP_CMD_ERROR_CLOSED,
+ MYRI10GE_MCP_CMD_ERROR_HASH_ERROR,
+ MYRI10GE_MCP_CMD_ERROR_BAD_PORT,
+ MYRI10GE_MCP_CMD_ERROR_RESOURCES
+} myri10ge_mcp_cmd_status_t;
+
+typedef enum {
+ MYRI10GE_MCP_INTR_NONE = 0,
+ MYRI10GE_MCP_INTR_ETHER_SEND_DONE,
+ MYRI10GE_MCP_INTR_ETHER_RECV_SMALL,
+ MYRI10GE_MCP_INTR_ETHER_RECV_BIG,
+ MYRI10GE_MCP_INTR_LINK_CHANGE,
+ MYRI10GE_MCP_INTR_STATS_UPDATE,
+ MYRI10GE_MCP_INTR_ETHER_DOWN
+} myri10ge_mcp_intr_type_t;
+
+
+/* 32 Bytes */
+typedef struct
+{
+ uint32_t link_up;
+ uint32_t dropped_link_overflow;
+ uint32_t dropped_link_error_or_filtered;
+ uint32_t dropped_runt;
+ uint32_t dropped_overrun;
+ uint32_t dropped_no_small_buffer;
+ uint32_t dropped_no_big_buffer;
+ uint32_t dropped_interrupt_busy;
+ uint32_t rdma_tags_available;
+} mcp_stats_t;
+
+
+#endif /* _myri10ge_mcp_h */
OpenPOWER on IntegriCloud