From bc0c7b0db30d46664bcc609356edc6ce34481525 Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Tue, 2 Apr 2024 18:23:59 +0200 Subject: [PATCH] drivers/net: add Intel e1000 network card support add Intel e1000 network card support Signed-off-by: p-szafonimateusz --- drivers/net/CMakeLists.txt | 4 + drivers/net/Kconfig | 33 + drivers/net/Make.defs | 4 + drivers/net/e1000.c | 1443 ++++++++++++++++++++++++++++++++++++ drivers/net/e1000.h | 443 +++++++++++ drivers/pci/pci_drivers.c | 11 + include/nuttx/net/e1000.h | 57 ++ 7 files changed, 1995 insertions(+) create mode 100644 drivers/net/e1000.c create mode 100644 drivers/net/e1000.h create mode 100644 include/nuttx/net/e1000.h diff --git a/drivers/net/CMakeLists.txt b/drivers/net/CMakeLists.txt index a04cdf752c..438b12ee00 100644 --- a/drivers/net/CMakeLists.txt +++ b/drivers/net/CMakeLists.txt @@ -79,6 +79,10 @@ if(CONFIG_NET) list(APPEND SRCS lan9250.c) endif() + if(CONFIG_NET_E1000) + list(APPEND SRCS e1000.c) + endif() + if(CONFIG_ARCH_PHY_INTERRUPT) list(APPEND SRCS phy_notify.c) endif() diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a16b62eb67..f5146c457d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -768,4 +768,37 @@ config WIFI_SIM_NUMBER ---help--- The number of simulated wifi network devices. +menuconfig NET_E1000 + bool "Intel E1000 support" + default n + depends on PCI + ---help--- + Enable E1000 PCI Ethernet driver. + +if NET_E1000 + +config NET_E1000_RXSPARE + int "Intel E1000 spare RX buffers" + default 8 + +config NET_E1000_I219 + bool "Intel I219" + default n + ---help--- + Enable Intel I219 Ethernet driver. + +config NET_E1000_82540EM + bool "Intel 82540EM" + default n + ---help--- + Enable Intel 82540EM Ethernet driver (-device e1000 on QEMU). + +config NET_E1000_82574L + bool "Intel 82574L" + default n + ---help--- + Enable Intel 82574L Ethernet driver (-device e1000e on QEMU). + +endif # NET_E1000 + endif # NETDEVICES diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs index 1efd873f68..900c95adb3 100644 --- a/drivers/net/Make.defs +++ b/drivers/net/Make.defs @@ -93,6 +93,10 @@ endif endif +ifeq ($(CONFIG_NET_E1000),y) + CSRCS += e1000.c +endif + ifeq ($(CONFIG_DRIVERS_WIFI_SIM),y) CSRCS += wifi_sim.c endif diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c new file mode 100644 index 0000000000..3d0c43a644 --- /dev/null +++ b/drivers/net/e1000.c @@ -0,0 +1,1443 @@ +/***************************************************************************** + * drivers/net/e1000.c + * + * 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 + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "e1000.h" + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +/* Packet buffer size */ + +#define E1000_PKTBUF_SIZE 2048 +#define E1000_RCTL_BSIZE E1000_RCTL_BSIZE_2048 + +/* TX and RX descriptors */ + +#define E1000_TX_DESC 256 +#define E1000_RX_DESC 256 + +/* 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 + * allways possible to allocate the new RX packet in the recevier logic. + * It's hard to tell how many spare buffers is needed, for now it's set to 8. + */ + +#define E1000_TX_QUOTA E1000_TX_DESC +#define E1000_RX_QUOTA (E1000_RX_DESC + CONFIG_NET_E1000_RXSPARE) + +/* NOTE: CONFIG_IOB_ALIGNMENT must match system D-CACHE line size */ + +#if CONFIG_IOB_NBUFFERS < (E1000_RX_QUOTA + E1000_TX_QUOTA) +# error CONFIG_IOB_NBUFFERS must be > (E1000_RX_QUOTA + E1000_TX_QUOTA) +#endif + +#if CONFIG_IOB_BUFSIZE < E1000_PKTBUF_SIZE +# error CONFIG_IOB_BUFSIZE must be > E1000_PKTBUF_SIZE +#endif + +/* PCI BARs */ + +#define E1000_MMIO_BAR 0 +#define E1000_FLASH_BAR 1 +#define E1000_IO_BAR 2 +#define E1000_MSIX_BAR 3 + +/* E1000 interrupts */ + +#define E1000_INTERRUPTS (E1000_IC_RXO | E1000_IC_RXT0 | \ + E1000_IC_RXDMT0 | E1000_IC_LSC | \ + E1000_IC_TXDW) + +/* For MSI-X we allocate all interrupts to MSI-X vector 0 */ + +#define E1000_MSIX_INTERRUPTS (E1000_IC_RXQ0 | \ + E1000_IC_TXQ0 | \ + E1000_IC_OTHER) +#define E1000_MSIX_IVAR (E1000_IVAR_RXQ0_EN | \ + E1000_IVAR_TXQ0_EN | \ + E1000_IVAR_OTHER_EN) + +/* NIC specific Flags */ + +#define E1000_RESET_BROKEN (1 << 0) +#define E1000_HAS_MSIX (1 << 1) + +/***************************************************************************** + * Private Types + *****************************************************************************/ + +/* Extend default PCI devie type */ + +struct e1000_type_s +{ + uint32_t desc_align; /* Descriptor alignment */ + uint32_t mta_regs; /* MTA registers */ + uint32_t flags; /* Device flags */ +}; + +/* E1000 private data */ + +struct e1000_driver_s +{ + /* This holds the information visible to the NuttX network */ + + struct netdev_lowerhalf_s dev; + + /* Driver state */ + + bool bifup; + + /* Packets list */ + + FAR netpkt_t **tx_pkt; + FAR netpkt_t **rx_pkt; + + /* Descriptors */ + + FAR struct e1000_tx_leg_s *tx; + FAR struct e1000_rx_leg_s *rx; + + size_t tx_now; + size_t tx_done; + size_t rx_now; + + /* PCI data */ + + FAR struct pci_device_s *pcidev; + const FAR struct e1000_type_s *type; + int irq; + uint64_t base; + uint32_t irqs; + +#ifdef CONFIG_NET_MCASTGROUP + /* MTA shadow */ + + FAR uint32_t *mta; +#endif +}; + +/***************************************************************************** + * Private Functions Definitions + *****************************************************************************/ + +/* Helpers */ + +static uint32_t e1000_getreg_mem(FAR struct e1000_driver_s *priv, + unsigned int offset); +static void e1000_putreg_mem(FAR struct e1000_driver_s *priv, + unsigned int offset, + uint32_t value); +#ifdef CONFIG_DEBUG_NET_INFO +static void e1000_dump_reg(FAR struct e1000_driver_s *priv, + FAR const char *msg, unsigned int offset); +static void e1000_dump_mem(FAR struct e1000_driver_s *priv, + FAR const char *msg); +#endif + +/* Common TX logic */ + +static int e1000_transmit(FAR struct netdev_lowerhalf_s *dev, + FAR netpkt_t *pkt); + +/* Interrupt handling */ + +static FAR netpkt_t *e1000_receive(FAR struct netdev_lowerhalf_s *dev); +static void e1000_txdone(FAR struct netdev_lowerhalf_s *dev); + +static void e1000_msi_interrupt(FAR struct e1000_driver_s *priv); +#ifdef CONFIG_PCI_MSIX +static void e1000_msix_interrupt(FAR struct e1000_driver_s *priv); +#endif +static int e1000_interrupt(int irq, FAR void *context, FAR void *arg); + +/* NuttX callback functions */ + +static int e1000_ifup(FAR struct netdev_lowerhalf_s *dev); +static int e1000_ifdown(FAR struct netdev_lowerhalf_s *dev); + +#ifdef CONFIG_NET_MCASTGROUP +static uint32_t e1000_hashmta(FAR struct e1000_driver_s *priv, + FAR const uint8_t *mac); +static int e1000_addmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); +static int e1000_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac); +#endif + +/* Initialization */ + +static void e1000_disable(FAR struct e1000_driver_s *priv); +static void e1000_enable(FAR struct e1000_driver_s *priv); +static int e1000_initialize(FAR struct e1000_driver_s *priv); +static int e1000_probe(FAR struct pci_device_s *dev); + +/***************************************************************************** + * Private Data + *****************************************************************************/ + +#ifdef CONFIG_NET_E1000_I219 +/* Intel I219 */ + +static const struct e1000_type_s g_e1000_i219 = +{ + .desc_align = 128, + .mta_regs = 32, + .flags = E1000_RESET_BROKEN +}; +#endif + +#ifdef CONFIG_NET_E1000_82540EM +/* Intel 82801IB (QEMU -device e1000) */ + +static const struct e1000_type_s g_e1000_82540em = +{ + .desc_align = 16, + .mta_regs = 128, + .flags = 0 +}; +#endif + +#ifdef CONFIG_NET_E1000_82574L +/* Intel 82574L (QEMU -device e1000e) */ + +static const struct e1000_type_s g_e1000_82574l = +{ + .desc_align = 128, + .mta_regs = 128, + .flags = E1000_HAS_MSIX +}; +#endif + +static const struct pci_device_id_s g_e1000_id_table[] = +{ +#ifdef CONFIG_NET_E1000_I219 + { + PCI_DEVICE(0x8086, 0x1a1e), + .driver_data = (uintptr_t)&g_e1000_i219 + }, +#endif +#ifdef CONFIG_NET_E1000_82540EM + { + PCI_DEVICE(0x8086, 0x100e), + .driver_data = (uintptr_t)&g_e1000_82540em + }, +#endif +#ifdef CONFIG_NET_E1000_82574L + { + PCI_DEVICE(0x8086, 0x10d3), + .driver_data = (uintptr_t)&g_e1000_82574l + }, +#endif + { } +}; + +static struct pci_driver_s g_e1000_drv = +{ + .id_table = g_e1000_id_table, + .probe = e1000_probe, +}; + +static const struct netdev_ops_s g_e1000_ops = +{ + .ifup = e1000_ifup, + .ifdown = e1000_ifdown, + .transmit = e1000_transmit, + .receive = e1000_receive, +#ifdef CONFIG_NET_MCASTGROUP + .addmac = e1000_addmac, + .rmmac = e1000_rmmac, +#endif +}; + +/***************************************************************************** + * Private Functions + *****************************************************************************/ + +/***************************************************************************** + * Name: e1000_getreg_mem + *****************************************************************************/ + +static uint32_t e1000_getreg_mem(FAR struct e1000_driver_s *priv, + unsigned int offset) +{ + uintptr_t addr = priv->base + offset; + return *((FAR volatile uint32_t *)addr); +} + +/***************************************************************************** + * Name: e1000_putreg_mem + *****************************************************************************/ + +static void e1000_putreg_mem(FAR struct e1000_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: e1000_dump_reg + *****************************************************************************/ + +static void e1000_dump_reg(FAR struct e1000_driver_s *priv, + FAR const char *msg, unsigned int offset) +{ + ninfo("\t%s:\t\t0x%" PRIx32 "\n", msg, e1000_getreg_mem(priv, offset)); +} + +/***************************************************************************** + * Name: e1000_dump_mem + *****************************************************************************/ + +static void e1000_dump_mem(FAR struct e1000_driver_s *priv, + FAR const char *msg) +{ + ninfo("Dump: %s\n", msg); + + ninfo("General registers:\n"); + e1000_dump_reg(priv, "CTRL", E1000_CTRL); + e1000_dump_reg(priv, "STATUS", E1000_STATUS); + + ninfo("Interrupt registers:\n"); + e1000_dump_reg(priv, "ICS", E1000_ICS); + e1000_dump_reg(priv, "IMS", E1000_IMS); + e1000_dump_reg(priv, "IVAR", E1000_IVAR); + + ninfo("Transmit registers:\n"); + e1000_dump_reg(priv, "TCTL", E1000_TCTL); + e1000_dump_reg(priv, "TIPG", E1000_TIPG); + e1000_dump_reg(priv, "AIT", E1000_AIT); + e1000_dump_reg(priv, "TDBAL", E1000_TDBAL); + e1000_dump_reg(priv, "TDBAH", E1000_TDBAH); + e1000_dump_reg(priv, "TDLEN", E1000_TDLEN); + e1000_dump_reg(priv, "TDH", E1000_TDH); + e1000_dump_reg(priv, "TDT", E1000_TDT); + e1000_dump_reg(priv, "TARC", E1000_TARC); + e1000_dump_reg(priv, "TIDV", E1000_TIDV); + e1000_dump_reg(priv, "TXDCTL", E1000_TXDCTL); + e1000_dump_reg(priv, "TADV", E1000_TADV); + + ninfo("Receive registers:\n"); + e1000_dump_reg(priv, "RCTL", E1000_RCTL); + e1000_dump_reg(priv, "RDBAL", E1000_RDBAL); + e1000_dump_reg(priv, "RDBAH", E1000_RDBAH); + e1000_dump_reg(priv, "RDLEN", E1000_RDLEN); + e1000_dump_reg(priv, "RDH", E1000_RDH); + e1000_dump_reg(priv, "RDT", E1000_RDT); + e1000_dump_reg(priv, "RDTR", E1000_RDTR); + e1000_dump_reg(priv, "RXDCTL", E1000_RXDCTL); + e1000_dump_reg(priv, "RADV", E1000_RADV); + e1000_dump_reg(priv, "RSRPD", E1000_RSRPD); + e1000_dump_reg(priv, "RAID", E1000_RAID); + e1000_dump_reg(priv, "RXCSUM", E1000_RXCSUM); + e1000_dump_reg(priv, "RFCTL", E1000_RFCTL); + e1000_dump_reg(priv, "RAL", E1000_RAL); + e1000_dump_reg(priv, "RAH", E1000_RAH); + + ninfo("Statistic registers:\n"); + e1000_dump_reg(priv, "CRCERRS", E1000_CRCERRS); + e1000_dump_reg(priv, "ALGNERRC", E1000_ALGNERRC); + e1000_dump_reg(priv, "RXERRC", E1000_RXERRC); + e1000_dump_reg(priv, "MPC", E1000_MPC); + e1000_dump_reg(priv, "SCC", E1000_SCC); + e1000_dump_reg(priv, "ECOL", E1000_ECOL); + e1000_dump_reg(priv, "MCC", E1000_MCC); + e1000_dump_reg(priv, "LATECOL", E1000_LATECOL); + e1000_dump_reg(priv, "COLC", E1000_COLC); + e1000_dump_reg(priv, "DC", E1000_DC); + e1000_dump_reg(priv, "TNCRS", E1000_TNCRS); + e1000_dump_reg(priv, "CEXTERR", E1000_CEXTERR); + e1000_dump_reg(priv, "RLEC", E1000_RLEC); + e1000_dump_reg(priv, "XONRXC", E1000_XONRXC); + e1000_dump_reg(priv, "XONTXC", E1000_XONTXC); + e1000_dump_reg(priv, "XOFFRXC", E1000_XOFFRXC); + e1000_dump_reg(priv, "XOFFTXC", E1000_XOFFTXC); + e1000_dump_reg(priv, "FCRUC", E1000_FCRUC); + e1000_dump_reg(priv, "PRC64", E1000_PRC64); + e1000_dump_reg(priv, "PRC127", E1000_PRC127); + e1000_dump_reg(priv, "PRC255", E1000_PRC255); + e1000_dump_reg(priv, "PRC511", E1000_PRC511); + e1000_dump_reg(priv, "PRC1023", E1000_PRC1023); + e1000_dump_reg(priv, "PRC1522", E1000_PRC1522); + e1000_dump_reg(priv, "GPRC", E1000_GPRC); + e1000_dump_reg(priv, "BPRC", E1000_BPRC); + e1000_dump_reg(priv, "MPRC", E1000_MPRC); + e1000_dump_reg(priv, "GPTC", E1000_GPTC); + e1000_dump_reg(priv, "GORCL", E1000_GORCL); + e1000_dump_reg(priv, "GORCH", E1000_GORCH); + e1000_dump_reg(priv, "GOTCL", E1000_GOTCL); + e1000_dump_reg(priv, "GOTCH", E1000_GOTCH); + e1000_dump_reg(priv, "RNBC", E1000_RNBC); + e1000_dump_reg(priv, "RUC", E1000_RUC); + e1000_dump_reg(priv, "RFC", E1000_RFC); + e1000_dump_reg(priv, "ROC", E1000_ROC); + e1000_dump_reg(priv, "RJC", E1000_RJC); + e1000_dump_reg(priv, "MNGPRC", E1000_MNGPRC); + e1000_dump_reg(priv, "MPDC", E1000_MPDC); + e1000_dump_reg(priv, "MPTC", E1000_MPTC); + e1000_dump_reg(priv, "TORL", E1000_TORL); + e1000_dump_reg(priv, "TORH", E1000_TORH); + e1000_dump_reg(priv, "TOT", E1000_TOT); + e1000_dump_reg(priv, "TPR", E1000_TPR); + e1000_dump_reg(priv, "TPT", E1000_TPT); + e1000_dump_reg(priv, "PTC64", E1000_PTC64); + e1000_dump_reg(priv, "PTC127", E1000_PTC127); + e1000_dump_reg(priv, "PTC255", E1000_PTC255); + e1000_dump_reg(priv, "PTC511", E1000_PTC511); + e1000_dump_reg(priv, "PTC1023", E1000_PTC1023); + e1000_dump_reg(priv, "PTC1522", E1000_PTC1522); + e1000_dump_reg(priv, "MPTC", E1000_MPTC); + e1000_dump_reg(priv, "BPTC", E1000_BPTC); + e1000_dump_reg(priv, "TSCTC", E1000_TSCTC); + e1000_dump_reg(priv, "TSCTFC", E1000_TSCTFC); + e1000_dump_reg(priv, "IAC", E1000_IAC); + + ninfo("Management registers:\n"); + e1000_dump_reg(priv, "WUC", E1000_WUC); + e1000_dump_reg(priv, "WUFC", E1000_WUFC); + e1000_dump_reg(priv, "WUS", E1000_WUS); + e1000_dump_reg(priv, "MFUTP01", E1000_MFUTP01); + e1000_dump_reg(priv, "MFUTP23", E1000_MFUTP23); + e1000_dump_reg(priv, "IPAV", E1000_IPAV); + + ninfo("Diagnostic registers:\n"); + e1000_dump_reg(priv, "POEMB", E1000_POEMB); + e1000_dump_reg(priv, "RDFH", E1000_RDFH); + e1000_dump_reg(priv, "FDFT", E1000_FDFT); + e1000_dump_reg(priv, "RDFHS", E1000_RDFHS); + e1000_dump_reg(priv, "RDFTS", E1000_RDFTS); + e1000_dump_reg(priv, "RDFPC", E1000_RDFPC); + e1000_dump_reg(priv, "TDFH", E1000_TDFH); + e1000_dump_reg(priv, "TDFT", E1000_TDFT); + e1000_dump_reg(priv, "TDFHS", E1000_TDFHS); + e1000_dump_reg(priv, "TDFTS", E1000_TDFTS); + e1000_dump_reg(priv, "TDFPC", E1000_TDFPC); + e1000_dump_reg(priv, "PBM", E1000_PBM); + e1000_dump_reg(priv, "PBS", E1000_PBS); +} +#endif + +/***************************************************************************** + * Name: e1000_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: + * Return OK on success + * + * Assumptions: + * The network is locked. + * + *****************************************************************************/ + +static int e1000_transmit(FAR struct netdev_lowerhalf_s *dev, + FAR netpkt_t *pkt) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_driver_s *)dev; + uint64_t pa = 0; + int desc = priv->tx_now; + size_t len = netpkt_getdatalen(dev, pkt); + + ninfo("transmit\n"); + + /* Check the send length */ + + if (len > E1000_PKTBUF_SIZE) + { + nerr("net transmit buffer too large\n"); + return -EINVAL; + } + + /* Store TX packet reference */ + + priv->tx_pkt[priv->tx_now] = pkt; + + /* Prepare next TX descriptor */ + + priv->tx_now = (priv->tx_now + 1) % E1000_TX_DESC; + + /* 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 = (E1000_TDESC_CMD_EOP | E1000_TDESC_CMD_IFCS | + E1000_TDESC_CMD_RS | E1000_TDESC_CMD_RPS); + priv->tx[desc].cso = 0; + priv->tx[desc].status = 0; + + SP_DSB(); + + /* Update TX tail */ + + e1000_putreg_mem(priv, E1000_TDT, priv->tx_now); + + ninfodumpbuffer("Transmitted:", netpkt_getdata(dev, pkt), len); + + return OK; +} + +/***************************************************************************** + * Name: e1000_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: + * A pointer to received packet + * + * Assumptions: + * The network is locked. + * + *****************************************************************************/ + +static FAR netpkt_t *e1000_receive(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_driver_s *)dev; + FAR netpkt_t *pkt = NULL; + FAR struct e1000_rx_leg_s *rx = NULL; + int desc = 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 & E1000_RDESC_STATUS_DD)) + { + return NULL; + } + + /* Next descriptor */ + + priv->rx_now = (priv->rx_now + 1) % E1000_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 */ + + e1000_putreg_mem(priv, E1000_RDT, desc); + + /* Handle errros */ + + 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: e1000_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 e1000_txdone(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_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 & E1000_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) % E1000_TX_DESC; + } + + netdev_lower_txdone(dev); +} + +/***************************************************************************** + * Name: e1000_msi_interupt + * + * Description: + * Perform MSI/legacy 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 e1000_msi_interrupt(FAR struct e1000_driver_s *priv) +{ + uint32_t status; + uint32_t tmp; + + status = e1000_getreg_mem(priv, E1000_ICR); + ninfo("irq status = 0x%" PRIx32 "\n", status); + + if (status == 0) + { + /* Ignore spurious interrupts */ + + return; + } + + /* Receiver Timer Interrupt or Receive Descriptor Minimum Threshold Reached + */ + + if ((status & E1000_IC_RXT0) || (status & E1000_IC_RXDMT0)) + { + netdev_lower_rxready(&priv->dev); + } + + /* Link Status Change */ + + if (status & E1000_IC_LSC) + { + tmp = e1000_getreg_mem(priv, E1000_STATUS); + if (tmp & E1000_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); + } + } + + /* Receiver Overrun */ + + if (status & E1000_IC_RXO) + { + nerr("Receiver Overrun\n"); + netdev_lower_rxready(&priv->dev); + } + + /* Transmit Descriptor Written Back */ + + if (status & E1000_IC_TXDW) + { + e1000_txdone(&priv->dev); + } +} + +#ifdef CONFIG_PCI_MSIX +/***************************************************************************** + * Name: e1000_msix_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 e1000_msix_interrupt(FAR struct e1000_driver_s *priv) +{ + uint32_t status; + + status = e1000_getreg_mem(priv, E1000_ICR); + ninfo("irq status = 0x%" PRIx32 "\n", status); + + if (status == 0) + { + /* Ignore spurious interrupts */ + + return; + } + + /* Receive Queue 0 Interrupt */ + + if (status & E1000_IC_RXQ0) + { + netdev_lower_rxready(&priv->dev); + } + + /* Link Status Change */ + + if (status & E1000_IC_LSC) + { + if (e1000_getreg_mem(priv, E1000_STATUS) & E1000_STATUS_LU) + { + ninfo("Link up\n"); + netdev_lower_carrier_on(&priv->dev); + } + else + { + ninfo("Link down\n"); + netdev_lower_carrier_off(&priv->dev); + } + } + + /* Receiver Overrun */ + + if (status & E1000_IC_RXO) + { + nerr("Receiver Overrun\n"); + netdev_lower_rxready(&priv->dev); + } + + /* Transmit Descriptor Written Back */ + + if (status & E1000_IC_TXQ0) + { + e1000_txdone(&priv->dev); + } +} +#endif + +/***************************************************************************** + * Name: e1000_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 e1000_interrupt(int irq, FAR void *context, FAR void *arg) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_driver_s *)arg; + + DEBUGASSERT(priv != NULL); + + ninfo("interrupt!\n"); + + /* Schedule to perform the interrupt processing on the worker thread. */ + +#ifdef CONFIG_PCI_MSIX + if (priv->type->flags & E1000_HAS_MSIX) + { + e1000_msix_interrupt(priv); + } + else +#endif + { + e1000_msi_interrupt(priv); + } + + return OK; +} + +/***************************************************************************** + * Name: e1000_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 e1000_ifup(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_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 + + /* Enable the Ethernet */ + + flags = enter_critical_section(); + e1000_enable(priv); + priv->bifup = true; + leave_critical_section(flags); + + return OK; +} + +/***************************************************************************** + * Name: e1000_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 e1000_ifdown(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_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 e1000_ifup() always + * successfully brings the interface back up. + */ + + e1000_disable(priv); + + /* Mark the device "down" */ + + priv->bifup = false; + leave_critical_section(flags); + return OK; +} + +#ifdef CONFIG_NET_MCASTGROUP +/***************************************************************************** + * Name: e1000_hashmta + * + * Note: This logic is based on freeBSD e1000 implementation + * + *****************************************************************************/ + +static uint32_t e1000_hashmta(FAR struct e1000_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: e1000_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 e1000_addmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_driver_s *)dev; + uint16_t hash = 0; + uint8_t row = 0; + uint8_t bit = 0; + int i = 0; + + hash = e1000_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--) + { + e1000_putreg_mem(priv, E1000_MTA + (i << 2), priv->mta[i]); + } + + return OK; +} + +/***************************************************************************** + * Name: e1000_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 e1000_rmmac(FAR struct netdev_lowerhalf_s *dev, + FAR const uint8_t *mac) +{ + FAR struct e1000_driver_s *priv = (FAR struct e1000_driver_s *)dev; + uint16_t hash = 0; + uint8_t row = 0; + uint8_t bit = 0; + int i = 0; + + hash = e1000_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--) + { + e1000_putreg_mem(priv, E1000_MTA + (i << 2), priv->mta[i]); + } + + return OK; +} +#endif /* CONFIG_NET_MCASTGROUP */ + +/***************************************************************************** + * Name: e1000_disable + * + * Description: + * Reset device to known state. + * + *****************************************************************************/ + +static void e1000_disable(FAR struct e1000_driver_s *priv) +{ + int i = 0; + + /* Reset Tx tail */ + + e1000_putreg_mem(priv, E1000_TDH, 0); + e1000_putreg_mem(priv, E1000_TDT, 0); + + /* Reset Rx tail */ + + e1000_putreg_mem(priv, E1000_RDH, 0); + e1000_putreg_mem(priv, E1000_RDT, 0); + + /* Disable interrupts */ + + e1000_putreg_mem(priv, E1000_IMC, priv->irqs); + up_disable_irq(priv->irq); + + /* Disable Transmiter */ + + e1000_putreg_mem(priv, E1000_TCTL, 0); + + /* Disable Receiver */ + + e1000_putreg_mem(priv, E1000_RCTL, 0); + + /* Free RX packets */ + + for (i = 0; i < E1000_RX_DESC; i += 1) + { + netpkt_free(&priv->dev, priv->rx_pkt[i], NETPKT_RX); + } +} + +/***************************************************************************** + * Name: e1000_enable + * + * Description: + * Enable device. + * + *****************************************************************************/ + +static void e1000_enable(FAR struct e1000_driver_s *priv) +{ + FAR struct netdev_lowerhalf_s *dev = (FAR struct netdev_lowerhalf_s *)priv; + int i = 0; + uint64_t pa = 0; + uint32_t regval = 0; + uint32_t fextnvm11 = 0; + + /* Errata for i219 - this is undocumented by Intel bug. + * Linux and BSD drivers include this workaround which was optimised by + * ipxe but no one except Intel engineers knows exactly wtha this does. + * For some exaplanaition look at 546dd51de8459d4d09958891f426fa2c73ff090d + * commit in ipxe. + */ + + if (priv->type->flags & E1000_RESET_BROKEN) + { + fextnvm11 = e1000_getreg_mem(priv, E1000_FEXTNVM11); + fextnvm11 |= E1000_FEXTNVM11_MAGIC; + e1000_putreg_mem(priv, E1000_FEXTNVM11, fextnvm11); + } + + /* Reset Multicast Table Array */ + + for (i = 0; i < priv->type->mta_regs; i++) + { + e1000_putreg_mem(priv, E1000_MTA + (i << 2), 0); + } + + /* Allocate RX packets */ + + for (i = 0; i < E1000_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; + e1000_putreg_mem(priv, E1000_TDBAL, regval); + regval = (uint32_t)(pa >> 32); + e1000_putreg_mem(priv, E1000_TDBAH, regval); + + regval = E1000_TX_DESC * sizeof(struct e1000_tx_leg_s); + e1000_putreg_mem(priv, E1000_TDLEN, regval); + + priv->tx_now = 0; + + /* Reset TX tail */ + + e1000_putreg_mem(priv, E1000_TDH, 0); + e1000_putreg_mem(priv, E1000_TDT, 0); + + /* Setup RX descriptor */ + + /* The address passed to the NIC must be physical */ + + pa = up_addrenv_va_to_pa(priv->rx); + + regval = (uint32_t)pa; + e1000_putreg_mem(priv, E1000_RDBAL, regval); + regval = (uint32_t)(pa >> 32); + e1000_putreg_mem(priv, E1000_RDBAH, regval); + + regval = E1000_RX_DESC * sizeof(struct e1000_rx_leg_s); + e1000_putreg_mem(priv, E1000_RDLEN, regval); + + priv->rx_now = 0; + + /* Reset RX tail */ + + e1000_putreg_mem(priv, E1000_RDH, 0); + e1000_putreg_mem(priv, E1000_RDT, E1000_RX_DESC); + + /* Enable interrupts */ + + e1000_putreg_mem(priv, E1000_IMS, priv->irqs); + up_enable_irq(priv->irq); + + /* Set link up and auto-detect speed */ + + regval = E1000_CTRL_SLU | E1000_CTRL_ASDE; + e1000_putreg_mem(priv, E1000_CTRL, regval); + + /* Setup and enable Transmiter */ + + regval = e1000_getreg_mem(priv, E1000_TCTL); + regval |= E1000_TCTL_EN | E1000_TCTL_PSP; + e1000_putreg_mem(priv, E1000_TCTL, regval); + + /* Setup and enable Receiver */ + + regval = E1000_RCTL_EN | E1000_RCTL_MPE | + (E1000_RCTL_BSIZE << E1000_RCTL_BSIZE_SHIFT) | + (E1000_RCTL_MO_4736 << E1000_RCTL_MO_SHIFT); +#ifdef CONFIG_NET_PROMISCUOUS + regval |= E1000_RCTL_UPE | E1000_RCTL_MPE; +#endif + e1000_putreg_mem(priv, E1000_RCTL, regval); + + /* REVISIT: Set granuality to Descriptors */ + + regval = e1000_getreg_mem(priv, E1000_RXDCTL); + regval |= E1000_RXDCTL_GRAN; + e1000_putreg_mem(priv, E1000_RXDCTL, regval); + +#ifdef CONFIG_DEBUG_NET_INFO + /* Dump memory */ + + e1000_dump_mem(priv, "enabled"); +#endif +} + +/***************************************************************************** + * Name: e1000_initialize + * + * Description: + * Initialize device + * + *****************************************************************************/ + +static int e1000_initialize(FAR struct e1000_driver_s *priv) +{ + uint32_t regval = 0; + uint64_t mac = 0; + int ret = OK; + + /* Make sure that interrupts are masked */ + + e1000_putreg_mem(priv, E1000_IMC, 0xffffffff); + + /* Allocate MSI */ + + ret = pci_alloc_irq(priv->pcidev, &priv->irq, 1); + if (ret != 1) + { + nerr("Failed to allocate MSI %d\n", ret); + return ret; + } + + /* Connect MSI */ + + ret = pci_connect_irq(priv->pcidev, &priv->irq, 1); + if (ret < 0) + { + nerr("Failed to connect MSI %d\n", ret); + pci_release_irq(priv->pcidev, &priv->irq, 1); + + /* Get legacy IRQ if MSI not supported */ + + priv->irq = pci_get_irq(priv->pcidev); + } + + /* Attach interupts */ + + irq_attach(priv->irq, e1000_interrupt, priv); + +#ifdef CONFIG_PCI_MSIX + /* Configure MSI-X */ + + if (priv->type->flags & E1000_HAS_MSIX) + { + e1000_putreg_mem(priv, E1000_IVAR, E1000_MSIX_IVAR); + priv->irqs = E1000_MSIX_INTERRUPTS; + } + else +#endif + { + priv->irqs = E1000_INTERRUPTS; + } + + /* Get MAC if valid */ + + regval = e1000_getreg_mem(priv, E1000_RAH); + if (regval & E1000_RAH_AV) + { + mac = ((uint64_t)regval & E1000_RAH_RAH_MASK) << 32; + mac |= e1000_getreg_mem(priv, E1000_RAL); + memcpy(&priv->dev.netdev.d_mac.ether, &mac, sizeof(struct ether_addr)); + } + else + { + nwarn("Receive Address not vaild!\n"); + } + + return OK; +} + +/***************************************************************************** + * Name: e1000_probe + * + * Description: + * Initialize device + * + *****************************************************************************/ + +static int e1000_probe(FAR struct pci_device_s *dev) +{ + FAR const struct e1000_type_s *type = NULL; + FAR struct e1000_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 e1000_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, + E1000_TX_DESC * sizeof(struct e1000_tx_leg_s)); + if (priv->tx == NULL) + { + nerr("alloc tx failed\n"); + goto errout; + } + + /* Allocate RX descriptors */ + + priv->rx = kmm_memalign(type->desc_align, + E1000_RX_DESC * sizeof(struct e1000_rx_leg_s)); + if (priv->rx == NULL) + { + nerr("alloc rx failed\n"); + goto errout; + } + + /* Allocate TX packet pointer array */ + + priv->tx_pkt = kmm_zalloc(E1000_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(E1000_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, E1000_MMIO_BAR); + if (!priv->base) + { + pcierr("Not found MMIO control bar\n"); + goto errout; + } + + /* Initialize PHYs, Ethernet interface, and setup up Ethernet interrupts */ + + ret = e1000_initialize(priv); + if (ret != OK) + { + nerr("e1000_initialize failed %d\n", ret); + goto errout; + } + + /* Register the network device */ + + netdev->quota[NETPKT_TX] = E1000_TX_QUOTA; + netdev->quota[NETPKT_RX] = E1000_RX_QUOTA; + netdev->ops = &g_e1000_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_e1000_init + * + * Description: + * Register a pci driver + * + *****************************************************************************/ + +int pci_e1000_init(void) +{ + return pci_register_driver(&g_e1000_drv); +} diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h new file mode 100644 index 0000000000..0650c69d07 --- /dev/null +++ b/drivers/net/e1000.h @@ -0,0 +1,443 @@ +/***************************************************************************** + * drivers/net/e1000.h + * + * 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_E1000_H +#define __DRIVERS_NET_E1000_H + +/***************************************************************************** + * Included Files + *****************************************************************************/ + +#include + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +/* General registers */ + +#define E1000_CTRL (0x0000) /* Device Control Register */ +#define E1000_STATUS (0x0008) /* Device Status Register */ +#define E1000_EEC (0x0010) /* EEPROM/FLASH Control Register */ +#define E1000_EERD (0x0014) /* EEPROM Read Register */ +#define E1000_CTRLEXT (0x0018) /* Extended Device Control Register */ +#define E1000_FLA (0x001c) /* Flash Access Register */ +#define E1000_MDIC (0x0020) /* MDI Control Register */ +#define E1000_FCAL (0x0028) /* Flow Control Address Low */ +#define E1000_FCAH (0x002c) /* Flow Control Address High */ +#define E1000_FCT (0x0030) /* Flow Control Type */ +#define E1000_VET (0x0038) /* VLAN Ether Type */ +#define E1000_FCTTV (0x0170) /* Flow Control Transmit Timer Value */ +#define E1000_FCRTV (0x5f40) /* Flow Control Refresh Threshold Value */ +#define E1000_LEDCTL (0x0e00) /* LED Control */ + +/* Interrupt registers */ + +#define E1000_ICR (0x00c0) /* Interrupt Cause Read */ +#define E1000_ICS (0x00c8) /* Interrupt Cause Set */ +#define E1000_IMS (0x00d0) /* Interrupt Mask Set */ +#define E1000_IMC (0x00d8) /* Interrupt Mask Clear */ +#define E1000_EIAC (0x00dc) /* Interrupt Auto Clear */ +#define E1000_IAM (0x00e0) /* Interrupt Acknowledge Auto–Mask */ +#define E1000_IVAR (0x00e4) /* Interrupt Vector Allocation Registers */ + +/* Transmit registers */ + +#define E1000_TCTL (0x0400) /* Transmit Control */ +#define E1000_TIPG (0x0410) /* Transmit IPG Register */ +#define E1000_AIT (0x0458) /* Adaptive IFS Throttle */ +#define E1000_TDBAL (0x3800) /* Tx Descriptor Base Address Low */ +#define E1000_TDBAH (0x3804) /* Tx Descriptor Base Address High */ +#define E1000_TDLEN (0x3808) /* Tx Descriptor Length */ +#define E1000_TDH (0x3810) /* Tx Descriptor Head */ +#define E1000_TDT (0x3818) /* Tx Descriptor Tail */ +#define E1000_TARC (0x3840) /* Transmit Arbitration Count */ +#define E1000_TIDV (0x3820) /* Transmit Interrupt Delay Value */ +#define E1000_TXDCTL (0x3828) /* Transmit Descriptor Control */ +#define E1000_TADV (0x382c) /* Transmit Absolute Interrupt Delay Value */ + +/* Receive registers */ + +#define E1000_RCTL (0x0100) /* Receive Control */ +#define E1000_PSRCTL (0x2170) /* Packet Split Receive Control Register */ +#define E1000_FCRTL (0x2160) /* Flow Control Receive Threshold Low */ +#define E1000_FCRTH (0x2168) /* Flow Control Receive Threshold High */ +#define E1000_RDBAL (0x2800) /* Rx Descriptor Base Address Low */ +#define E1000_RDBAH (0x2804) /* Rx Descriptor Base Address High */ +#define E1000_RDLEN (0x2808) /* Rx Descriptor Length */ +#define E1000_RDH (0x2810) /* Rx Descriptor Head */ +#define E1000_RDT (0x2818) /* Rx Descriptor Tail */ +#define E1000_RDTR (0x2820) /* Receive Delay Timer Register */ +#define E1000_RXDCTL (0x2828) /* Receive Descriptor Control */ +#define E1000_RADV (0x282c) /* Receive Interrupt Absolute Delay Timer */ +#define E1000_RSRPD (0x2c00) /* Receive Small Packet Detect Interrupt */ +#define E1000_RAID (0x2c08) /* Receive ACK Interrupt Delay Register */ +#define E1000_RXCSUM (0x5000) /* Receive Checksum Control */ +#define E1000_RFCTL (0x5008) /* Receive Filter Control Register */ +#define E1000_MTA (0x5200) /* Multicast Table Array */ +#define E1000_RAL (0x5400) /* Receive Address Low */ +#define E1000_RAH (0x5404) /* Receive Address High */ + +/* Statistic registers */ + +#define E1000_CRCERRS (0x04000) /* CRC Error Count */ +#define E1000_ALGNERRC (0x04004) /* Alignment Error Count */ +#define E1000_RXERRC (0x0400c) /* RX Error Count */ +#define E1000_MPC (0x04010) /* Missed Packets Count */ +#define E1000_SCC (0x04014) /* Single Collision Count */ +#define E1000_ECOL (0x04018) /* Excessive Collisions Count */ +#define E1000_MCC (0x0401c) /* Multiple Collision Count */ +#define E1000_LATECOL (0x04020) /* Late Collisions Count */ +#define E1000_COLC (0x04028) /* Collision Count */ +#define E1000_DC (0x04030) /* Defer Count */ +#define E1000_TNCRS (0x04034) /* Transmit with No CRS */ +#define E1000_CEXTERR (0x0403c) /* Carrier Extension Error Count */ +#define E1000_RLEC (0x04040) /* Receive Length Error Count */ +#define E1000_XONRXC (0x04048) /* XON Received Count */ +#define E1000_XONTXC (0x0404c) /* XON Transmitted Count */ +#define E1000_XOFFRXC (0x04050) /* XOFF Received Count */ +#define E1000_XOFFTXC (0x04054) /* XOFF Transmitted Count */ +#define E1000_FCRUC (0x04058) /* FC Received Unsupported Count */ +#define E1000_PRC64 (0x0405c) /* Packets Received [64 Bytes] Count */ +#define E1000_PRC127 (0x04060) /* Packets Received [65–127 Bytes] Count */ +#define E1000_PRC255 (0x04064) /* Packets Received [128–255 Bytes] */ +#define E1000_PRC511 (0x04068) /* Packets Received [256–511 Bytes] */ +#define E1000_PRC1023 (0x0406c) /* Packets Received [512–1023 Bytes] */ +#define E1000_PRC1522 (0x04070) /* Packets Received [1024 to Max Bytes] */ +#define E1000_GPRC (0x04074) /* Good Packets Received Count */ +#define E1000_BPRC (0x04078) /* Broadcast Packets Received Count */ +#define E1000_MPRC (0x0407c) /* Multicast Packets Received Count */ +#define E1000_GPTC (0x04080) /* Good Packets Transmitted Count */ +#define E1000_GORCL (0x04088) /* Good Octets Received Count Low */ +#define E1000_GORCH (0x0408c) /* Good Octets Received Count High */ +#define E1000_GOTCL (0x04090) /* Good Octets Transmitted Count Low */ +#define E1000_GOTCH (0x04094) /* Good Octets Transmitted Count High */ +#define E1000_RNBC (0x040a0) /* Receive No Buffers Count */ +#define E1000_RUC (0x040a4) /* Receive Undersize Count */ +#define E1000_RFC (0x040a8) /* Receive Fragment Count */ +#define E1000_ROC (0x040ac) /* Receive Oversize Count */ +#define E1000_RJC (0x040b0) /* Receive Jabber Count */ +#define E1000_MNGPRC (0x040b4) /* Management Packets Received Count */ +#define E1000_MPDC (0x040b8) /* Management Packets Dropped Count */ +#define E1000_MPTC (0x040bc) /* Management Packets Transmitted Count */ +#define E1000_TORL (0x040c0) /* Total Octets Received */ +#define E1000_TORH (0x040c4) /* Total Octets Received */ +#define E1000_TOT (0x040c8) /* Total Octets Transmitted */ +#define E1000_TPR (0x040d0) /* Total Packets Received */ +#define E1000_TPT (0x040d4) /* Total Packets Transmitted */ +#define E1000_PTC64 (0x040d8) /* Packets Transmitted [64 Bytes] Count */ +#define E1000_PTC127 (0x040dc) /* Packets Transmitted [65–127 Bytes] Count */ +#define E1000_PTC255 (0x040e0) /* Packets Transmitted [128–255 Bytes] Count */ +#define E1000_PTC511 (0x040e4) /* Packets Transmitted [256–511 Bytes] Count */ +#define E1000_PTC1023 (0x040e8) /* Packets Transmitted [512–1023 Bytes] Count */ +#define E1000_PTC1522 (0x040ec) /* Packets Transmitted [Greater than 1024 Bytes] Count */ +#define E1000_MCPTC (0x040f0) /* Multicast Packets Transmitted Count */ +#define E1000_BPTC (0x040f4) /* Broadcast Packets Transmitted Count */ +#define E1000_TSCTC (0x040f8) /* TCP Segmentation Context Transmitted Count */ +#define E1000_TSCTFC (0x040fc) /* TCP Segmentation Context Transmit Fail Count */ +#define E1000_IAC (0x04100) /* Interrupt Assertion Count */ + +/* Management registers */ + +#define E1000_WUC (0x5800) /* Wake Up Control Register */ +#define E1000_WUFC (0x5808) /* Wake Up Filter Control Register */ +#define E1000_WUS (0x5810) /* Wake Up Status Register */ +#define E1000_MFUTP01 (0x5828) /* Management Flex UDP/TCP Ports 0/1 */ +#define E1000_MFUTP23 (0x5830) /* Management Flex UDP/TCP Port 2/3 */ +#define E1000_IPAV (0x5838) /* IP Address Valid */ + +/* Diagnostic registers */ + +#define E1000_POEMB (0x00f10) /* PHY OEM Bits Register */ +#define E1000_RDFH (0x02410) /* Receive Data FIFO Head Register */ +#define E1000_FDFT (0x02418) /* Receive Data FIFO Tail Register */ +#define E1000_RDFHS (0x02420) /* Receive Data FIFO Head Saved Register */ +#define E1000_RDFTS (0x02428) /* Receive Data FIFO Tail Saved Register */ +#define E1000_RDFPC (0x02430) /* Receive Data FIFO Packet Count */ +#define E1000_TDFH (0x03410) /* Transmit Data FIFO Head Register */ +#define E1000_TDFT (0x03418) /* Transmit Data FIFO Tail Register */ +#define E1000_TDFHS (0x03420) /* Transmit Data FIFO Head Saved Register */ +#define E1000_TDFTS (0x03428) /* Transmit Data FIFO Tail Saved Register */ +#define E1000_TDFPC (0x03430) /* Transmit Data FIFO Packet Count */ +#define E1000_PBM (0x10000) /* Packet Buffer Memory */ +#define E1000_PBS (0x01008) /* Packet Buffer Size */ + +/* Device Control Register */ + +#define E1000_CTRL_FD (1 << 0) /* Bit 0: Full-Duplex */ + /* Bits 1-2: Reserved */ +#define E1000_CTRL_LRST (1 << 3) /* Bit 3: Link Reset */ + /* Bit 4: Reserved */ +#define E1000_CTRL_ASDE (1 << 5) /* Bit 5: Auto-Speed Detection Enable */ +#define E1000_CTRL_SLU (1 << 6) /* Bit 6: Set Link Up */ +#define E1000_CTRL_ILOS (1 << 7) /* Bit 7: Speed selection */ +#define E1000_CTRL_SPEED_SHIFT (8) /* Bits 8-9: Speed selection */ +#define E1000_CTRL_SPEED_MASK (3 << E1000_CTRL_SPEED_SHIFT) +# define E1000_CTRL_SPEED_10MBS (0 << E1000_CTRL_SPEED_SHIFT) +# define E1000_CTRL_SPEED_100MBS (1 << E1000_CTRL_SPEED_SHIFT) +# define E1000_CTRL_SPEED_1000MBS (2 << E1000_CTRL_SPEED_SHIFT) + /* Bit 10: Reserved */ +#define E1000_CTRL_FRCSPD (1 << 11) /* Bit 11: Force Speed */ +#define E1000_CTRL_FRCDPLX (1 << 12) /* Bit 12: Force Duplex */ + /* Bits 13-17: Reserved */ +#define E1000_CTRL_SDP0_DATA (1 << 18) /* Bit 18: SDP0 Data Value */ +#define E1000_CTRL_SDP1_DATA (1 << 19) /* Bit 19: SDP1 Data Value */ +#define E1000_CTRL_ADVD3WUC (1 << 20) /* Bit 20: D3Cold Wakeup Capability Advertisement Enable */ +#define E1000_CTRL_PWRMGMT (1 << 21) /* Bit 21: PHY Power-Management Enable */ +#define E1000_CTRL_SDP0_IODIR (1 << 22) /* Bit 22: SDP0 Pin Directionality */ +#define E1000_CTRL_SDP1_IODIR (1 << 23) /* Bit 23: SDP1 Pin Directionality */ + /* Bits 24-25: Reserved */ +#define E1000_CTRL_RST (1 << 26) /* Bit 26: Device Reset */ +#define E1000_CTRL_RFCE (1 << 27) /* Bit 27: Receive Flow Control Enable */ +#define E1000_CTRL_TFCE (1 << 28) /* Bit 28: Transmit Flow Control Enable */ + /* Bit 29: Reserved */ +#define E1000_CTRL_VME (1 << 30) /* Bit 30: VLAN Mode Enable */ +#define E1000_CTRL_PHYRST (1 << 31) /* Bit 31: PHY Reset */ + +/* Status Regiuster */ + +#define E1000_STATUS_FD (1 << 0) /* Bit 0: Full Duplex */ +#define E1000_STATUS_LU (1 << 1) /* Bit 1: Link Up */ + /* Bits 2-3: Reserved */ +#define E1000_STATUS_TXOFF (1 << 4) /* Bit 4: Transmission Paused */ + /* Bit 5: Reserved */ +#define E1000_STATUS_SPEED_SHFIT (5) /* Bits 6-7: Link speed setting */ +#define E1000_STATUS_ASDV_SHFIT (8) /* Bits 8-9: Auto-Speed Detection Value */ +#define E1000_STATUS_PHYRA (10) /* Bit 10: PHY Reset Asserted */ + /* Bits 11-18: Reserved */ +#define E1000_STATUS_GIOM (19) /* Bit 19: GIO Master Disable bit state */ + /* Bits 20-32: Reserved */ + +/* Receive Address High */ + +#define E1000_RAH_RAH_MASK (0xffff) /* Bits 0-15: Receive address High */ +#define E1000_RAH_AS (16) /* Bits 16-17 Address Select */ + /* Bits 18-30: Reserved */ +#define E1000_RAH_AV (1 << 31) /* Bit 31: Address Valid */ + +/* Transmit Control */ + + /* Bit 0: Reserved */ +#define E1000_TCTL_EN (1 << 1) /* Bit 1: Transmit Enable */ + /* Bit 2: Reserved */ +#define E1000_TCTL_PSP (1 << 3) /* Bit 3: Pad Short Packets */ +#define E1000_TCTL_CT_SHIFT (4) /* Bits 4-11: Collision Threshold */ +#define E1000_TCTL_COLD_SHIFT (12) /* Bits 12-21: Collision Distance */ +#define E1000_TCTL_SWXOFF (1 << 22) /* Bit 22: Software XOFF Transmission */ + /* Bit 23: Reserved */ +#define E1000_TCTL_RTLC (1 << 24) /* Bit 24: Re-transmit on Late Collision */ +#define E1000_TCTL_NRTU (1 << 25) /* Bit 25: No Re-transmit on underrun */ + /* Bits 26-32: Reserved */ + +/* Transmit Descriptor Control */ + +#define E1000_TXDCTL_PTHRESH_SHIFT (0) /* Bits 0-5: Prefetch Threshold */ + /* Bits 6-7: Reserved */ +#define E1000_TXDCTL_HTHRESH_SHIFT (8) /* Bits 8-13: Host Threshold */ + /* Bits 14-15: Reserved */ +#define E1000_TXDCTL_WTHRESH_SHIFT (16) /* Bits 16-21: Write-Back Threshold */ + /* Bits 22-23: Reserved */ +#define E1000_TXDCTL_GRAN (1 << 24) /* Bit 24: Granularity */ +#define E1000_TXDCTL_LWTHRESH_SHIFT (25) /* Bits 25-32: Transmit Descriptor Low Threshold */ + +/* Receive Control */ + + /* Bit 0: Reserved */ +#define E1000_RCTL_EN (1 << 1) /* Bit 1: Receiver Enable */ +#define E1000_RCTL_SBP (1 << 2) /* Bit 2: Store Bad Packets */ +#define E1000_RCTL_UPE (1 << 3) /* Bit 3: Unicast Promiscuous Enabled */ +#define E1000_RCTL_MPE (1 << 4) /* Bit 4: Multicast Promiscuous Enabled */ +#define E1000_RCTL_LPE (1 << 5) /* Bit 5: Long Packet Reception Enable */ +#define E1000_RCTL_LBM_SHIFT (6) /* Bits 6-7: Loopback mode */ +#define E1000_RCTL_RDMTS_SHIFT (8) /* Bits 8-9: Receive Descriptor Minimum Threshold Size */ + /* Bits 10-11: Reserved */ +#define E1000_RCTL_MO_SHIFT (12) /* Bits 12-13: Multicast Offset */ +# define E1000_RCTL_MO_4736 (0) /* 0: bit 47:36 */ +# define E1000_RCTL_MO_4635 (1) /* 1: bit 46:35 */ +# define E1000_RCTL_MO_4535 (2) /* 2: bit 45:34 */ +# define E1000_RCTL_MO_4332 (3) /* 3: bit 43:32 */ + /* Bit 14: Reserved */ +#define E1000_RCTL_BAM (1 << 15) /* Bit 15: Broadcast Accept Mode */ +#define E1000_RCTL_BSIZE_SHIFT (16) /* Bits 16-17: Receive Buffer Size */ +# define E1000_RCTL_BSIZE_2048 (0 << 16) /* 00b: 2048 bytes */ +# define E1000_RCTL_BSIZE_1024 (1 << 16) /* 01b: 1024 bytes */ +# define E1000_RCTL_BSIZE_512 (2 << 16) /* 10b: 512 bytes */ +# define E1000_RCTL_BSIZE_256 (3 << 16) /* 11b: 256 bytes */ + /* 00b: Reserved */ +# define E1000_RCTL_BSIZE_16384 (1 << 16) /* 00b: 16384 bytes */ +# define E1000_RCTL_BSIZE_8192 (2 << 16) /* 01b: 8192 bytes */ +# define E1000_RCTL_BSIZE_4096 (3 << 16) /* 10b: 4096 bytes */ +#define E1000_RCTL_VFE (1 << 18) /* Bit 18: VLAN Filter Enable */ +#define E1000_RCTL_CFIEN (1 << 18) /* Bit 19: Canonical Form Indicator Enable */ +#define E1000_RCTL_CFI (1 << 20) /* Bit 20: Canonical Form Indicator bit value */ + /* Bit 21: Reserved */ +#define E1000_RCTL_DPF (1 << 22) /* Bit 22: Discard Pause Frames */ +#define E1000_RCTL_PMCF (1 << 23) /* Bit 23: Pass MAC Control Frames */ + /* Bit 24: Reserved */ +#define E1000_RCTL_BSEX (1 << 25) /* Bit 25: Buffer Size Extension */ +#define E1000_RCTL_SECRC (1 << 26) /* Bit 26: Strip Ethernet CRC from incoming packet */ + /* Bits 27-31: Reserved */ + +/* Receive Descriptor Control */ + +#define E1000_RXDCTL_PTHRESH_SHIFT (0) /* Bits 0-5: Prefetch Threshold */ + /* Bits 6-7: Reserved */ +#define E1000_RXDCTL_HTHRESH_SHIFT (8) /* Bits 8-13: Host Threshold */ + /* Bits 14-15: Reserved */ +#define E1000_RXDCTL_WTHRESH_SHIFT (16) /* Bits 16-21: Write-Back Threshold */ + /* Bits 22-23: Reserved */ +#define E1000_RXDCTL_GRAN (1 << 24) /* Bit 24: Granularity */ + /* Bits 25-32: Reserved */ + +/* Receive Delay Timer Register */ + +#define E1000_RDTR_DELAY_MASK (0xffff) /* Bits 0-15: Receive delay timer */ +#define E1000_RDTR_FPD (1 << 31) /* Bit 31: Flush partial descriptor block */ + +/* Interrupt Cause */ + +#define E1000_IC_TXDW (1 << 0) /* Bit 0: Transmit Descriptor Written Back */ +#define E1000_IC_TXQE (1 << 1) /* Bit 1: Transmit Queue Empty */ +#define E1000_IC_LSC (1 << 2) /* Bit 2: Link Status Change */ +#define E1000_IC_RXSEQ (1 << 3) /* Bit 3: Receive Sequence Error */ +#define E1000_IC_RXDMT0 (1 << 4) /* Bit 4: Receive Descriptor Minimum Threshold Reached */ + /* Bit 5: Reserved */ +#define E1000_IC_RXO (1 << 6) /* Bit 6: Receiver Overrun */ +#define E1000_IC_RXT0 (1 << 7) /* Bit 7: Receiver Timer Interrupt */ + /* Bit 8: Reserved */ +#define E1000_IC_MDAC (1 << 9) /* Bit 9: MDI/O Access Complete */ +#define E1000_IC_RXCFG (1 << 10) /* Bit 10: Receiving /C/ ordered sets */ + /* Bit 11: Reserved */ +#define E1000_IC_PHYINT (1 << 12) /* Bit 12: PHY Interrupt */ +#define E1000_IC_GPISDP6 (1 << 13) /* Bit 13: General Purpose Interrupt on SDP6[2] */ +#define E1000_IC_GPISDP7 (1 << 14) /* Bit 14: General Purpose Interrupt on SDP7[3] */ +#define E1000_IC_TXDLOW (1 << 15) /* Bit 15: Transmit Descriptor Low Threshold hit */ +#define E1000_IC_SRPD (1 << 16) /* Bit 16: Small Receive Packet Detected */ + /* Bits 17-20: Reserved */ +#define E1000_IC_RXQ0 (1 << 20) /* Bit 20: Receive Queue 0 Interrupt */ +#define E1000_IC_RXQ1 (1 << 21) /* Bit 21: Receive Queue 1 Interrupt */ +#define E1000_IC_TXQ0 (1 << 22) /* Bit 22: Transmit Queue 0 Interrupt */ +#define E1000_IC_TXQ1 (1 << 23) /* Bit 23: Transmit Queue 1 Interrupt */ +#define E1000_IC_OTHER (1 << 24) /* Bit 24: Other Interrupt */ + /* Bits 25-30: Reserved */ +#define E1000_IC_ASSERTED (1 << 31) /* Bit 31: Interrupt Asserted */ + +/* Interrupt Vector Allocation Registers */ + +#define E1000_IVAR_RXQ0_SHIFT (0) /* Bits 0-2: MSI-X vector assigned to RxQ0 */ +#define E1000_IVAR_RXQ0_EN (1 << 3) /* Bit 3: Enable bit for RxQ0 */ +#define E1000_IVAR_RXQ1_SHIFT (4) /* Bits 4-6: MSI-X vector assigned to RxQ1 */ +#define E1000_IVAR_RXQ1_EN (1 << 7) /* Bit 7: Enable bit for RxQ1 */ +#define E1000_IVAR_TXQ0_SHIFT (8) /* Bits 8-10: MSI-X vector assigned to TxQ0 */ +#define E1000_IVAR_TXQ0_EN (1 << 11) /* Bit 11: Enable bit for TxQ0 */ +#define E1000_IVAR_TXQ1_SHIFT (12) /* Bits 12-14: MSI-X vector assigned to TxQ1 */ +#define E1000_IVAR_TXQ1_EN (1 << 15) /* Bit 15: Enable bit for TxQ1 */ +#define E1000_IVAR_OTHER_SHIFT (16) /* Bits 16-18: MSI-X vector assigned to Ohter Cause */ +#define E1000_IVAR_OTHER_EN (1 << 19) /* Bit 19: Enable bit for Ohter Cause */ + /* Bits 20-30: Reserved */ +#define E1000_IVAR_ONALLWB (1 << 31) /* Bit 31: Tx interrupts occur on every write back */ + +/* Transmit Descriptor Command Field */ + +#define E1000_TDESC_CMD_EOP (1 << 0) /* Bit 0: End Of Packet */ +#define E1000_TDESC_CMD_IFCS (1 << 1) /* Bit 1: Insert FCS */ +#define E1000_TDESC_CMD_IC (1 << 2) /* Bit 2: Insert Checksum */ +#define E1000_TDESC_CMD_RS (1 << 3) /* Bit 3: Report Status */ +#define E1000_TDESC_CMD_RPS (1 << 4) /* Bit 4: Report Packet Sent */ +#define E1000_TDESC_CMD_DEXT (1 << 5) /* Bit 5: Extension (0b for legacy mode) */ +#define E1000_TDESC_CMD_VLE (1 << 6) /* Bit 6: VLAN Packet Enable */ +#define E1000_TDESC_CMD_IDE (1 << 7) /* Bit 7: Interrupt Delay Enable */ + +/* Transmit Descriptor Status Field */ + +#define E1000_TDESC_STATUS_DD (1 << 0) /* Bit 0: Descriptor Done */ +#define E1000_TDESC_STATUS_EC (1 << 1) /* Bit 1: Excess Collisions */ +#define E1000_TDESC_STATUS_LC (1 << 2) /* Bit 2: Late Collision */ +#define E1000_TDESC_STATUS_RSU (1 << 3) /* Bit 3: Transmit Underrun */ + +/* Transmit Descriptor Special Field */ + +#define E1000_TDESC_SPEC_VLAN_SHIFT (0) /* Bits 0-11: VLAN Identifier */ +#define E1000_TDESC_SPEC_CFI (1 << 12) /* Bit 12: Canonical Form Indicator */ +#define E1000_TDESC_SPEC_PRI_SHIFT (13) /* Bits 13-15: User Priority */ + +/* Receive Descriptor Status Field */ + +#define E1000_RDESC_STATUS_DD (1 << 0) /* Bit 0: Descriptor Done */ +#define E1000_RDESC_STATUS_EOP (1 << 1) /* Bit 1: End of Packet */ +#define E1000_RDESC_STATUS_IXSM (1 << 2) /* Bit 2: Ignore Checksum Indication */ +#define E1000_RDESC_STATUS_VP (1 << 3) /* Bit 3: Packet is 802.1Q (matched VET) */ +#define E1000_RDESC_STATUS_RSV (1 << 4) /* Bit 4: Reserved */ +#define E1000_RDESC_STATUS_TCPCS (1 << 5) /* Bit 5: TCP Checksum Calculated on Packet */ +#define E1000_RDESC_STATUS_IPCS (1 << 6) /* Bit 6: IP Checksum Calculated on Packet */ +#define E1000_RDESC_STATUS_PIF (1 << 7) /* Bit 7: Passed in-exact filter */ + +/* Receive Descriptor Errors Field */ + +#define E1000_RDESC_ERRORS_CE (1 << 0) /* Bit 0: CRC Error or Alignment Error */ +#define E1000_RDESC_ERRORS_SE (1 << 1) /* Bit 1: Symbol Error */ +#define E1000_RDESC_ERRORS_SEQ (1 << 2) /* Bit 2: Sequence Error */ +#define E1000_RDESC_ERRORS_RSV (1 << 3) /* Bit 3: Reserved */ +#define E1000_RDESC_ERRORS_CXE (1 << 4) /* Bit 4: Carrier Extension Error */ +#define E1000_RDESC_ERRORS_TCPE (1 << 5) /* Bit 5: TCP/UDP Checksum Error */ +#define E1000_RDESC_ERRORS_IPE (1 << 6) /* Bit 6: IP Checksum Error */ +#define E1000_RDESC_ERRORS_RXE (1 << 7) /* Bit 7: RX Data Error */ + +/* Receive Descriptor Special Field */ + +#define E1000_RDESC_SPEC_VLAN_SHIFT (0) /* Bits 0-11: VLAN Identifier */ +#define E1000_RDESC_SPEC_CFI (1 << 12) /* Bit 12: Canonical Form Indicator */ +#define E1000_RDESC_SPEC_PRI_SHIFT (13) /* Bits 13-15: User Priority */ + +/* Future Extended NVM register 11 */ + +#define E1000_FEXTNVM11 0x05bbc +#define E1000_FEXTNVM11_MAGIC 0x00002000 /* Some magic number */ + +/***************************************************************************** + * Public Types + *****************************************************************************/ + +/* Legacy TX descriptor */ + +begin_packed_struct struct e1000_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 e1000_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_E1000_H */ diff --git a/drivers/pci/pci_drivers.c b/drivers/pci/pci_drivers.c index 4247d7340b..e839515384 100644 --- a/drivers/pci/pci_drivers.c +++ b/drivers/pci/pci_drivers.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "pci_drivers.h" @@ -114,6 +115,16 @@ int pci_register_drivers(void) } #endif + /* Initialization e1000 driver */ + +#ifdef CONFIG_NET_E1000 + ret = pci_e1000_init(); + if (ret < 0) + { + pcierr("pci_e1000_init failed, ret=%d\n", ret); + } +#endif + UNUSED(ret); return ret; } diff --git a/include/nuttx/net/e1000.h b/include/nuttx/net/e1000.h new file mode 100644 index 0000000000..83ad6d44ad --- /dev/null +++ b/include/nuttx/net/e1000.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * include/nuttx/net/e1000.h + * + * 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_E1000_H +#define __INCLUDE_NUTTX_NET_E1000_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pci_e1000_init + * + * Description: + * Register a pci driver + * + ****************************************************************************/ + +int pci_e1000_init(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_E1000_H */