This is an automated email from the ASF dual-hosted git repository.
jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 880c8e5d266 drivers/net: add IGB network card support
880c8e5d266 is described below
commit 880c8e5d26662f690432645327e3b76ebd2980b0
Author: p-szafonimateusz <[email protected]>
AuthorDate: Mon Jun 9 13:04:38 2025 +0200
drivers/net: add IGB network card support
Add support for Intel IGB type of network cards.
Signed-off-by: p-szafonimateusz <[email protected]>
---
.../components/drivers/special/pci/index.rst | 10 +
drivers/net/CMakeLists.txt | 4 +
drivers/net/Kconfig | 30 +
drivers/net/Make.defs | 8 +-
drivers/net/igb.c | 1492 ++++++++++++++++++++
drivers/net/igb.h | 544 +++++++
drivers/pci/pci_drivers.c | 11 +
include/nuttx/net/igb.h | 59 +
8 files changed, 2156 insertions(+), 2 deletions(-)
diff --git a/Documentation/components/drivers/special/pci/index.rst
b/Documentation/components/drivers/special/pci/index.rst
index 99160423b4e..ddd5dca7e58 100644
--- a/Documentation/components/drivers/special/pci/index.rst
+++ b/Documentation/components/drivers/special/pci/index.rst
@@ -50,6 +50,16 @@ Supported devices:
- Intel 82574L
- Intel 82574L
+Intel igb
+---------
+
+Intel igb compatible NIC support can be found in ``drivers/net/igb.c``.
+
+Supported devices:
+
+- Intel 82576
+- Intel I211
+
Intel igc
---------
diff --git a/drivers/net/CMakeLists.txt b/drivers/net/CMakeLists.txt
index 3d0937f7f5f..1e9613871e8 100644
--- a/drivers/net/CMakeLists.txt
+++ b/drivers/net/CMakeLists.txt
@@ -89,6 +89,10 @@ if(CONFIG_NET)
list(APPEND SRCS e1000.c)
endif()
+ if(CONFIG_NET_IGB)
+ list(APPEND SRCS igb.c)
+ endif()
+
if(CONFIG_NET_IGC)
list(APPEND SRCS igc.c)
endif()
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 77e6604877c..ffb561a3e47 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -815,6 +815,36 @@ config NET_E1000_RXSPARE
endif # NET_E1000
+menuconfig NET_IGB
+ bool "Intel IGB support"
+ default n
+ depends on PCI && PCI_MSIX
+ ---help---
+ Enable IGB PCI Ethernet driver.
+
+if NET_IGB
+
+config NET_IGB_TXDESC
+ int "Intel IGB TX descriptors"
+ default 256
+
+config NET_IGB_RXDESC
+ int "Intel IGB RX descriptors"
+ default 256
+
+config NET_IGB_RXSPARE
+ int "Intel IGB spare RX buffers"
+ default 8
+
+config NET_IGB_INT_INTERVAL
+ int "Intel IGB interrupt interval"
+ default 100
+ range 1 8191
+ ---help---
+ Minimum Inter-interrupt Interval in 1 us increments.
+
+endif # NET_IGB
+
menuconfig NET_IGC
bool "Intel IGC support"
default n
diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs
index f341749752b..b1e781b7e00 100644
--- a/drivers/net/Make.defs
+++ b/drivers/net/Make.defs
@@ -103,14 +103,18 @@ ifeq ($(CONFIG_NET_E1000),y)
CSRCS += e1000.c
endif
-ifeq ($(CONFIG_DRIVERS_WIFI_SIM),y)
- CSRCS += wifi_sim.c
+ifeq ($(CONFIG_NET_IGB),y)
+ CSRCS += igb.c
endif
ifeq ($(CONFIG_NET_IGC),y)
CSRCS += igc.c
endif
+ifeq ($(CONFIG_DRIVERS_WIFI_SIM),y)
+ CSRCS += wifi_sim.c
+endif
+
# Include network build support
DEPPATH += --dep-path net
diff --git a/drivers/net/igb.c b/drivers/net/igb.c
new file mode 100644
index 00000000000..8585dd83b3e
--- /dev/null
+++ b/drivers/net/igb.c
@@ -0,0 +1,1492 @@
+/*****************************************************************************
+ * drivers/net/igb.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/addrenv.h>
+#include <nuttx/spinlock.h>
+
+#include <nuttx/net/netdev_lowerhalf.h>
+#include <nuttx/pci/pci.h>
+#include <nuttx/net/igb.h>
+
+#include <arch/barriers.h>
+
+#include "igb.h"
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+#if CONFIG_NET_IGB_TXDESC % 8 != 0
+# error CONFIG_NET_IGB_TXDESC must be multiple of 8
+#endif
+
+#if CONFIG_NET_IGB_RXDESC % 8 != 0
+# error CONFIG_NET_IGB_RXDESC must be multiple of 8
+#endif
+
+/* Packet buffer size */
+
+#define IGB_PKTBUF_SIZE 2048
+#define IGB_RCTL_BSIZE IGB_RCTL_BSIZE_2048
+
+/* TX and RX descriptors */
+
+#define IGB_TX_DESC CONFIG_NET_IGB_TXDESC
+#define IGB_RX_DESC CONFIG_NET_IGB_RXDESC
+
+/* After RX packet is done, we provide free netpkt to the RX descriptor ring.
+ * The upper-half network logic is responsible for freeing the RX packets
+ * so we need some additional spare netpkt buffers to assure that it's
+ * always possible to allocate the new RX packet in the receiver logic.
+ * It's hard to tell how many spare buffers is needed, for now it's set to 8.
+ */
+
+#define IGB_TX_QUOTA IGB_TX_DESC
+#define IGB_RX_QUOTA (IGB_RX_DESC + CONFIG_NET_IGB_RXSPARE)
+
+/* NOTE: CONFIG_IOB_ALIGNMENT must match system D-CACHE line size */
+
+#if CONFIG_IOB_NBUFFERS < IGB_RX_QUOTA + IGB_TX_QUOTA
+# error CONFIG_IOB_NBUFFERS must be > (IGB_RX_QUOTA + IGB_TX_QUOTA)
+#endif
+
+#if CONFIG_IOB_BUFSIZE < IGB_PKTBUF_SIZE
+# error CONFIG_IOB_BUFSIZE must be > IGB_PKTBUF_SIZE
+#endif
+
+/* PCI BARs */
+
+#define IGB_MMIO_BAR 0
+#define IGB_FLASH_BAR 1
+#define IGB_IO_BAR 2
+#define IGB_MSIX_BAR 3
+
+/* For MSI-X we allocate all interrupts to MSI-X vector 0 */
+
+#define IGB_GPIE_MSIX_SINGLE (IGB_GPIE_NSICR | IGB_GPIE_EIAME | \
+ IGB_GPIE_PBASUPPORT)
+#define IGB_MSIX_IMS (IGB_IC_TXDW | IGB_IC_LSC | \
+ IGB_IC_RXMISS | IGB_IC_RXDW)
+#define IGB_MSIX_EIMS (IGB_EIMS_NOMSIX_OTHER | \
+ IGB_EIMS_NOMSIX_RXTX0)
+#define IGB_MSIX_IVAR0 (IGB_IVAR0_RXQ0_VAL | IGB_IVAR0_TXQ0_VAL)
+#define IGB_MSIX_IVARMSC (IGB_IVARMSC_OTHER_VAL)
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/* Extend default PCI devie type */
+
+struct igb_type_s
+{
+ uint32_t desc_align; /* Descriptor alignment */
+ uint32_t mta_regs; /* MTA registers */
+};
+
+/* IGB private data */
+
+struct igb_driver_s
+{
+ /* This holds the information visible to the NuttX network */
+
+ struct netdev_lowerhalf_s dev;
+ struct work_s work;
+
+ /* Packets list */
+
+ FAR netpkt_t **tx_pkt;
+ FAR netpkt_t **rx_pkt;
+
+ /* Descriptors */
+
+ FAR struct igb_tx_leg_s *tx;
+ FAR struct igb_rx_leg_s *rx;
+
+ size_t tx_now;
+ size_t tx_done;
+ size_t rx_now;
+
+ /* PCI data */
+
+ FAR struct pci_device_s *pcidev;
+ FAR const struct igb_type_s *type;
+ int irq;
+ uint64_t base;
+
+#ifdef CONFIG_NET_MCASTGROUP
+ /* MTA shadow */
+
+ FAR uint32_t *mta;
+#endif
+};
+
+/*****************************************************************************
+ * Private Functions Definitions
+ *****************************************************************************/
+
+/* Helpers */
+
+static uint32_t igb_getreg_mem(FAR struct igb_driver_s *priv,
+ unsigned int offset);
+static void igb_putreg_mem(FAR struct igb_driver_s *priv,
+ unsigned int offset,
+ uint32_t value);
+#ifdef CONFIG_DEBUG_NET_INFO
+static void igb_dump_reg(FAR struct igb_driver_s *priv,
+ FAR const char *msg, unsigned int offset);
+static void igb_dump_mem(FAR struct igb_driver_s *priv, FAR const char *msg);
+#endif
+
+/* Rings management */
+
+static void igb_txclean(FAR struct igb_driver_s *priv);
+static void igb_rxclean(FAR struct igb_driver_s *priv);
+
+/* Common TX logic */
+
+static int igb_transmit(FAR struct netdev_lowerhalf_s *dev,
+ FAR netpkt_t *pkt);
+
+/* Interrupt handling */
+
+static FAR netpkt_t *igb_receive(FAR struct netdev_lowerhalf_s *dev);
+static void igb_txdone(FAR struct netdev_lowerhalf_s *dev);
+
+static void igb_msix_interrupt(FAR struct igb_driver_s *priv);
+static int igb_interrupt(int irq, FAR void *context, FAR void *arg);
+
+/* NuttX callback functions */
+
+static int igb_ifup(FAR struct netdev_lowerhalf_s *dev);
+static int igb_ifdown(FAR struct netdev_lowerhalf_s *dev);
+
+#ifdef CONFIG_NET_MCASTGROUP
+static uint32_t igb_hashmta(FAR struct igb_driver_s *priv,
+ FAR const uint8_t *mac);
+static int igb_addmac(FAR struct netdev_lowerhalf_s *dev,
+ FAR const uint8_t *mac);
+static int igb_rmmac(FAR struct netdev_lowerhalf_s *dev,
+ FAR const uint8_t *mac);
+#endif
+
+/* Initialization */
+
+static void igb_disable(FAR struct igb_driver_s *priv);
+static void igb_enable(FAR struct igb_driver_s *priv);
+static int igb_initialize(FAR struct igb_driver_s *priv);
+static int igb_probe(FAR struct pci_device_s *dev);
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/* Intel 82576 (QEMU -device igb) */
+
+static const struct igb_type_s g_igb_82576 =
+{
+ .desc_align = 128,
+ .mta_regs = 128
+};
+
+/* Intel I211 */
+
+static const struct igb_type_s g_igb_i211 =
+{
+ .desc_align = 128,
+ .mta_regs = 128
+};
+
+static const struct pci_device_id_s g_igb_id_table[] =
+{
+ {
+ PCI_DEVICE(0x8086, 0x10c9),
+ .driver_data = (uintptr_t)&g_igb_82576
+ },
+
+ {
+ PCI_DEVICE(0x8086, 0x1539),
+ .driver_data = (uintptr_t)&g_igb_i211
+ },
+
+ {
+ PCI_DEVICE(0x8086, 0x1533),
+ .driver_data = (uintptr_t)&g_igb_i211
+ },
+ { }
+};
+
+static struct pci_driver_s g_pci_igb_drv =
+{
+ .id_table = g_igb_id_table,
+ .probe = igb_probe,
+};
+
+static const struct netdev_ops_s g_igb_ops =
+{
+ .ifup = igb_ifup,
+ .ifdown = igb_ifdown,
+ .transmit = igb_transmit,
+ .receive = igb_receive,
+#ifdef CONFIG_NET_MCASTGROUP
+ .addmac = igb_addmac,
+ .rmmac = igb_rmmac,
+#endif
+};
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: igb_getreg_mem
+ *****************************************************************************/
+
+static uint32_t igb_getreg_mem(FAR struct igb_driver_s *priv,
+ unsigned int offset)
+{
+ uintptr_t addr = priv->base + offset;
+ return *((FAR volatile uint32_t *)addr);
+}
+
+/*****************************************************************************
+ * Name: igb_putreg_mem
+ *****************************************************************************/
+
+static void igb_putreg_mem(FAR struct igb_driver_s *priv,
+ unsigned int offset,
+ uint32_t value)
+{
+ uintptr_t addr = priv->base + offset;
+ *((FAR volatile uint32_t *)addr) = value;
+}
+
+#ifdef CONFIG_DEBUG_NET_INFO
+/*****************************************************************************
+ * Name: igb_dump_reg
+ *****************************************************************************/
+
+static void igb_dump_reg(FAR struct igb_driver_s *priv,
+ FAR const char *msg, unsigned int offset)
+{
+ ninfo("\t%s:\t\t0x%" PRIx32 "\n", msg, igb_getreg_mem(priv, offset));
+}
+
+/*****************************************************************************
+ * Name: igb_dump_mem
+ *****************************************************************************/
+
+static void igb_dump_mem(FAR struct igb_driver_s *priv, FAR const char *msg)
+{
+ ninfo("\nDump: %s\n", msg);
+
+ ninfo("General registers:\n");
+ igb_dump_reg(priv, "CTRL", IGB_CTRL);
+ igb_dump_reg(priv, "STATUS", IGB_STATUS);
+ igb_dump_reg(priv, "CTRLEXT", IGB_CTRLEXT);
+ igb_dump_reg(priv, "MDIC", IGB_MDIC);
+ igb_dump_reg(priv, "SERDESCTL", IGB_SERDESCTL);
+ igb_dump_reg(priv, "FCAL", IGB_FCAL);
+ igb_dump_reg(priv, "FCAH", IGB_FCAH);
+ igb_dump_reg(priv, "FCT", IGB_FCT);
+ igb_dump_reg(priv, "CONNSW", IGB_CONNSW);
+ igb_dump_reg(priv, "VET", IGB_VET);
+ igb_dump_reg(priv, "FCTTV", IGB_FCTTV);
+
+ ninfo("Interrupt registers:\n");
+ igb_dump_reg(priv, "ICS", IGB_ICS);
+ igb_dump_reg(priv, "IMS", IGB_IMS);
+ igb_dump_reg(priv, "IAM", IGB_IAM);
+ igb_dump_reg(priv, "EICS", IGB_EICS);
+ igb_dump_reg(priv, "EIMS", IGB_EIMS);
+ igb_dump_reg(priv, "EIAM", IGB_EIAM);
+ igb_dump_reg(priv, "EIAC", IGB_EIAC);
+ igb_dump_reg(priv, "IVAR0", IGB_IVAR0);
+ igb_dump_reg(priv, "IVARMSC", IGB_IVARMSC);
+ igb_dump_reg(priv, "EITR0", IGB_EITR0);
+ igb_dump_reg(priv, "GPIE", IGB_GPIE);
+ igb_dump_reg(priv, "PBACL", IGB_PBACL);
+
+ ninfo("Receive registers:\n");
+ igb_dump_reg(priv, "RCTL", IGB_RCTL);
+ igb_dump_reg(priv, "PSRCTL", IGB_PSRCTL);
+ igb_dump_reg(priv, "FCRTL0", IGB_FCRTL0);
+ igb_dump_reg(priv, "FCRTH0", IGB_FCRTH0);
+ igb_dump_reg(priv, "RXPBSIZE", IGB_RXPBSIZE);
+ igb_dump_reg(priv, "FCRTV", IGB_FCRTV);
+ igb_dump_reg(priv, "RDBAL0", IGB_RDBAL0);
+ igb_dump_reg(priv, "RDBAH0", IGB_RDBAH0);
+ igb_dump_reg(priv, "RDLEN0", IGB_RDLEN0);
+ igb_dump_reg(priv, "SRRCTL0", IGB_SRRCTL0);
+ igb_dump_reg(priv, "RDH0", IGB_RDH0);
+ igb_dump_reg(priv, "RDT0", IGB_RDT0);
+ igb_dump_reg(priv, "RXDCTL0", IGB_RXDCTL0);
+ igb_dump_reg(priv, "RXCTL0", IGB_RXCTL0);
+ igb_dump_reg(priv, "RXCSUM", IGB_RXCSUM);
+ igb_dump_reg(priv, "RLPML", IGB_RLPML);
+ igb_dump_reg(priv, "RFCTL", IGB_RFCTL);
+ igb_dump_reg(priv, "MTA", IGB_MTA);
+ igb_dump_reg(priv, "RAL", IGB_RAL);
+ igb_dump_reg(priv, "RAH", IGB_RAH);
+
+ ninfo("Transmit registers:\n");
+ igb_dump_reg(priv, "TXPBSIZE", IGB_TXPBSIZE);
+ igb_dump_reg(priv, "PBTWAC", IGB_PBTWAC);
+ igb_dump_reg(priv, "TCTL", IGB_TCTL);
+ igb_dump_reg(priv, "TCTLEXT", IGB_TCTLEXT);
+ igb_dump_reg(priv, "TIPG", IGB_TIPG);
+ igb_dump_reg(priv, "RETXCTL", IGB_RETXCTL);
+ igb_dump_reg(priv, "DTXCTL", IGB_DTXCTL);
+ igb_dump_reg(priv, "TDBAL0", IGB_TDBAL0);
+ igb_dump_reg(priv, "TDBAH0", IGB_TDBAH0);
+ igb_dump_reg(priv, "TDLEN0", IGB_TDLEN0);
+ igb_dump_reg(priv, "TDH0", IGB_TDH0);
+ igb_dump_reg(priv, "TDT0", IGB_TDT0);
+ igb_dump_reg(priv, "TXDCTL0", IGB_TXDCTL0);
+ igb_dump_reg(priv, "TXCTL0", IGB_TXCTL0);
+ igb_dump_reg(priv, "TDWBAL0", IGB_TDWBAL0);
+ igb_dump_reg(priv, "TDWBAH0", IGB_TDWBAH0);
+
+ ninfo("Statistic registers:\n");
+ igb_dump_reg(priv, "CRCERRS", IGB_CRCERRS);
+ igb_dump_reg(priv, "ALGNERRC", IGB_ALGNERRC);
+ igb_dump_reg(priv, "RXERRC", IGB_RXERRC);
+ igb_dump_reg(priv, "MPC", IGB_MPC);
+ igb_dump_reg(priv, "SCC", IGB_SCC);
+ igb_dump_reg(priv, "ECOL", IGB_ECOL);
+ igb_dump_reg(priv, "MCC", IGB_MCC);
+ igb_dump_reg(priv, "LATECOL", IGB_LATECOL);
+ igb_dump_reg(priv, "COLC", IGB_COLC);
+ igb_dump_reg(priv, "DC", IGB_DC);
+ igb_dump_reg(priv, "TNCRS", IGB_TNCRS);
+ igb_dump_reg(priv, "RLEC", IGB_RLEC);
+ igb_dump_reg(priv, "XONRXC", IGB_XONRXC);
+ igb_dump_reg(priv, "XONTXC", IGB_XONTXC);
+ igb_dump_reg(priv, "XOFFRXC", IGB_XOFFRXC);
+ igb_dump_reg(priv, "XOFFTXC", IGB_XOFFTXC);
+ igb_dump_reg(priv, "FCRUC", IGB_FCRUC);
+ igb_dump_reg(priv, "PRC64", IGB_PRC64);
+ igb_dump_reg(priv, "PRC127", IGB_PRC127);
+ igb_dump_reg(priv, "PRC255", IGB_PRC255);
+ igb_dump_reg(priv, "PRC511", IGB_PRC511);
+ igb_dump_reg(priv, "PRC1023", IGB_PRC1023);
+ igb_dump_reg(priv, "PRC1522", IGB_PRC1522);
+ igb_dump_reg(priv, "GPRC", IGB_GPRC);
+ igb_dump_reg(priv, "BPRC", IGB_BPRC);
+ igb_dump_reg(priv, "MPRC", IGB_MPRC);
+ igb_dump_reg(priv, "GPTC", IGB_GPTC);
+ igb_dump_reg(priv, "GORCL", IGB_GORCL);
+ igb_dump_reg(priv, "GORCH", IGB_GORCH);
+ igb_dump_reg(priv, "GOTCL", IGB_GOTCL);
+ igb_dump_reg(priv, "GOTCH", IGB_GOTCH);
+ igb_dump_reg(priv, "RNBC", IGB_RNBC);
+ igb_dump_reg(priv, "RUC", IGB_RUC);
+ igb_dump_reg(priv, "RFC", IGB_RFC);
+ igb_dump_reg(priv, "ROC", IGB_ROC);
+ igb_dump_reg(priv, "RJC", IGB_RJC);
+ igb_dump_reg(priv, "MNGPRC", IGB_MNGPRC);
+ igb_dump_reg(priv, "MPDC", IGB_MPDC);
+ igb_dump_reg(priv, "TORL", IGB_TORL);
+ igb_dump_reg(priv, "TORH", IGB_TORH);
+ igb_dump_reg(priv, "TPR", IGB_TPR);
+ igb_dump_reg(priv, "TPT", IGB_TPT);
+ igb_dump_reg(priv, "PTC64", IGB_PTC64);
+ igb_dump_reg(priv, "PTC127", IGB_PTC127);
+ igb_dump_reg(priv, "PTC255", IGB_PTC255);
+ igb_dump_reg(priv, "PTC511", IGB_PTC511);
+ igb_dump_reg(priv, "PTC1023", IGB_PTC1023);
+ igb_dump_reg(priv, "PTC1522", IGB_PTC1522);
+ igb_dump_reg(priv, "BPTC", IGB_BPTC);
+ ninfo("Diagnostic registers:\n");
+ igb_dump_reg(priv, "RDFT", IGB_RDFT);
+ igb_dump_reg(priv, "RDFHS", IGB_RDFHS);
+ igb_dump_reg(priv, "RDFTS", IGB_RDFTS);
+ igb_dump_reg(priv, "RDFPC", IGB_RDFPC);
+ igb_dump_reg(priv, "RPBECCSTS", IGB_RPBECCSTS);
+ igb_dump_reg(priv, "TPBECCSTS", IGB_TPBECCSTS);
+ igb_dump_reg(priv, "FCSTS0", IGB_FCSTS0);
+ igb_dump_reg(priv, "RDHESTS", IGB_RDHESTS);
+ igb_dump_reg(priv, "TDHESTS", IGB_TDHESTS);
+ igb_dump_reg(priv, "TDFH", IGB_TDFH);
+ igb_dump_reg(priv, "TDFT", IGB_TDFT);
+ igb_dump_reg(priv, "TDFHS", IGB_TDFHS);
+ igb_dump_reg(priv, "TDFTS", IGB_TDFTS);
+ igb_dump_reg(priv, "TDFPC", IGB_TDFPC);
+ igb_dump_reg(priv, "TDHMP", IGB_TDHMP);
+ igb_dump_reg(priv, "CIRC", IGB_CIRC);
+ igb_dump_reg(priv, "TXBDC", IGB_TXBDC);
+ igb_dump_reg(priv, "TXIDLE", IGB_TXIDLE);
+ igb_dump_reg(priv, "RXBDC", IGB_RXBDC);
+ igb_dump_reg(priv, "RXIDLE", IGB_RXIDLE);
+}
+#endif
+
+/*****************************************************************************
+ * Name: igb_txclean
+ *
+ * Description:
+ * Clean transmission ring
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumption:
+ * This function can be called only after card reset and when TX is disabled
+ *
+ *****************************************************************************/
+
+static void igb_txclean(FAR struct igb_driver_s *priv)
+{
+ FAR struct netdev_lowerhalf_s *netdev = &priv->dev;
+
+ /* Reset ring */
+
+ igb_putreg_mem(priv, IGB_TDH0, 0);
+ igb_putreg_mem(priv, IGB_TDT0, 0);
+
+ /* Free any pending TX */
+
+ while (priv->tx_now != priv->tx_done)
+ {
+ /* Free net packet */
+
+ netpkt_free(netdev, priv->tx_pkt[priv->tx_done], NETPKT_TX);
+
+ /* Next descriptor */
+
+ priv->tx_done = (priv->tx_done + 1) % IGB_TX_DESC;
+ }
+
+ priv->tx_now = 0;
+ priv->tx_done = 0;
+}
+
+/*****************************************************************************
+ * Name: igb_rxclean
+ *
+ * Description:
+ * Clean receive ring
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumption:
+ * This function can be called only after card reset and when RX is disabled
+ *
+ *****************************************************************************/
+
+static void igb_rxclean(FAR struct igb_driver_s *priv)
+{
+ priv->rx_now = 0;
+
+ igb_putreg_mem(priv, IGB_RDH0, 0);
+ igb_putreg_mem(priv, IGB_RDT0, IGB_RX_DESC - 1);
+}
+
+/*****************************************************************************
+ * Name: igb_transmit
+ *
+ * Description:
+ * Start hardware transmission. Called either from the txdone interrupt
+ * handling or from watchdog based polling.
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ *****************************************************************************/
+
+static int igb_transmit(FAR struct netdev_lowerhalf_s *dev,
+ FAR netpkt_t *pkt)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ uint64_t pa = 0;
+ int desc = priv->tx_now;
+ size_t len = netpkt_getdatalen(dev, pkt);
+ size_t tx_next = (priv->tx_now + 1) % IGB_TX_DESC;
+
+ ninfo("transmit\n");
+
+ /* Check the send length */
+
+ if (len > IGB_PKTBUF_SIZE)
+ {
+ nerr("net transmit buffer too large\n");
+ return -EINVAL;
+ }
+
+ if (!IFF_IS_RUNNING(dev->netdev.d_flags))
+ {
+ return -ENETDOWN;
+ }
+
+ /* Drop packet if ring full */
+
+ if (tx_next == priv->tx_done)
+ {
+ return -ENOMEM;
+ }
+
+ /* Store TX packet reference */
+
+ priv->tx_pkt[priv->tx_now] = pkt;
+
+ /* Prepare next TX descriptor */
+
+ priv->tx_now = tx_next;
+
+ /* Setup TX descriptor */
+
+ pa = up_addrenv_va_to_pa(netpkt_getdata(dev, pkt));
+
+ priv->tx[desc].addr = pa;
+ priv->tx[desc].len = len;
+ priv->tx[desc].cmd = (IGB_TDESC_CMD_EOP | IGB_TDESC_CMD_IFCS |
+ IGB_TDESC_CMD_RS);
+ priv->tx[desc].cso = 0;
+ priv->tx[desc].status = 0;
+
+ UP_DSB();
+
+ /* Update TX tail */
+
+ igb_putreg_mem(priv, IGB_TDT0, priv->tx_now);
+
+ ninfodumpbuffer("Transmitted:", netpkt_getdata(dev, pkt), len);
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: igb_receive
+ *
+ * Description:
+ * An interrupt was received indicating the availability of a new RX packet
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ *****************************************************************************/
+
+static FAR netpkt_t *igb_receive(FAR struct netdev_lowerhalf_s *dev)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ FAR netpkt_t *pkt = NULL;
+ FAR struct igb_rx_leg_s *rx = NULL;
+ int desc = 0;
+
+ desc = priv->rx_now;
+
+ /* Get RX descriptor and RX packet */
+
+ rx = &priv->rx[desc];
+ pkt = priv->rx_pkt[desc];
+
+ /* Check if descriptor done */
+
+ if (!(rx->status & IGB_RDESC_STATUS_DD))
+ {
+ return NULL;
+ }
+
+ /* Next descriptor */
+
+ priv->rx_now = (priv->rx_now + 1) % IGB_RX_DESC;
+
+ /* Allocate new rx packet */
+
+ priv->rx_pkt[desc] = netpkt_alloc(dev, NETPKT_RX);
+ if (priv->rx_pkt[desc] == NULL)
+ {
+ nerr("alloc pkt_new failed\n");
+ PANIC();
+ }
+
+ /* Set packet length */
+
+ netpkt_setdatalen(dev, pkt, rx->len);
+
+ /* Store new packet in RX descriptor ring */
+
+ rx->addr = up_addrenv_va_to_pa(
+ netpkt_getdata(dev, priv->rx_pkt[desc]));
+ rx->len = 0;
+ rx->status = 0;
+
+ /* Update RX tail */
+
+ igb_putreg_mem(priv, IGB_RDT0, desc);
+
+ /* Handle errors */
+
+ if (rx->errors)
+ {
+ nerr("RX error reported (%"PRIu8")\n", rx->errors);
+ NETDEV_RXERRORS(&priv->dev.netdev);
+ netpkt_free(dev, pkt, NETPKT_RX);
+ return NULL;
+ }
+
+ return pkt;
+}
+
+/*****************************************************************************
+ * Name: igb_txdone
+ *
+ * Description:
+ * An interrupt was received indicating that the last TX packet(s) is done
+ *
+ * Input Parameters:
+ * priv - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ *****************************************************************************/
+
+static void igb_txdone(FAR struct netdev_lowerhalf_s *dev)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+
+ while (priv->tx_now != priv->tx_done)
+ {
+ if (priv->tx[priv->tx_done].status == 0)
+ {
+ break;
+ }
+
+ if (!(priv->tx[priv->tx_done].status & IGB_TDESC_STATUS_DD))
+ {
+ nerr("tx failed: 0x%" PRIx32 "\n", priv->tx[priv->tx_done].status);
+ NETDEV_TXERRORS(&priv->dev.netdev);
+ }
+
+ /* Free net packet */
+
+ netpkt_free(dev, priv->tx_pkt[priv->tx_done], NETPKT_TX);
+
+ /* Next descriptor */
+
+ priv->tx_done = (priv->tx_done + 1) % IGB_TX_DESC;
+ }
+
+ netdev_lower_txdone(dev);
+}
+
+/*****************************************************************************
+ * Name: igb_link_work
+ *
+ * Description:
+ * Handle link status change.
+ *
+ * Input Parameters:
+ * arg - Reference to the lover half driver structure (cast to void *)
+ *
+ * Returned Value:
+ * None
+ *
+ *****************************************************************************/
+
+static void igb_link_work(FAR void *arg)
+{
+ FAR struct igb_driver_s *priv = arg;
+ uint32_t tmp;
+
+ tmp = igb_getreg_mem(priv, IGB_STATUS);
+ if (tmp & IGB_STATUS_LU)
+ {
+ ninfo("Link up, status = 0x%x\n", tmp);
+
+ netdev_lower_carrier_on(&priv->dev);
+ }
+ else
+ {
+ ninfo("Link down\n");
+
+ netdev_lower_carrier_off(&priv->dev);
+ }
+}
+
+/*****************************************************************************
+ * Name: igb_misx_interrupt
+ *
+ * Description:
+ * Perform MSI-X interrupt work
+ *
+ * Input Parameters:
+ * arg - The argument passed when work_queue() was called.
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ * Runs on a worker thread.
+ *
+ *****************************************************************************/
+
+static void igb_msix_interrupt(FAR struct igb_driver_s *priv)
+{
+ uint32_t icr = 0;
+ uint32_t eicr = 0;
+
+ /* Get interrupts */
+
+ icr = igb_getreg_mem(priv, IGB_ICR);
+ eicr = igb_getreg_mem(priv, IGB_EICR);
+
+ ninfo("eicr = 0x%" PRIx32 " icr = 0x%" PRIx32 "\n", eicr, icr);
+
+ if (icr == 0)
+ {
+ /* Ignore spurious interrupts */
+
+ return;
+ }
+
+ /* Receiver Descriptor Write Back */
+
+ if (icr & IGB_IC_RXDW)
+ {
+ netdev_lower_rxready(&priv->dev);
+ }
+
+ /* Link Status Change */
+
+ if (icr & IGB_IC_LSC)
+ {
+ if (work_available(&priv->work))
+ {
+ /* Schedule to work queue because netdev_lower_carrier_xxx API
+ * can't be used in interrupt context
+ */
+
+ work_queue(LPWORK, &priv->work, igb_link_work, priv, 0);
+ }
+ }
+
+ /* Receiver Miss */
+
+ if (icr & IGB_IC_RXMISS)
+ {
+ nerr("Receiver Miss\n");
+ netdev_lower_rxready(&priv->dev);
+ }
+
+ /* Transmit Descriptor Written Back */
+
+ if (icr & IGB_IC_TXDW)
+ {
+ igb_txdone(&priv->dev);
+ }
+}
+
+/*****************************************************************************
+ * Name: igb_interrupt
+ *
+ * Description:
+ * Hardware interrupt handler
+ *
+ * Input Parameters:
+ * irq - Number of the IRQ that generated the interrupt
+ * context - Interrupt register state save info (architecture-specific)
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ * Runs in the context of a the Ethernet interrupt handler. Local
+ * interrupts are disabled by the interrupt logic.
+ *
+ *****************************************************************************/
+
+static int igb_interrupt(int irq, FAR void *context, FAR void *arg)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)arg;
+
+ DEBUGASSERT(priv != NULL);
+
+ ninfo("interrupt!\n");
+
+ /* Schedule to perform the interrupt processing on the worker thread. */
+
+ igb_msix_interrupt(priv);
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: igb_ifup
+ *
+ * Description:
+ * NuttX Callback: Bring up the Ethernet interface when an IP address is
+ * provided
+ *
+ * Input Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ *****************************************************************************/
+
+static int igb_ifup(FAR struct netdev_lowerhalf_s *dev)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ irqstate_t flags;
+
+#ifdef CONFIG_NET_IPv4
+ ninfo("Bringing up: %u.%u.%u.%u\n",
+ ip4_addr1(dev->netdev.d_ipaddr), ip4_addr2(dev->netdev.d_ipaddr),
+ ip4_addr3(dev->netdev.d_ipaddr), ip4_addr4(dev->netdev.d_ipaddr));
+#endif
+
+#ifdef CONFIG_NET_IPv6
+ ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ dev->netdev.d_ipv6addr[0], dev->netdev.d_ipv6addr[1],
+ dev->netdev.d_ipv6addr[2], dev->netdev.d_ipv6addr[3],
+ dev->netdev.d_ipv6addr[4], dev->netdev.d_ipv6addr[5],
+ dev->netdev.d_ipv6addr[6], dev->netdev.d_ipv6addr[7]);
+#endif
+
+ flags = enter_critical_section();
+
+ /* Enable the Ethernet */
+
+ igb_enable(priv);
+ leave_critical_section(flags);
+
+ /* Update link status in case link status interrupt is missing */
+
+ igb_link_work(priv);
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: igb_ifdown
+ *
+ * Description:
+ * NuttX Callback: Stop the interface.
+ *
+ * Input Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ *****************************************************************************/
+
+static int igb_ifdown(FAR struct netdev_lowerhalf_s *dev)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ /* Put the EMAC in its reset, non-operational state. This should be
+ * a known configuration that will guarantee the igb_ifup() always
+ * successfully brings the interface back up.
+ */
+
+ igb_disable(priv);
+ leave_critical_section(flags);
+ return OK;
+}
+
+#ifdef CONFIG_NET_MCASTGROUP
+/*****************************************************************************
+ * Name: igb_hashmta
+ *
+ * Note: This logic is based on freeBSD igb implementation
+ *
+ *****************************************************************************/
+
+static uint32_t igb_hashmta(FAR struct igb_driver_s *priv,
+ FAR const uint8_t *mac)
+{
+ uint32_t hash_mask = 0;
+ uint8_t bit_shift = 0;
+
+ /* Register count multiplied by bits per register */
+
+ hash_mask = (priv->type->mta_regs * 32) - 1;
+
+/* For a mc_filter_type of 0, bit_shift is the number of left-shifts
+ * where 0xFF would still fall within the hash mask.
+ */
+
+ while (hash_mask >> bit_shift != 0xff)
+ {
+ bit_shift++;
+ }
+
+ /* bit_shift += 0 because we have MO set to 0 */
+
+ return hash_mask & ((mac[4] >> (8 - bit_shift)) | (mac[5] << bit_shift));
+}
+
+/*****************************************************************************
+ * Name: igb_addmac
+ *
+ * Description:
+ * NuttX Callback: Add the specified MAC address to the hardware multicast
+ * address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be added
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ *****************************************************************************/
+
+static int igb_addmac(FAR struct netdev_lowerhalf_s *dev,
+ FAR const uint8_t *mac)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ uint16_t hash = 0;
+ uint8_t row = 0;
+ uint8_t bit = 0;
+ int i = 0;
+
+ hash = igb_hashmta(priv, mac);
+ bit = hash & 31;
+ row = (hash >> 5) & (priv->type->mta_regs - 1);
+
+ /* Bits 4:0 indicate bit in row word */
+
+ priv->mta[row] |= (1 << bit);
+
+ /* Replace the entire MTA */
+
+ for (i = priv->type->mta_regs - 1; i >= 0; i--)
+ {
+ igb_putreg_mem(priv, IGB_MTA + (i << 2), priv->mta[i]);
+ }
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: igb_rmmac
+ *
+ * Description:
+ * NuttX Callback: Remove the specified MAC address from the hardware
+ * multicast address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be removed
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ *****************************************************************************/
+
+static int igb_rmmac(FAR struct netdev_lowerhalf_s *dev,
+ FAR const uint8_t *mac)
+{
+ FAR struct igb_driver_s *priv = (FAR struct igb_driver_s *)dev;
+ uint16_t hash = 0;
+ uint8_t row = 0;
+ uint8_t bit = 0;
+ int i = 0;
+
+ hash = igb_hashmta(priv, mac);
+ bit = hash & 31;
+ row = (hash >> 5) & (priv->type->mta_regs - 1);
+
+ /* Bits 4:0 indicate bit in row word */
+
+ priv->mta[row] &= ~(1 << bit);
+
+ /* Replace the entire MTA */
+
+ for (i = priv->type->mta_regs - 1; i >= 0; i--)
+ {
+ igb_putreg_mem(priv, IGB_MTA + (i << 2), priv->mta[i]);
+ }
+
+ return OK;
+}
+#endif /* CONFIG_NET_MCASTGROUP */
+
+/*****************************************************************************
+ * Name: igb_disable
+ *
+ * Description:
+ * Reset device to known state.
+ *
+ *****************************************************************************/
+
+static void igb_disable(FAR struct igb_driver_s *priv)
+{
+ uint32_t regval;
+ int i = 0;
+
+ /* Disable interrupts */
+
+ igb_putreg_mem(priv, IGB_EIMC, IGB_MSIX_EIMS);
+ igb_putreg_mem(priv, IGB_IMC, IGB_MSIX_IMS);
+ up_disable_irq(priv->irq);
+
+ /* Disable Transmitter */
+
+ regval = igb_getreg_mem(priv, IGB_TCTL);
+ regval &= ~IGB_TCTL_EN;
+ igb_putreg_mem(priv, IGB_TCTL, regval);
+
+ /* Disable Receiver */
+
+ igb_putreg_mem(priv, IGB_RCTL, 0);
+
+ /* We have to reset device, otherwise writing to RDH and THD corrupts
+ * the device state.
+ */
+
+ igb_putreg_mem(priv, IGB_CTRL, IGB_CTRL_RST);
+
+ /* Reset Tx tail */
+
+ igb_txclean(priv);
+
+ /* Reset Rx tail */
+
+ igb_rxclean(priv);
+
+ /* Free RX packets */
+
+ for (i = 0; i < IGB_RX_DESC; i += 1)
+ {
+ netpkt_free(&priv->dev, priv->rx_pkt[i], NETPKT_RX);
+ }
+}
+
+/*****************************************************************************
+ * Name: igb_phy_reset
+ *
+ * Description:
+ * Reset PHY
+ *
+ *****************************************************************************/
+
+static void igb_phy_reset(FAR struct igb_driver_s *priv)
+{
+ uint32_t regval = 0;
+
+ regval = igb_getreg_mem(priv, IGB_CTRL);
+ igb_putreg_mem(priv, IGB_CTRL, regval | IGB_CTRL_PHYRST);
+ up_udelay(100);
+ igb_putreg_mem(priv, IGB_CTRL, regval);
+ up_udelay(100);
+}
+
+/*****************************************************************************
+ * Name: igb_enable
+ *
+ * Description:
+ * Enable device.
+ *
+ *****************************************************************************/
+
+static void igb_enable(FAR struct igb_driver_s *priv)
+{
+ FAR struct netdev_lowerhalf_s *dev = (FAR struct netdev_lowerhalf_s *)priv;
+ uint64_t pa = 0;
+ uint32_t regval = 0;
+ int i = 0;
+
+ /* Reset PHY */
+
+ igb_phy_reset(priv);
+
+ /* Reset Multicast Table Array */
+
+ for (i = 0; i < priv->type->mta_regs; i++)
+ {
+ igb_putreg_mem(priv, IGB_MTA + (i << 2), 0);
+ }
+
+ /* Allocate RX packets */
+
+ for (i = 0; i < IGB_RX_DESC; i += 1)
+ {
+ priv->rx_pkt[i] = netpkt_alloc(dev, NETPKT_RX);
+ if (priv->rx_pkt[i] == NULL)
+ {
+ nerr("alloc rx_pkt failed\n");
+ PANIC();
+ }
+
+ /* Configure RX descriptor */
+
+ priv->rx[i].addr = up_addrenv_va_to_pa(
+ netpkt_getdata(dev, priv->rx_pkt[i]));
+ priv->rx[i].len = 0;
+ priv->rx[i].status = 0;
+ }
+
+ /* Setup TX descriptor */
+
+ /* The address passed to the NIC must be physical */
+
+ pa = up_addrenv_va_to_pa(priv->tx);
+
+ regval = (uint32_t)pa;
+ igb_putreg_mem(priv, IGB_TDBAL0, regval);
+ regval = (uint32_t)(pa >> 32);
+ igb_putreg_mem(priv, IGB_TDBAH0, regval);
+
+ regval = IGB_TX_DESC * sizeof(struct igb_tx_leg_s);
+ igb_putreg_mem(priv, IGB_TDLEN0, regval);
+
+ /* Reset TX tail */
+
+ igb_txclean(priv);
+
+ /* Setup RX descriptor */
+
+ /* The address passed to the NIC must be physical */
+
+ pa = up_addrenv_va_to_pa(priv->rx);
+
+ regval = (uint32_t)pa;
+ igb_putreg_mem(priv, IGB_RDBAL0, regval);
+ regval = (uint32_t)(pa >> 32);
+ igb_putreg_mem(priv, IGB_RDBAH0, regval);
+
+ regval = IGB_RX_DESC * sizeof(struct igb_rx_leg_s);
+ igb_putreg_mem(priv, IGB_RDLEN0, regval);
+
+ /* Enable interrupts */
+
+ igb_putreg_mem(priv, IGB_EIMS, IGB_MSIX_EIMS);
+ igb_putreg_mem(priv, IGB_IMS, IGB_MSIX_IMS);
+ up_enable_irq(priv->irq);
+
+ /* Set link up */
+
+ igb_putreg_mem(priv, IGB_CTRL, IGB_CTRL_SLU);
+
+ /* Setup and enable Transmitter */
+
+ regval = igb_getreg_mem(priv, IGB_TCTL);
+ regval |= IGB_TCTL_EN | IGB_TCTL_PSP;
+ igb_putreg_mem(priv, IGB_TCTL, regval);
+
+ /* Setup and enable Receiver */
+
+ regval = (IGB_RCTL_EN | IGB_RCTL_MPE |
+ (IGB_RCTL_BSIZE << IGB_RCTL_BSIZE_SHIFT));
+#ifdef CONFIG_NET_PROMISCUOUS
+ regval |= IGB_RCTL_UPE | IGB_RCTL_MPE;
+#endif
+ igb_putreg_mem(priv, IGB_RCTL, regval);
+
+ /* Enable TX queeu */
+
+ regval = igb_getreg_mem(priv, IGB_TXDCTL0);
+ regval |= IGB_TXDCTL_ENABLE;
+ igb_putreg_mem(priv, IGB_TXDCTL0, regval);
+
+ /* Enable RX queue */
+
+ regval = igb_getreg_mem(priv, IGB_RXDCTL0);
+ regval |= IGB_RXDCTL_ENABLE;
+ igb_putreg_mem(priv, IGB_RXDCTL0, regval);
+
+ /* Reset RX tail - after queue is enabled */
+
+ igb_rxclean(priv);
+
+#ifdef CONFIG_DEBUG_NET_INFO
+ /* Dump memory */
+
+ igb_dump_mem(priv, "enabled");
+#endif
+}
+
+/*****************************************************************************
+ * Name: igb_initialize
+ *
+ * Description:
+ * Initialize device
+ *
+ *****************************************************************************/
+
+static int igb_initialize(FAR struct igb_driver_s *priv)
+{
+ uint32_t regval = 0;
+ uint64_t mac = 0;
+ int ret = OK;
+
+ /* Allocate MSI */
+
+ ret = pci_alloc_irq(priv->pcidev, &priv->irq, 1);
+ if (ret != 1)
+ {
+ nerr("Failed to allocate MSI %d\n", ret);
+ return ret;
+ }
+
+ /* Attach IRQ */
+
+ irq_attach(priv->irq, igb_interrupt, priv);
+
+ /* Connect MSI */
+
+ ret = pci_connect_irq(priv->pcidev, &priv->irq, 1);
+ if (ret != OK)
+ {
+ nerr("Failed to connect MSI %d\n", ret);
+ pci_release_irq(priv->pcidev, &priv->irq, 1);
+
+ return -ENOTSUP;
+ }
+
+ /* Clear previous Extended Interrupt Mask */
+
+ igb_putreg_mem(priv, IGB_EIMC, 0xffffffff);
+ igb_putreg_mem(priv, IGB_IMC, 0xffffffff);
+
+ /* Configure MSI-X */
+
+ igb_putreg_mem(priv, IGB_IVAR0, IGB_MSIX_IVAR0);
+ igb_putreg_mem(priv, IGB_IVARMSC, IGB_MSIX_IVARMSC);
+
+ /* Enable MSI-X Single Vector */
+
+ igb_putreg_mem(priv, IGB_GPIE, IGB_GPIE_MSIX_SINGLE);
+ igb_putreg_mem(priv, IGB_EIMS, IGB_MSIX_EIMS);
+
+ /* Configure Other causes */
+
+ igb_putreg_mem(priv, IGB_IMS, IGB_MSIX_IMS);
+
+ /* Configure Interrupt Throttle */
+
+ igb_putreg_mem(priv, IGB_EITR0, (CONFIG_NET_IGB_INT_INTERVAL << 2));
+
+ /* Get MAC if valid */
+
+ regval = igb_getreg_mem(priv, IGB_RAH);
+ if (regval & IGB_RAH_AV)
+ {
+ mac = ((uint64_t)regval & IGB_RAH_RAH_MASK) << 32;
+ mac |= igb_getreg_mem(priv, IGB_RAL);
+ memcpy(&priv->dev.netdev.d_mac.ether, &mac, sizeof(struct ether_addr));
+ }
+ else
+ {
+ nwarn("Receive Address not valid!\n");
+ }
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: igb_probe
+ *
+ * Description:
+ * Initialize device
+ *
+ *****************************************************************************/
+
+static int igb_probe(FAR struct pci_device_s *dev)
+{
+ FAR const struct igb_type_s *type = NULL;
+ FAR struct igb_driver_s *priv = NULL;
+ FAR struct netdev_lowerhalf_s *netdev = NULL;
+ int ret = -ENOMEM;
+
+ /* Get type data associated with this PCI device card */
+
+ type = (FAR const struct igb_type_s *)dev->id->driver_data;
+
+ /* Not found private data */
+
+ if (type == NULL)
+ {
+ return -ENODEV;
+ }
+
+ /* Allocate the interface structure */
+
+ priv = kmm_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ {
+ return ret;
+ }
+
+ priv->pcidev = dev;
+
+ /* Allocate TX descriptors */
+
+ priv->tx = kmm_memalign(type->desc_align,
+ IGB_TX_DESC * sizeof(struct igb_tx_leg_s));
+ if (priv->tx == NULL)
+ {
+ nerr("alloc tx failed %d\n", errno);
+ goto errout;
+ }
+
+ /* Allocate RX descriptors */
+
+ priv->rx = kmm_memalign(type->desc_align,
+ IGB_RX_DESC * sizeof(struct igb_rx_leg_s));
+ if (priv->rx == NULL)
+ {
+ nerr("alloc rx failed %d\n", errno);
+ goto errout;
+ }
+
+ /* Allocate TX packet pointer array */
+
+ priv->tx_pkt = kmm_zalloc(IGB_TX_DESC * sizeof(netpkt_t *));
+ if (priv->tx_pkt == NULL)
+ {
+ nerr("alloc tx_pkt failed\n");
+ goto errout;
+ }
+
+ /* Allocate RX packet pointer array */
+
+ priv->rx_pkt = kmm_zalloc(IGB_RX_DESC * sizeof(netpkt_t *));
+ if (priv->rx_pkt == NULL)
+ {
+ nerr("alloc rx_pkt failed\n");
+ goto errout;
+ }
+
+#ifdef CONFIG_NET_MCASTGROUP
+ /* Allocate MTA shadow */
+
+ priv->mta = kmm_zalloc(type->mta_regs);
+ if (priv->mta == NULL)
+ {
+ nerr("alloc mta failed\n");
+ goto errout;
+ }
+#endif
+
+ /* Get devices */
+
+ netdev = &priv->dev;
+ priv->type = type;
+
+ pci_set_master(dev);
+ pciinfo("Enabled bus mastering\n");
+ pci_enable_device(dev);
+ pciinfo("Enabled memory resources\n");
+
+ /* If the BAR is MMIO then it must be mapped */
+
+ priv->base = (uintptr_t)pci_map_bar(dev, IGB_MMIO_BAR);
+ if (!priv->base)
+ {
+ pcierr("Not found MMIO control bar\n");
+ goto errout;
+ }
+
+ /* Initialize PHYs, Ethernet interface, and setup up Ethernet interrupts */
+
+ ret = igb_initialize(priv);
+ if (ret != OK)
+ {
+ nerr("igb_initialize failed %d\n", ret);
+ return ret;
+ }
+
+ /* Register the network device */
+
+ netdev->quota[NETPKT_TX] = IGB_TX_QUOTA;
+ netdev->quota[NETPKT_RX] = IGB_RX_QUOTA;
+ netdev->ops = &g_igb_ops;
+
+ return netdev_lower_register(netdev, NET_LL_ETHERNET);
+
+errout:
+ kmm_free(priv->tx);
+ kmm_free(priv->rx);
+#ifdef CONFIG_NET_MCASTGROUP
+ kmm_free(priv->mta);
+#endif
+ kmm_free(priv);
+ return ret;
+}
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: pci_igb_init
+ *
+ * Description:
+ * Register a pci driver
+ *
+ *****************************************************************************/
+
+int pci_igb_init(void)
+{
+ return pci_register_driver(&g_pci_igb_drv);
+}
diff --git a/drivers/net/igb.h b/drivers/net/igb.h
new file mode 100644
index 00000000000..e281fd5ad3c
--- /dev/null
+++ b/drivers/net/igb.h
@@ -0,0 +1,544 @@
+/*****************************************************************************
+ * drivers/net/igb.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ *****************************************************************************/
+
+#ifndef __DRIVERS_NET_IGB_H
+#define __DRIVERS_NET_IGB_H
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <stdint.h>
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/* General registers */
+
+#define IGB_CTRL (0x0000) /* Device Control Register */
+#define IGB_STATUS (0x0008) /* Device Status Register */
+#define IGB_CTRLEXT (0x0018) /* Extended Device Control
Register */
+#define IGB_MDIC (0x0020) /* MDI Control Register */
+#define IGB_SERDESCTL (0x0024) /* Serdes_ana */
+#define IGB_FCAL (0x0028) /* Flow Control Address Low */
+#define IGB_FCAH (0x002c) /* Flow Control Address High */
+#define IGB_FCT (0x0030) /* Flow Control Type */
+#define IGB_CONNSW (0x0034) /* Copper/Fiber Switch Control */
+#define IGB_VET (0x0038) /* VLAN Ether Type */
+#define IGB_FCTTV (0x0170) /* Flow Control Transmit Timer
Value */
+#define IGB_LEDCTL (0x0e00) /* LED Control */
+#define IGB_I2CCM (0x1028) /* SFP I2C Command */
+#define IGB_I2CPARAMS (0x102c) /* SFP I2C Parameter */
+#define IGB_WDSTP (0x1040) /* Watchdog Setup Register */
+#define IGB_WDSWSTS (0x1044) /* Watchdog Software */
+#define IGB_FRTIMER (0x1048) /* Free Running Timer */
+#define IGB_TCPTIMER (0x104c) /* TCP Timer */
+#define IGB_DCAID (0x5b70) /* DCA Requester ID Information
Register */
+#define IGB_SWSM (0x5b50) /* Software Semaphore Register */
+#define IGB_FWSM (0x5b54) /* Firmware Semaphore Register */
+#define IGB_SWFWSYNC (0x5b5c) /* Software-Firmware
Synchronization */
+
+/* Flash/EEPROM Registers */
+
+#define IGB_EEC (0x00010) /* EEPROM/FLASH Control Register
*/
+#define IGB_EERD (0x00014) /* EEPROM Read Register */
+#define IGB_FLA (0x0001c) /* Flash Access Register */
+#define IGB_EEMNGCTL (0x01010) /* MNG EEPROM Control Register */
+#define IGB_EEMNGDATA (0x01014) /* MNG EEPROM Read/Write data */
+#define IGB_FLMNGCTL (0x01018) /* MNG Flash Control Register */
+#define IGB_FLMNGDATA (0x0101c) /* MNG Flash Read data */
+#define IGB_FLMNGCNT (0x01020) /* MNG Flash Read Counter */
+#define IGB_EEARBC (0x01024) /* EEPROM Auto Read Bus Control */
+#define IGB_FLASHOP (0x0103c) /* Flash Opcode Register */
+#define IGB_EEDIAG (0x01038) /* EEPROM Diagnostic */
+#define IGB_VPDDIAG (0x01060) /* VPD Diagnostic */
+
+/* Interrupt registers */
+
+#define IGB_ICR (0x1500) /* Interrupt Cause Read */
+#define IGB_ICS (0x1504) /* Interrupt Cause Set */
+#define IGB_IMS (0x1508) /* Interrupt Mask Set */
+#define IGB_IMC (0x150c) /* Interrupt Mask Clear */
+#define IGB_IAM (0x1510) /* Interrupt Acknowledge
Auto–Mask */
+#define IGB_EICS (0x1520) /* Extended Interrupt Cause Set */
+#define IGB_EIMS (0x1524) /* Extended Interrupt Mask
Set/Read */
+#define IGB_EIMC (0x1528) /* Extended Interrupt Mask Clear
*/
+#define IGB_EIAC (0x152c) /* Extended Interrupt Auto Clear
*/
+#define IGB_EIAM (0x1530) /* Extended Interrupt Auto Mask */
+#define IGB_EICR (0x1580) /* Extended Interrupt Cause Read
*/
+#define IGB_IVAR0 (0x1700) /* Interrupt Vector Allocation
Registers */
+#define IGB_IVARMSC (0x1740) /* Interrupt Vector Allocation
Registers - MISC */
+#define IGB_EITR0 (0x1680) /* Extended Interrupt Throttling
Rate 0 - 24 */
+#define IGB_GPIE (0x1514) /* General Purpose Interrupt
Enable */
+#define IGB_PBACL (0x5b68) /* MSI-X PBA Clear */
+
+/* Receive registers */
+
+#define IGB_RCTL (0x0100) /* Receive Control */
+#define IGB_FCRTL0 (0x2160) /* Flow Control Receive Threshold
Low */
+#define IGB_PSRCTL (0x2170) /* Packet Split Receive Control
Register */
+#define IGB_FCRTH0 (0x2168) /* Flow Control Receive Threshold
High */
+#define IGB_RXPBSIZE (0x2404) /* Rx Packet Buffer Size */
+#define IGB_PBRWAC (0x24e8) /* Rx Packet Buffer wrap around
counter */
+#define IGB_FCRTV (0x2460) /* Flow Control Refresh Threshold
Value */
+#define IGB_DRXMXOD (0x2540) /* DMA RX Max Total Allow Size
Requests */
+#define IGB_RDBAL0 (0xc000) /* Tx Descriptor Base Address Low
*/
+#define IGB_RDBAH0 (0xc004) /* Rx Descriptor Base Address
High */
+#define IGB_RDLEN0 (0xc008) /* Rx Descriptor Length */
+#define IGB_SRRCTL0 (0xc00c) /* Split and Replication Receive
Control Register Queue */
+#define IGB_RDH0 (0xc010) /* Rx Descriptor Head */
+#define IGB_RDT0 (0xc018) /* Rx Descriptor Tail */
+#define IGB_RXDCTL0 (0xc028) /* Receive Descriptor Control
Queue */
+#define IGB_RXCTL0 (0xc014) /* Receive Queue DCA CTRL
Register */
+#define IGB_RXCSUM (0x5000) /* Receive Checksum Control */
+#define IGB_RLPML (0x5004) /* Receive Long packet maximal
length */
+#define IGB_RFCTL (0x5008) /* Receive Filter Control
Register */
+#define IGB_MTA (0x5200) /* Multicast Table Array (n) */
+#define IGB_RAL (0x5400) /* Receive Address Low */
+#define IGB_RAH (0x5404) /* Receive Address Low */
+#define IGB_PSRTYPE0 (0x5480) /* Packet Split Receive type (n)
*/
+#define IGB_RPLPSRTYPE (0x54c0) /* Replicated Packet Split
Receive type */
+#define IGB_VTCTL (0x5818) /* Next Generation VMDq Control
register */
+#define IGB_VFTA0 (0x5600) /* VLAN Filter Table Array (n) */
+#define IGB_MRQC (0x5818) /* Multiple Receive Queues
Command */
+#define IGB_RETA (0x5c00) /* Redirection Table */
+#define IGB_RSSRK (0x5c80) /* RSS Random Key Register */
+
+/* Transmit registers */
+
+#define IGB_TXPBSIZE (0x3404) /* Transmit Packet Buffer Size */
+#define IGB_PBTWAC (0x34e8) /* Tx Packet Buffer wrap around
counter */
+#define IGB_TCTL (0x0400) /* Transmit Control */
+#define IGB_TCTLEXT (0x0404) /* Transmit Control Extended */
+#define IGB_TIPG (0x0410) /* Transmit IPG Register */
+#define IGB_RETXCTL (0x041c) /* Retry Buffer Control */
+#define IGB_DTXCTL (0x3590) /* DMA Tx Control */
+#define IGB_DTXTCPFLGL (0x359c) /* DMA Tx TCP Flags Control Low */
+#define IGB_DTXTCPFLGH (0x35a0) /* DMA Tx TCP Flags Control High
*/
+#define IGB_DTXMXSZRQ (0x3540) /* DMA Tx Max Total Allow Size
Requests */
+#define IGB_DTXMXPKTSZ (0x355c) /* DMA Tx Max Allowable Packet
Size */
+#define IGB_TDBAL0 (0xe000) /* Tx Descriptor Base Low */
+#define IGB_TDBAH0 (0xe004) /* Tx Descriptor Base High*/
+#define IGB_TDLEN0 (0xe008) /* Tx Descriptor Ring Length */
+#define IGB_TDH0 (0xe010) /* Tx Descriptor Head */
+#define IGB_TDT0 (0xe018) /* Tx Descriptor Tail */
+#define IGB_TXDCTL0 (0xe028) /* Transmit Descriptor Control
Queue */
+#define IGB_TXCTL0 (0xe014) /* Tx DCA CTRL Register Queue */
+#define IGB_TDWBAL0 (0xe038) /* Transmit Descriptor WB Address
Low Queue */
+#define IGB_TDWBAH0 (0xe03c) /* Transmit Descriptor WB Address
High Queue */
+
+/* TODO: Filters */
+
+#define IGB_ETQF0 (0x5cb0) /* EType Queue Filter */
+#define IGB_IMIR0 (0x5a80) /* Immediate Interrupt Rx */
+#define IGB_IMIREXT0 (0x5aa9) /* Immediate Interrupt Rx
Extended */
+#define IGB_IMIRVP (0x5ac0) /* Immediate Interrupt Rx VLAN
Priority */
+#define IGB_SAQF0 (0x5980) /* Source Address Queue Filter */
+#define IGB_DAQF0 (0x59a0) /* Destination Address Queue
Filter */
+#define IGB_SPQF0 (0x59c0) /* Source Port Queue Filter */
+#define IGB_FTQF0 (0x59e0) /* Five-Tuple Queue Filter */
+#define IGB_SYNQF (0x55fc) /* SYN Packet Queue Filter */
+
+/* TODO: Virtualization */
+
+/* Statistic registers */
+
+#define IGB_CRCERRS (0x04000) /* CRC Error Count */
+#define IGB_ALGNERRC (0x04004) /* Alignment Error Count */
+#define IGB_SYMERRS (0x04008) /* Symbol Error Count */
+#define IGB_RXERRC (0x0400c) /* RX Error Count */
+#define IGB_MPC (0x04010) /* Missed Packets Count */
+#define IGB_SCC (0x04014) /* Single Collision Count */
+#define IGB_ECOL (0x04018) /* Excessive Collisions Count */
+#define IGB_MCC (0x0401c) /* Multiple Collision Count */
+#define IGB_LATECOL (0x04020) /* Late Collisions Count */
+#define IGB_COLC (0x04028) /* Collision Count */
+#define IGB_DC (0x04030) /* Defer Count */
+#define IGB_TNCRS (0x04034) /* Transmit with No CRS */
+#define IGB_HTDPMC (0x0403c) /* Host Transmit Discarded
Packets by MAC Count */
+#define IGB_RLEC (0x04040) /* Receive Length Error Count */
+#define IGB_CBRDPC (0x04044) /* Circuit Breaker Rx dropped
packet */
+#define IGB_XONRXC (0x04048) /* XON Received Count */
+#define IGB_XONTXC (0x0404c) /* XON Transmitted Count */
+#define IGB_XOFFRXC (0x04050) /* XOFF Received Count */
+#define IGB_XOFFTXC (0x04054) /* XOFF Transmitted Count */
+#define IGB_FCRUC (0x04058) /* FC Received Unsupported Count
*/
+#define IGB_PRC64 (0x0405c) /* Packets Received [64 Bytes]
Count */
+#define IGB_PRC127 (0x04060) /* Packets Received [65–127
Bytes] Count */
+#define IGB_PRC255 (0x04064) /* Packets Received [128–255
Bytes] */
+#define IGB_PRC511 (0x04068) /* Packets Received [256–511
Bytes] */
+#define IGB_PRC1023 (0x0406c) /* Packets Received [512–1023
Bytes] */
+#define IGB_PRC1522 (0x04070) /* Packets Received [1024 to Max
Bytes] */
+#define IGB_GPRC (0x04074) /* Good Packets Received Count */
+#define IGB_BPRC (0x04078) /* Broadcast Packets Received
Count */
+#define IGB_MPRC (0x0407c) /* Multicast Packets Received
Count */
+#define IGB_GPTC (0x04080) /* Good Packets Transmitted Count
*/
+#define IGB_GORCL (0x04088) /* Good Octets Received Count Low
*/
+#define IGB_GORCH (0x0408c) /* Good Octets Received Count
High */
+#define IGB_GOTCL (0x04090) /* Good Octets Transmitted Count
Low */
+#define IGB_GOTCH (0x04094) /* Good Octets Transmitted Count
High */
+#define IGB_RNBC (0x040a0) /* Receive No Buffers Count */
+#define IGB_RUC (0x040a4) /* Receive Undersize Count */
+#define IGB_RFC (0x040a8) /* Receive Fragment Count */
+#define IGB_ROC (0x040ac) /* Receive Oversize Count */
+#define IGB_RJC (0x040b0) /* Receive Jabber Count */
+#define IGB_MNGPRC (0x040b4) /* Management Packets Received
Count */
+#define IGB_MPDC (0x040b8) /* Management Packets Dropped
Count */
+#define IGB_MNGPTC (0x040bc) /* Management Packets Transmitted
Count */
+#define IGB_BMNGPRC (0x0414c) /* BMC Management Packets Receive
Count */
+#define IGB_BMPDC (0x04140) /* BMC Management Packets Dropped
Count */
+#define IGB_BMNGPTC (0x04144) /* BMC Management Packets
Transmitted Count */
+#define IGB_TORL (0x040c0) /* Total Octets Received */
+#define IGB_TORH (0x040c4) /* Total Octets Received */
+#define IGB_TOTL (0x040c8) /* Total Octets Transmitted */
+#define IGB_TOTH (0x040cc) /* Total Octets Transmitted */
+#define IGB_TPR (0x040d0) /* Total Packets Received */
+#define IGB_TPT (0x040d4) /* Total Packets Transmitted */
+#define IGB_PTC64 (0x040d8) /* Packets Transmitted [64 Bytes]
Count */
+#define IGB_PTC127 (0x040dc) /* Packets Transmitted [65–127
Bytes] Count */
+#define IGB_PTC255 (0x040e0) /* Packets Transmitted [128–255
Bytes] Count */
+#define IGB_PTC511 (0x040e4) /* Packets Transmitted [256–511
Bytes] Count */
+#define IGB_PTC1023 (0x040e8) /* Packets Transmitted [512–1023
Bytes] Count */
+#define IGB_PTC1522 (0x040ec) /* Packets Transmitted [Greater
than 1024 Bytes] Count */
+#define IGB_MCPTC (0x040f0) /* Multicast Packets Transmitted
Count */
+#define IGB_BPTC (0x040f4) /* Broadcast Packets Transmitted
Count */
+ /* ... missing registers */
+
+/* Wake Up and Proxying */
+
+#define IGB_WUC (0x5800) /* Wake Up Control Register */
+#define IGB_WUFC (0x5808) /* Wake Up Filter Control
Register */
+#define IGB_WUS (0x5810) /* Wake Up Status Register */
+#define IGB_WUPL (0x5900) /* Wake Up Packet Length */
+#define IGB_WUPM (0x5a00) /* Wake Up Packet Memory */
+#define IGB_FHFT (0x9000) /* Flexible Host Filter Table
registers */
+#define IGB_FHFTEXT (0x9a00) /* Flexible Host Filter Table
registers extended */
+
+/* TODO: Management Register */
+
+/* TODO: PCIe */
+
+/* Diagnostic */
+
+#define IGB_RDFH (0x2410) /* RX Data FIFO Head */
+#define IGB_RDFT (0x2418) /* RX Data FIFO Tail */
+#define IGB_RDFHS (0x2420) /* RX Data FIFO Head Saved */
+#define IGB_RDFTS (0x2428) /* RX Data FIFO Tail Saved */
+#define IGB_RDFPC (0x2430) /* Receive Data FIFO Packet
Count */
+#define IGB_RPBECCSTS (0x245c) /* Receive Packet buffer ECC
control */
+#define IGB_TPBECCSTS (0x345C) /* Transmit Packet buffer ECC
control */
+#define IGB_FCSTS0 (0x2464) /* Flow Control Status */
+#define IGB_RDHESTS (0x25c0) /* Rx Descriptor Handler ECC
status */
+#define IGB_TDHESTS (0x35c0) /* Tx Descriptor Handler ECC
status */
+#define IGB_TDFH (0x3410) /* TX Data FIFO Head */
+#define IGB_TDFT (0x3418) /* TX Data FIFO Tail */
+#define IGB_TDFHS (0x3420) /* TX Data FIFO Head Saved */
+#define IGB_TDFTS (0x3428) /* TX Data FIFO Tail Saved */
+#define IGB_TDFPC (0x3430) /* Transmit Data FIFO Packet
Count */
+#define IGB_TDHMP (0x35fc) /* Tx Descriptor Handler Memory
Page Number */
+#define IGB_CIRC (0x0f00) /* Circuits Control */
+#define IGB_TXBDC (0x35e0) /* Tx DMA Performance Burst and
Descriptor Count */
+#define IGB_TXIDLE (0x35e4) /* Tx DMA Performance Idle Count
*/
+#define IGB_RXBDC (0x25e0) /* Tx DMA Performance Burst and
Descriptor Count */
+#define IGB_RXIDLE (0x25E4) /* Tx DMA Performance Idle Count
*/
+
+/* TODO: PCS */
+
+/* TODO: Time Sync */
+
+/* TODO: MACSec */
+
+/* TODO: IPSec */
+
+/* Device Control Register */
+
+#define IGB_CTRL_FD (1 << 0) /* Bit 0: Full-Duplex */
+ /* Bit 1: Reserved */
+#define IGB_CTRL_GIOMDIS (1 << 2) /* Bit 2: GIO Master Enable
Status */
+#define IGB_CTRL_LRST (1 << 3) /* Bit 3: Link Reset */
+ /* Bits 4-5: Reserved */
+#define IGB_CTRL_SLU (1 << 6) /* Bit 6: Set Link Up */
+#define IGB_CTRL_ILOS (1 << 7) /* Bit 7: Invert Loss-of-Signal */
+#define IGB_CTRL_SPEED_SHIFT (8) /* Bits 8-9: Speed selection */
+#define IGB_CTRL_SPEED_MASK (3 << IGB_CTRL_SPEED_SHIFT)
+# define IGB_CTRL_SPEED_10MBS (0 << IGB_CTRL_SPEED_SHIFT)
+# define IGB_CTRL_SPEED_100MBS (1 << IGB_CTRL_SPEED_SHIFT)
+# define IGB_CTRL_SPEED_1000MBS (2 << IGB_CTRL_SPEED_SHIFT)
+
+ /* Bit 10: Reserved */
+#define IGB_CTRL_FRCSPD (1 << 11) /* Bit 11: Force Speed */
+#define IGB_CTRL_FRCDPLX (1 << 12) /* Bit 12: Force Duplex */
+ /* Bits 13-15: Reserved */
+#define IGB_CTRL_SDP0_GPIEN (1 << 16) /* Bit 16: GPI Detection Enable
for SDP0 */
+#define IGB_CTRL_SDP1_GPIEN (1 << 17) /* Bit 17: GPI Detection Enable
for SDP1 */
+#define IGB_CTRL_SDP0_DATA (1 << 18) /* Bit 18: SDP0 Data Value */
+#define IGB_CTRL_SDP1_DATA (1 << 19) /* Bit 19: SDP1 Data Value */
+#define IGB_CTRL_ADVD3WUC (1 << 20) /* Bit 20: D3Cold Wakeup
Capability Advertisement Enable */
+#define IGB_CTRL_SDP0_WDE (1 << 21) /* Bit 21: SDP0 Used for Watchdog
Indication */
+#define IGB_CTRL_SDP0_IODIR (1 << 22) /* Bit 22: SDP0 Pin
Directionality */
+#define IGB_CTRL_SDP1_IODIR (1 << 23) /* Bit 23: SDP1 Pin
Directionality */
+ /* Bits 24-25: Reserved */
+#define IGB_CTRL_RST (1 << 26) /* Bit 26: Device Reset */
+#define IGB_CTRL_RFCE (1 << 27) /* Bit 27: Receive Flow Control
Enable */
+#define IGB_CTRL_TFCE (1 << 28) /* Bit 28: Transmit Flow Control
Enable */
+ /* Bit 29: Reserved */
+#define IGB_CTRL_VME (1 << 30) /* Bit 30: VLAN Mode Enable */
+#define IGB_CTRL_PHYRST (1 << 31) /* Bit 31: PHY Reset */
+
+/* Device Status Regiuster */
+
+#define IGB_STATUS_FD (1 << 0) /* Bit 0: Full Duplex */
+#define IGB_STATUS_LU (1 << 1) /* Bit 1: Link Up */
+#define IGB_STATUS_LANID_SHIFT (2) /* Bit 2-3: LAN ID*/
+#define IGB_STATUS_TXOFF (1 << 4) /* Bit 4: Transmission Paused */
+ /* Bit 5: Reserved */
+#define IGB_STATUS_SPEED_SHFIT (6) /* Bits 6-7: Link speed setting */
+#define IGB_STATUS_ASDV_SHFIT (8) /* Bits 8-9: Auto-Speed Detection
Value. */
+#define IGB_STATUS_PHYRA (10) /* Bit 10: PHY Reset Asserted */
+ /* Bits 11-13: Reserved */
+#define IGB_STATUS_NVFS_SHFIT (14) /* Bits 14-17: Num VFs in the IOV
capability */
+#define IGB_STATUS_IOVMODE (18) /* Bit 18: VF enable (VFE) bit in
the IOV */
+#define IGB_STATUS_GIOM (19) /* Bit 19: GIO Master Disable bit
state */
+ /* Bits 20-30: Reserved */
+#define IGB_STATUS_DMACGE (31) /* Bit 31: DMA clock gating
Enable bit */
+
+/* Receive Address High */
+
+#define IGB_RAH_RAH_MASK (0xffff) /* Bits 0-15: Receive address
High */
+#define IGB_RAH_ASEL (16) /* Bits 16-17 Address Select */
+#define IGB_RAH_POOLSEL (18) /* Bits 18-25 Pool Select */
+ /* Bits 26-30: Reserved */
+#define IGB_RAH_AV (1 << 31) /* Bit 31: Address Valid */
+
+/* Transmit Control */
+
+ /* Bit 0: Reserved */
+#define IGB_TCTL_EN (1 << 1) /* Bit 1: Transmit Enable */
+ /* Bit 2: Reserved */
+#define IGB_TCTL_PSP (1 << 3) /* Bit 3: Pad Short Packets */
+#define IGB_TCTL_CT_SHIFT (4) /* Bits 4-11: Collision Threshold
*/
+#define IGB_TCTL_COLD_SHIFT (12) /* Bits 12-21: Collision Distance
(BST) */
+#define IGB_TCTL_SWXOFF (1 << 22) /* Bit 22: Software XOFF
Transmission */
+ /* Bit 23: Reserved */
+#define IGB_TCTL_RTLC (1 << 24) /* Bit 24: Re-transmit on Late
Collision */
+ /* Bits 25-32: Reserved */
+
+/* Transmit Descriptor Control */
+
+#define IGB_TXDCTL_PTHRESH_SHIFT (0) /* Bits 0-4: Prefetch Threshold */
+ /* Bits 5-7: Reserved */
+#define IGB_TXDCTL_HTHRESH_SHIFT (8) /* Bits 8-12: Host Threshold */
+ /* Bits 13-15: Reserved */
+#define IGB_TXDCTL_WTHRESH_SHIFT (16) /* Bits 16-20: Write-Back
Threshold */
+ /* Bits 21-24: Reserved */
+#define IGB_TXDCTL_ENABLE (1 << 25) /* Bit 25: Transmit Queue Enable */
+ /* Bits 27-31: Reserved */
+
+/* Tx Descriptor Ring Length */
+
+/* Receive Control */
+
+ /* Bit 0: Reserved */
+#define IGB_RCTL_EN (1 << 1) /* Bit 1: Receiver Enable */
+#define IGB_RCTL_SBP (1 << 2) /* Bit 2: Store Bad Packets */
+#define IGB_RCTL_UPE (1 << 3) /* Bit 3: Unicast Promiscuous
Enabled */
+#define IGB_RCTL_MPE (1 << 4) /* Bit 4: Multicast Promiscuous
Enabled */
+#define IGB_RCTL_LPE (1 << 5) /* Bit 5: Long Packet Reception
Enable */
+#define IGB_RCTL_LBM_SHIFT (6) /* Bits 6-7: Loopback mode */
+ /* Bits 8-11: Reserved */
+#define IGB_RCTL_MO_SHIFT (12) /* Bits 12-13: Multicast Offset */
+ /* Bit 14: Reserved */
+#define IGB_RCTL_BAM (1 << 15) /* Bit 15: Broadcast Accept Mode
*/
+#define IGB_RCTL_BSIZE_SHIFT (16) /* Bits 16-17: Receive Buffer
Size */
+# define IGB_RCTL_BSIZE_2048 (0 << 16) /* 00b: 2048 bytes */
+# define IGB_RCTL_BSIZE_1024 (1 << 16) /* 01b: 1024 bytes */
+# define IGB_RCTL_BSIZE_512 (2 << 16) /* 10b: 512 bytes */
+# define IGB_RCTL_BSIZE_256 (3 << 16) /* 11b: 256 bytes */
+#define IGB_RCTL_VFE (1 << 18) /* Bit 18: VLAN Filter Enable */
+#define IGB_RCTL_CFIEN (1 << 18) /* Bit 19: Canonical Form
Indicator Enable */
+#define IGB_RCTL_CFI (1 << 20) /* Bit 20: Canonical Form
Indicator bit value */
+#define IGB_RCTL_PSP (1 << 21) /* Bit 21: Pad Small Receive
Packets */
+#define IGB_RCTL_DPF (1 << 22) /* Bit 22: Discard Pause Frames */
+#define IGB_RCTL_PMCF (1 << 23) /* Bit 23: Pass MAC Control
Frames */
+ /* Bits 24-25: Reserved */
+#define IGB_RCTL_SECRC (1 << 26) /* Bit 26: Strip Ethernet CRC
from incoming packet */
+ /* Bits 27-31: Reserved */
+
+/* Receive Descriptor Control */
+
+#define IGB_RXDCTL_PTHRESH_SHIFT (0) /* Bits 0-4: Prefetch Threshold */
+ /* Bits 5-7: Reserved */
+#define IGB_RXDCTL_HTHRESH_SHIFT (8) /* Bits 8-12: Host Threshold */
+ /* Bits 13-15: Reserved */
+#define IGB_RXDCTL_WTHRESH_SHIFT (16) /* Bits 16-20: Write-Back
Threshold */
+ /* Bits 21-24: Reserved */
+#define IGB_RXDCTL_ENABLE (1 << 25) /* Bit 25: Receive Queue Enable */
+#define IGB_RXDCTL_SWFLUSH (1 << 26) /* Bit 26: Receive Software Flush
*/
+ /* Bits 27-31: Reserved */
+
+/* Interrupt Cause */
+
+#define IGB_IC_TXDW (1 << 0) /* Bit 0: Transmit Descriptor
Written Back */
+ /* Bit 1: Reserved */
+#define IGB_IC_LSC (1 << 2) /* Bit 2: Link Status Change */
+ /* Bit 3: Reserved */
+#define IGB_IC_RXDMT0 (1 << 4) /* Bit 4: Receive Descriptor
Minimum Threshold Reached */
+#define IGB_IC_MACSEC (1 << 5) /* Bit 5: Sets the MACSec
interrupt */
+#define IGB_IC_RXMISS (1 << 6) /* Bit 6: Receiver Miss Interrupt
*/
+#define IGB_IC_RXDW (1 << 7) /* Bit 7: Receiver Descriptor
Write Back interrupt */
+#define IGB_IC_VMMB (1 << 8) /* Bit 8: Sets the VM mailbox
interrupt. */
+ /* Bits 9-10: Reserved */
+ /* Bits 11-14: General Purpose
Interrupts */
+#define IGB_IC_PTRAP (1 << 15) /* Bit 15: Probe trap interrupt */
+ /* Bits 16-17: Reserved */
+#define IGB_IC_MNG (1 << 18) /* Bit 18: Management Event
interrupt */
+ /* Bit 19: Reserved */
+#define IGB_IC_OMED (1 << 20) /* Bit 20: Sets the Other Media
Energy Detected Interrupt */
+ /* Bit 21: Reserved */
+#define IGB_IC_FER (1 << 22) /* Bit 22: Fatal Error interrupt
*/
+#define IGB_IC_NFER (1 << 23) /* Bit 23: Sets the Non Fatal
Error Interrupt */
+#define IGB_IC_CSRTO (1 << 24) /* Bit 24: Sets the CSR access
time out indication interrupt */
+#define IGB_IC_SCE (1 << 25) /* Bit 25: Set the Storm Control
Event Interrupt */
+#define IGB_IC_SWD (1 << 26) /* Bit 26: Software Watchdog
interrupt */
+ /* Bit 27: Reserved */
+#define IGB_IC_DOUTSYNC (1 << 28) /* Bit 28: Sets the DMA Tx Out of
Sync Interrupt. */
+ /* Bit 29: Reserved */
+#define IGB_IC_TCPTIM (1 << 30) /* Bit 30: Sets the TCP timer
interrupt */
+ /* Bit 31: Reserved */
+
+/* Extended Interrupt Mask for Non-MSI-X Mode */
+
+#define IGB_EIMS_NOMSIX_RXTX0 (1 << 0)
+#define IGB_EIMS_NOMSIX_RXTX1 (1 << 1)
+#define IGB_EIMS_NOMSIX_RXTX2 (1 << 2)
+#define IGB_EIMS_NOMSIX_RXTX3 (1 << 3)
+#define IGB_EIMS_NOMSIX_TCPTIM (1 << 30)
+#define IGB_EIMS_NOMSIX_OTHER (1 << 31)
+
+/* Extended Interrupt Mask for MSI-X Mode */
+
+#define IGB_EIMS_MSIX_0 (1 << 0)
+#define IGB_EIMS_MSIX_1 (1 << 1)
+#define IGB_EIMS_MSIX_2 (1 << 2)
+#define IGB_EIMS_MSIX_3 (1 << 3)
+#define IGB_EIMS_MSIX_4 (1 << 4)
+
+/* Interrupt Vector Allocation Registers */
+
+#define IGB_IVAR0_RXQ0_SHIFT (0) /* Bits 0-4: MSI-X vector
assigned to RxQ0 */
+#define IGB_IVAR0_RXQ0_VAL (1 << 7) /* Bit 7: Valid bit for RxQ0 */
+#define IGB_IVAR0_TXQ0_SHIFT (8) /* Bits 8-12: MSI-X vector
assigned to TxQ0 */
+#define IGB_IVAR0_TXQ0_VAL (1 << 7) /* Bit 7: Valid bit for TxQ0 */
+
+/* Interrupt Vector Allocation Registers - Misc */
+
+#define IGB_IVARMSC_TCPTIM (0) /* Bits 0-5: MSI-X vectorassigned
to TCP timer interrupt */
+ /* Bits 5-6: Reserved */
+#define IGB_IVARMSC_TCPTIM_VAL (1 << 7) /* Bit 7: Enable bit for TCP
timer interrupt */
+#define IGB_IVARMSC_OTHER_SHIFT (8) /* Bits 8-12: MSI-X vector
assigned to Other Cause */
+ /* Bits 13-14: Reserved */
+#define IGB_IVARMSC_OTHER_VAL (1 << 15) /* Bit 15: Enable bit for Other
Cause */
+ /* Bits 20-30: Reserved */
+
+/* General Purpose Interrupt Enable */
+
+#define IGB_GPIE_NSICR (1 << 0) /* Bit 0: Non Selective Interrupt
Clear on Read */
+ /* Bits 1-3: Reserved */
+#define IGB_GPIE_MSIX (1 << 4) /* Bit 4: MSI-X mode */
+ /* Bits 5-6: Reserved */
+#define IGB_GPIE_LLINTERVAL_SHIFT (7) /* Bits 7-11: Low Latency Credits
Increment Rate */
+ /* Bits 12-29: Reserved */
+#define IGB_GPIE_EIAME (1 << 30) /* Bit 30: Extended Interrupt
Auto Mask Enable */
+#define IGB_GPIE_PBASUPPORT (1 << 31) /* Bit 31: PBA Support */
+
+/* Transmit Descriptor Command Field */
+
+#define IGB_TDESC_CMD_EOP (1 << 0) /* Bit 0: End Of Packet */
+#define IGB_TDESC_CMD_IFCS (1 << 1) /* Bit 1: Insert FCS */
+#define IGB_TDESC_CMD_IC (1 << 2) /* Bit 2: Insert Checksum */
+#define IGB_TDESC_CMD_RS (1 << 3) /* Bit 3: Report Status */
+#define IGB_TDESC_CMD_DEXT (1 << 5) /* Bit 5: Extension (0b for
legacy mode) */
+#define IGB_TDESC_CMD_VLE (1 << 6) /* Bit 6: VLAN Packet Enable */
+
+/* Transmit Descriptor Status Field */
+
+#define IGB_TDESC_STATUS_DD (1 << 0) /* Bit 0: Descriptor Done */
+
+/* Transmit Descriptor Special Field */
+
+#define IGB_TDESC_SPEC_VLAN_SHIFT (0) /* Bits 0-11: VLAN Identifier */
+#define IGB_TDESC_SPEC_CFI (1 << 12) /* Bit 12: Canonical Form
Indicator */
+#define IGB_TDESC_SPEC_PRI_SHIFT (13) /* Bits 13-15: User Priority */
+
+/* Receive Descriptor Status Field */
+
+#define IGB_RDESC_STATUS_DD (1 << 0) /* Bit 0: Descriptor Done */
+#define IGB_RDESC_STATUS_EOP (1 << 1) /* Bit 1: End of Packet */
+#define IGB_RDESC_STATUS_VP (1 << 3) /* Bit 3: Packet is 802.1Q
(matched VET) */
+#define IGB_RDESC_STATUS_UDPCS (1 << 4) /* Bit 4: UDP checksum or IP
payload checksum calculated on packet */
+#define IGB_RDESC_STATUS_L4CS (1 << 5) /* Bit 5: L4 (UDP or TCP)
checksum calculated on packet */
+#define IGB_RDESC_STATUS_IPCS (1 << 6) /* Bit 6: IP Checksum Calculated
on Packet */
+#define IGB_RDESC_STATUS_PIF (1 << 7) /* Bit 7: Passed in-exact filter
*/
+
+/* Receive Descriptor Errors Field */
+
+#define IGB_RDESC_ERRORS_L4E (1 << 5) /* Bit 5: TCP/UDP Checksum Error
*/
+#define IGB_RDESC_ERRORS_IPE (1 << 6) /* Bit 6: IP Checksum Error */
+#define IGB_RDESC_ERRORS_RXE (1 << 7) /* Bit 7: RX Data Error */
+
+/* Receive Descriptor Special Field */
+
+#define IGB_RDESC_SPEC_VLAN_SHIFT (0) /* Bits 0-11: VLAN Identifier */
+#define IGB_RDESC_SPEC_CFI (1 << 12) /* Bit 12: Canonical Form
Indicator */
+#define IGB_RDESC_SPEC_PRI_SHIFT (13) /* Bits 13-15: User Priority */
+
+/*****************************************************************************
+ * Public Types
+ *****************************************************************************/
+
+/* Legacy TX descriptor */
+
+begin_packed_struct struct igb_tx_leg_s
+{
+ uint64_t addr;
+ uint16_t len;
+ uint8_t cso;
+ uint8_t cmd;
+ uint8_t status;
+ uint8_t css;
+ uint16_t special;
+} end_packed_struct;
+
+/* Legacy RX descriptor */
+
+begin_packed_struct struct igb_rx_leg_s
+{
+ uint64_t addr;
+ uint16_t len;
+ uint16_t checksum;
+ uint8_t status;
+ uint8_t errors;
+ uint16_t special;
+} end_packed_struct;
+
+#endif /* __DRIVERS_NET_IGB!_H */
diff --git a/drivers/pci/pci_drivers.c b/drivers/pci/pci_drivers.c
index 5a0301c8dfd..c2204bd1239 100644
--- a/drivers/pci/pci_drivers.c
+++ b/drivers/pci/pci_drivers.c
@@ -32,6 +32,7 @@
#include <nuttx/virtio/virtio-pci.h>
#include <nuttx/net/e1000.h>
#include <nuttx/net/igc.h>
+#include <nuttx/net/igb.h>
#include <nuttx/can/kvaser_pci.h>
#include <nuttx/can/ctucanfd_pci.h>
#include <nuttx/usb/xhci_pci.h>
@@ -163,6 +164,16 @@ int pci_register_drivers(void)
}
#endif
+ /* Initialization igb driver */
+
+#ifdef CONFIG_NET_IGB
+ ret = pci_igb_init();
+ if (ret < 0)
+ {
+ pcierr("pci_igb_init failed, ret=%d\n", ret);
+ }
+#endif
+
/* Initialzie Kvaser pci driver */
#ifdef CONFIG_CAN_KVASER
diff --git a/include/nuttx/net/igb.h b/include/nuttx/net/igb.h
new file mode 100644
index 00000000000..1377959a984
--- /dev/null
+++ b/include/nuttx/net/igb.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * include/nuttx/net/igb.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_NET_IGB_H
+#define __INCLUDE_NUTTX_NET_IGB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pci_igb_init
+ *
+ * Description:
+ * Register a pci driver
+ *
+ ****************************************************************************/
+
+int pci_igb_init(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_NET_IGB_H */