[PATCH 13/17] libchip: Add dwmac 10/100/100 network driver

Gedare Bloom gedare at rtems.org
Wed Feb 26 19:10:13 UTC 2014


Please fix the Doxygen.

On Wed, Feb 26, 2014 at 5:52 AM, Ralf Kirchner
<ralf.kirchner at embedded-brains.de> wrote:
> ---
>  c/src/libchip/Makefile.am                          |   11 +-
>  c/src/libchip/network/README.dwmac                 |   25 +
>  c/src/libchip/network/dwmac-1000-core.c            |  240 ++
>  c/src/libchip/network/dwmac-1000-dma.c             |  246 ++
>  .../libchip/network/dwmac-1000-ethernet-mac-ops.c  |   35 +
>  c/src/libchip/network/dwmac-common.h               |  372 ++++
>  c/src/libchip/network/dwmac-core.c                 |  408 ++++
>  c/src/libchip/network/dwmac-core.h                 |   78 +
>  c/src/libchip/network/dwmac-desc-com.c             |   62 +
>  c/src/libchip/network/dwmac-desc-com.h             |   46 +
>  c/src/libchip/network/dwmac-desc-enh.c             | 1053 +++++++++
>  c/src/libchip/network/dwmac-desc.h                 |  257 +++
>  c/src/libchip/network/dwmac-regs.h                 |  515 +++++
>  c/src/libchip/network/dwmac.c                      | 2341 ++++++++++++++++++++
>  c/src/libchip/network/dwmac.h                      |  867 ++++++++
>  c/src/libchip/preinstall.am                        |    4 +
>  16 Dateien geändert, 6559 Zeilen hinzugefügt(+), 1 Zeile entfernt(-)
>  create mode 100644 c/src/libchip/network/README.dwmac
>  create mode 100644 c/src/libchip/network/dwmac-1000-core.c
>  create mode 100644 c/src/libchip/network/dwmac-1000-dma.c
>  create mode 100644 c/src/libchip/network/dwmac-1000-ethernet-mac-ops.c
>  create mode 100644 c/src/libchip/network/dwmac-common.h
>  create mode 100644 c/src/libchip/network/dwmac-core.c
>  create mode 100644 c/src/libchip/network/dwmac-core.h
>  create mode 100644 c/src/libchip/network/dwmac-desc-com.c
>  create mode 100644 c/src/libchip/network/dwmac-desc-com.h
>  create mode 100644 c/src/libchip/network/dwmac-desc-enh.c
>  create mode 100644 c/src/libchip/network/dwmac-desc.h
>  create mode 100644 c/src/libchip/network/dwmac-regs.h
>  create mode 100644 c/src/libchip/network/dwmac.c
>  create mode 100644 c/src/libchip/network/dwmac.h
>
> diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am
> index eb0d015..003c3c1 100644
> --- a/c/src/libchip/Makefile.am
> +++ b/c/src/libchip/Makefile.am
> @@ -44,11 +44,20 @@ libnetchip_a_SOURCES = network/cs8900.c network/dec21140.c network/i82586.c \
>  libnetchip_a_SOURCES += network/greth.c
>  include_libchip_HEADERS += network/smc91111.h network/smc91111exp.h
>  libnetchip_a_SOURCES += network/smc91111.c network/smc91111config.h
> +include_libchip_HEADERS += network/dwmac.h
> +libnetchip_a_SOURCES +=                 \
> +  network/dwmac-1000-core.c             \
> +  network/dwmac-1000-dma.c              \
> +  network/dwmac-1000-ethernet-mac-ops.c \
> +  network/dwmac-core.c                  \
> +  network/dwmac-desc-com.c              \
> +  network/dwmac-desc-enh.c              \
> +  network/dwmac.c
>  endif
>
>  EXTRA_DIST += network/README network/README.cs8900 network/README.dec21140 \
>      network/README.i82586 network/README.open_eth network/README.sonic \
> -    network/cs8900.c.bsp network/README.tulipclone
> +    network/cs8900.c.bsp network/README.tulipclone network/README.dwmac
>
>  # rtc
>  include_libchip_HEADERS += rtc/rtc.h rtc/icm7170.h rtc/m48t08.h \
> diff --git a/c/src/libchip/network/README.dwmac b/c/src/libchip/network/README.dwmac
> new file mode 100644
> index 0000000..4fd1622
> --- /dev/null
> +++ b/c/src/libchip/network/README.dwmac
> @@ -0,0 +1,25 @@
> +About
> +=====
> +The dwmac* files implement libchip driver for the DWMAC 10/100/1000
> +ethernet MAC. The DWMAC 10/100/1000 ethernet MAC is a Synopsys IP core.
> +
> +Target Support
> +==============
> +
> +The target is required to provide the low level support routines as
> +listed in the Configuration section of this file.
> +
> +The file cs8900.[ch].bsp are an example BSP files for DIMMPC target.
> +
> +Conditionals
> +============
> +None
> +
> +Todo
> +====
> ++ Add support for DWMAC 10/100. currently only support for DWMAC 1000
> +  is implemented
> +
> +Configuration
> +=============
> +See the dwmac.h header file for the documentation.
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-1000-core.c b/c/src/libchip/network/dwmac-1000-core.c
> new file mode 100644
> index 0000000..f754d34
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-1000-core.c
> @@ -0,0 +1,240 @@
> +/**
> + * @file dwmac-1000-core.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 1000 on-chip Ethernet controllers Core Handling
> + *
> + * Functions and data which are specific to the DWMAC 1000 Core Handling.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <assert.h>
> +#include "dwmac-core.h"
> +#include "dwmac-common.h"
> +
> +#define DWMAC_1000_CORE_DEBUG
> +
> +//#undef DWMAC_1000_CORE_DEBUG
> +#ifdef DWMAC_1000_CORE_DEBUG
> +#define DWMAC_1000_CORE_PRINT_DBG( fmt, args ... )  printk( fmt, ## args )
> +#else
> +#define DWMAC_1000_CORE_PRINT_DBG( fmt, args ... )  do { } while ( 0 )
> +#endif
> +
> +#define DWMAC_1000_CORE_INIT \
> +  ( \
> +    ( MACGRP_MAC_CONFIGURATION_JD \
> +      | MACGRP_MAC_CONFIGURATION_BE ) \
> +    & ~MACGRP_MAC_CONFIGURATION_PS \
> +  )
> +
> +#define DWMAC_1000_CORE_HASH_TABLE_SIZE 256
> +
> +static volatile uint32_t *dwmac_1000_core_get_mac_addr_low(
> +  dwmac_common_context *self,
> +  const unsigned int    mac_addr_index )
> +{
> +  volatile uint32_t *addr = NULL;
> +
> +  assert( self != NULL );
> +  assert( mac_addr_index <= 127 );
> +
> +  if ( mac_addr_index > 15 ) {
> +    addr = &self->macgrp->mac_addr16_127[mac_addr_index].low;
> +  } else {
> +    addr = &self->macgrp->mac_addr0_15[mac_addr_index].low;
> +  }
> +
> +  return addr;
> +}
> +
> +static volatile uint32_t *dwmac_1000_core_get_mac_addr_high(
> +  dwmac_common_context *self,
> +  const unsigned int    mac_addr_index )
> +{
> +  volatile uint32_t *addr = NULL;
> +
> +  assert( self != NULL );
> +  assert( mac_addr_index <= 127 );
> +
> +  if ( mac_addr_index > 15 ) {
> +    addr = &self->macgrp->mac_addr16_127[mac_addr_index].high;
> +  } else {
> +    addr = &self->macgrp->mac_addr0_15[mac_addr_index].high;
> +  }
> +
> +  return addr;
> +}
> +
> +static void dwmac_1000_core_init( dwmac_common_context *self )
> +{
> +  uint32_t value = self->macgrp->mac_configuration;
> +
> +  value |= DWMAC_1000_CORE_INIT;
> +
> +  if ( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_RXTYP1COE ) != 0
> +       || ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_RXTYP2COE ) != 0 ) {
> +    /* Enable RX checksum calculation offload to hardware */
> +    value |= MACGRP_MAC_CONFIGURATION_IPC;
> +  }
> +
> +  /* No Jumbo- or Giant frames. The network stack does not support them */
> +  value                          &= ~MACGRP_MAC_CONFIGURATION_JE;
> +  value                          &= ~MACGRP_MAC_CONFIGURATION_TWOKPE;
> +  self->macgrp->mac_configuration = value;
> +
> +  /* Mask GMAC interrupts */
> +  self->macgrp->interrupt_mask =
> +    MACGRP_INTERRUPT_MASK_RGSMIIIM
> +    | MACGRP_INTERRUPT_MASK_PCSLCHGIM
> +    | MACGRP_INTERRUPT_MASK_PCSANCIM
> +    | MACGRP_INTERRUPT_MASK_TSIM;
> +
> +  /* mask out interrupts because we don't handle them yet */
> +  self->macgrp->mmc_receive_interrupt_mask     = ( uint32_t ) ~0L;
> +  self->macgrp->mmc_transmit_interrupt_mask    = ( uint32_t ) ~0L;
> +  self->macgrp->mmc_ipc_receive_interrupt_mask = ( uint32_t ) ~0L;
> +}
> +
> +static void dwmac_1000_core_set_umac_addr(
> +  dwmac_common_context *self,
> +  const uint8_t        *addr,
> +  unsigned int          reg_n )
> +{
> +  dwmac_core_set_mac_addr(
> +    addr,
> +    dwmac_1000_core_get_mac_addr_high( self, reg_n ),
> +    dwmac_1000_core_get_mac_addr_low( self, reg_n )
> +    );
> +}
> +
> +static void dwmac_1000_core_set_hash_filter(
> +  dwmac_common_context *self,
> +  const bool            add,
> +  struct ifreq         *ifr )
> +{
> +  int            eno = 0;
> +  struct arpcom *ac  = &self->arpcom;
> +
> +  if ( add ) {
> +    eno = ether_addmulti( ifr, ac );
> +  } else {
> +    eno = ether_delmulti( ifr, ac );
> +  }
> +
> +  if ( eno == ENETRESET ) {
> +    struct ether_multistep step;
> +    struct ether_multi    *enm;
> +    unsigned int           num_multi = 0;
> +    unsigned int           index;
> +
> +    ETHER_FIRST_MULTI( step, ac, enm );
> +
> +    while ( enm != NULL ) {
> +      /* Find out how many multicast addresses we have to handle */
> +      uint64_t addrlo = 0;
> +      uint64_t addrhi = 0;
> +
> +      memcpy( &addrlo, enm->enm_addrlo, ETHER_ADDR_LEN );
> +      memcpy( &addrhi, enm->enm_addrhi, ETHER_ADDR_LEN );
> +      num_multi += 1U + (uint32_t) ( addrhi - addrlo );
> +    }
> +
> +    if ( num_multi > DWMAC_1000_CORE_HASH_TABLE_SIZE ) {
> +      /* Too many addresses to be hashed, Use the
> +       * pass all multi option instead */
> +
> +      for ( index = 0; index < 8; ++index ) {
> +        self->macgrp->hash_table_reg[index] = 0xffffffff;
> +      }
> +
> +      self->macgrp->mac_frame_filter |= MACGRP_MAC_FRAME_FILTER_PM;
> +    } else if ( num_multi > 0 ) {
> +      uint32_t hash_shadow[8] = {0, 0, 0, 0, 0, 0, 0, 0};
> +      ETHER_FIRST_MULTI( step, ac, enm );
> +
> +      while ( enm != NULL ) {
> +        uint64_t addrlo = 0;
> +        uint64_t addrhi = 0;
> +
> +        memcpy( &addrlo, enm->enm_addrlo, ETHER_ADDR_LEN );
> +        memcpy( &addrhi, enm->enm_addrhi, ETHER_ADDR_LEN );
> +
> +        while ( addrlo <= addrhi ) {
> +          /* XXX: ether_crc32_le() does not work, why? */
> +          uint32_t crc = ether_crc32_be( (uint8_t *) &addrlo, ETHER_ADDR_LEN );
> +
> +          /* The upper 8 bits of the bit reversed 32 bit CRC are used for hash filtering.
> +           * The most significant bits determine the register to be used and the
> +           * least significant five bits determine which bit to be set within the register */
> +          uint32_t index_reg = ( crc >> 29 ) & 0x7;
> +          uint32_t index_bit = ( crc >> 24 ) & 0x1f;
> +
> +          hash_shadow[index_reg] |= 1U << index_bit;
> +          ++addrlo;
> +        }
> +
> +        ETHER_NEXT_MULTI( step, enm );
> +      }
> +
> +      for ( index = 0; index < 8; ++index ) {
> +        self->macgrp->hash_table_reg[index] = hash_shadow[index];
> +      }
> +
> +      /* Hash filter for multicast */
> +      self->macgrp->mac_frame_filter |= MACGRP_MAC_FRAME_FILTER_HMC;
> +    } else {
> +      /* Set all hash registers to accect to accept no multicast packets */
> +      for ( index = 0; index < 8; ++index ) {
> +        self->macgrp->hash_table_reg[index] = 0x00000000;
> +      }
> +
> +      /* Hash filter for multicast */
> +      self->macgrp->mac_frame_filter |= MACGRP_MAC_FRAME_FILTER_HMC;
> +    }
> +
> +    DWMAC_1000_CORE_PRINT_DBG(
> +      "Frame Filter reg: 0x%08x\n",
> +      self->macgrp->mac_frame_filter
> +      );
> +    DWMAC_1000_CORE_PRINT_DBG(
> +      "Hash regs:\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n"
> +      "0x%08x\n",
> +      self->macgrp->hash_table_reg[0],
> +      self->macgrp->hash_table_reg[1],
> +      self->macgrp->hash_table_reg[2],
> +      self->macgrp->hash_table_reg[3],
> +      self->macgrp->hash_table_reg[4],
> +      self->macgrp->hash_table_reg[5],
> +      self->macgrp->hash_table_reg[6],
> +      self->macgrp->hash_table_reg[7]
> +      );
> +  }
> +}
> +
> +const dwmac_common_core_ops dwmac_core_ops_1000 = {
> +  .core_init       = dwmac_1000_core_init,
> +  .set_hash_filter = dwmac_1000_core_set_hash_filter,
> +  .set_umac_addr   = dwmac_1000_core_set_umac_addr,
> +};
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-1000-dma.c b/c/src/libchip/network/dwmac-1000-dma.c
> new file mode 100644
> index 0000000..660f681
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-1000-dma.c
> @@ -0,0 +1,246 @@
> +/**
> + * @file dwmac-1000-dma.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 1000 on-chip Ethernet controllers DMA handling
> + *
> + * Functions and data which are specific to the DWMAC 1000 DMA Handling.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <errno.h>
> +#include "dwmac-core.h"
> +#include "dwmac-common.h"
> +
> +typedef enum {
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_64  = 0x00000000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_128 = 0x00004000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_192 = 0x00008000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_256 = 0x0000c000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_40  = 0x00010000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_32  = 0x00014000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_24  = 0x00018000,
> +  DWMAC100_OPERATION_MODE_TTC_CONTROL_16  = 0x0001c000,
> +} dwmac1000_operation_mode_ttc_control;
> +
> +typedef enum {
> +  DWMAC100_OPERATION_MODE_RTC_CONTROL_64  = 0x00000000,
> +  DWMAC100_OPERATION_MODE_RTC_CONTROL_32  = 0x00000008,
> +  DWMAC100_OPERATION_MODE_RTC_CONTROL_96  = 0x00000010,
> +  DWMAC100_OPERATION_MODE_RTC_CONTROL_128 = 0x00000018,
> +} dwmac1000_operation_mode_rtc_control;
> +
> +static int dwmac1000_dma_init(
> +  dwmac_common_context *self,
> +  const uint32_t        pbl,
> +  const uint32_t        fb,
> +  const uint32_t        mb,
> +  const bool            use_enhanced_desc,
> +  const uint32_t        burst_len_4_support,
> +  const uint32_t        burst_len_8_support,
> +  const uint32_t        burst_len_16_support,
> +  const uint32_t        burst_boundary,
> +  volatile dwmac_desc  *dma_tx,
> +  volatile dwmac_desc  *dma_rx )
> +{
> +  int      eno   = 0;
> +  uint32_t value = self->dmagrp->bus_mode;
> +  int      limit = 10;
> +
> +
> +  /* DMA SW reset */
> +  value                 |= DMAGRP_BUS_MODE_SWR;
> +  self->dmagrp->bus_mode = value;
> +
> +  while ( limit-- ) {
> +    if ( !( self->dmagrp->bus_mode & DMAGRP_BUS_MODE_SWR ) )
> +      break;
> +
> +    rtems_task_wake_after( rtems_clock_get_ticks_per_second() / 100 );
> +  }
> +
> +  if ( limit < 0 ) {
> +    eno = EBUSY;
> +  } else {
> +    /*
> +     * Set the DMA PBL (Programmable Burst Length) mode
> +     */
> +    if ( pbl >= DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_8 ) {
> +      value =
> +        DMAGRP_BUS_MODE_PBL( ( pbl + 1 ) / 8 ) | DMAGRP_BUS_MODE_RPBL(
> +          ( pbl + 1 ) / 8 ) | DMAGRP_BUS_MODE_EIGHTXPBL;
> +    } else {
> +      value = DMAGRP_BUS_MODE_PBL( pbl + 1 ) | DMAGRP_BUS_MODE_RPBL( pbl + 1 );
> +    }
> +
> +    /* Set the Fixed burst mode */
> +    if ( fb ) {
> +      value |= DMAGRP_BUS_MODE_FB;
> +    }
> +
> +    /* Mixed Burst has no effect when fb is set */
> +    if ( mb ) {
> +      value |= DMAGRP_BUS_MODE_MB;
> +    }
> +
> +    if ( use_enhanced_desc ) {
> +      value |= DMAGRP_BUS_MODE_ATDS;
> +    }
> +
> +    self->dmagrp->bus_mode = value;
> +
> +    /* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
> +     * for supported bursts.
> +     *
> +     * Note: This is applicable only for revision GMACv3.61a. For
> +     * older version this register is reserved and shall have no
> +     * effect.
> +     *
> +     * Note:
> +     *  For Fixed Burst Mode: if we directly write 0xFF to this
> +     *  register using the configurations pass from platform code,
> +     *  this would ensure that all bursts supported by core are set
> +     *  and those which are not supported would remain ineffective.
> +     *
> +     *  For Non Fixed Burst Mode: provide the maximum value of the
> +     *  burst length. Any burst equal or below the provided burst
> +     *  length would be allowed to perform. */
> +    value = self->dmagrp->axi_bus_mode;
> +
> +    if ( burst_len_4_support ) {
> +      value |= DMAGRP_AXI_BUS_MODE_BLEND4;
> +    } else {
> +      value &= ~DMAGRP_AXI_BUS_MODE_BLEND4;
> +    }
> +
> +    if ( burst_len_8_support ) {
> +      value |= DMAGRP_AXI_BUS_MODE_BLEND8;
> +    } else {
> +      value &= ~DMAGRP_AXI_BUS_MODE_BLEND8;
> +    }
> +
> +    if ( burst_len_16_support ) {
> +      value |= DMAGRP_AXI_BUS_MODE_BLEND16;
> +    } else {
> +      value &= ~DMAGRP_AXI_BUS_MODE_BLEND16;
> +    }
> +
> +    if ( burst_boundary ) {
> +      value |= DMAGRP_AXI_BUS_MODE_ONEKBBE;
> +    } else {
> +      value &= ~DMAGRP_AXI_BUS_MODE_ONEKBBE;
> +    }
> +
> +    self->dmagrp->axi_bus_mode = value;
> +
> +    /* Mask interrupts by writing to CSR7 */
> +    dwmac_core_enable_dma_irq_rx( self );
> +    dwmac_core_enable_dma_irq_tx( self );
> +
> +    /* The base address of the RX/TX descriptor lists must be written into
> +     * DMA CSR3 and CSR4, respectively. */
> +    self->dmagrp->transmit_descr_list_addr = (uintptr_t) &dma_tx[0];
> +    self->dmagrp->receive_descr_list_addr  = (uintptr_t) &dma_rx[0];
> +  }
> +
> +  return eno;
> +}
> +
> +static void dwmac1000_dma_operation_mode(
> +  dwmac_common_context *self,
> +  const unsigned int    txmode,
> +  const unsigned int    rxmode )
> +{
> +  uint32_t value = self->dmagrp->operation_mode;
> +
> +
> +  if ( txmode == DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD ) {
> +    /* Transmit COE type 2 cannot be done in cut-through mode. */
> +    value |= DMAGRP_OPERATION_MODE_TSF;
> +
> +    /* Operating on second frame increase the performance
> +     * especially when transmit store-and-forward is used.*/
> +    value |= DMAGRP_OPERATION_MODE_OSF;
> +  } else {
> +    value &= ~DMAGRP_OPERATION_MODE_TSF;
> +    value &= ~DMAGRP_OPERATION_MODE_TTC_GET( value );
> +
> +    /* Set the transmit threshold */
> +    if ( txmode <= 32 ) {
> +      value |= DMAGRP_OPERATION_MODE_TTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_TTC_CONTROL_32
> +        );
> +    } else if ( txmode <= 64 ) {
> +      value = DMAGRP_OPERATION_MODE_TTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_TTC_CONTROL_64
> +        );
> +    } else if ( txmode <= 128 ) {
> +      value = DMAGRP_OPERATION_MODE_TTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_TTC_CONTROL_128
> +        );
> +    } else if ( txmode <= 192 ) {
> +      value = DMAGRP_OPERATION_MODE_TTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_TTC_CONTROL_192
> +        );
> +    } else {
> +      value = DMAGRP_OPERATION_MODE_TTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_TTC_CONTROL_256
> +        );
> +    }
> +  }
> +
> +  if ( rxmode == DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD ) {
> +    value |= DMAGRP_OPERATION_MODE_RSF;
> +  } else {
> +    value &= ~DMAGRP_OPERATION_MODE_RSF;
> +    value &= DMAGRP_OPERATION_MODE_RTC_GET( value );
> +
> +    if ( rxmode <= 32 ) {
> +      value = DMAGRP_OPERATION_MODE_RTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_RTC_CONTROL_32
> +        );
> +    } else if ( rxmode <= 64 ) {
> +      value = DMAGRP_OPERATION_MODE_RTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_RTC_CONTROL_64
> +        );
> +    } else if ( rxmode <= 96 ) {
> +      value = DMAGRP_OPERATION_MODE_RTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_RTC_CONTROL_96
> +        );
> +    } else {
> +      value = DMAGRP_OPERATION_MODE_RTC_SET(
> +        value,
> +        DWMAC100_OPERATION_MODE_RTC_CONTROL_128
> +        );
> +    }
> +  }
> +
> +  self->dmagrp->operation_mode = value;
> +}
> +
> +const dwmac_common_dma_ops dwmac_dma_ops_1000 = {
> +  .init     = dwmac1000_dma_init,
> +  .dma_mode = dwmac1000_dma_operation_mode,
> +};
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-1000-ethernet-mac-ops.c b/c/src/libchip/network/dwmac-1000-ethernet-mac-ops.c
> new file mode 100644
> index 0000000..00bc71d
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-1000-ethernet-mac-ops.c
> @@ -0,0 +1,35 @@
> +/**
> + * @file dwmac-1000-ethernet-mac-ops.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief Operations for the dwmac 1000 ethernet mac
> + *
> + * DWMAC_1000_ETHERNET_MAC_OPS will be accessible in the API header and can be
> + * passed to the configuration data if handling a DWMAC 1000 driver
> + */
> +
> +/*
> + * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include "dwmac-common.h"
> +
> +extern const dwmac_common_dma_ops  dwmac_dma_ops_1000;
> +extern const dwmac_common_core_ops dwmac_core_ops_1000;
> +
> +const dwmac_ethernet_mac_ops       DWMAC_1000_ETHERNET_MAC_OPS =
> +  DWMAC_ETHERNET_MAC_OPS_INITIALIZER(
> +    &dwmac_core_ops_1000,
> +    &dwmac_dma_ops_1000
> +    );
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-common.h b/c/src/libchip/network/dwmac-common.h
> new file mode 100644
> index 0000000..983b4ff
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-common.h
> @@ -0,0 +1,372 @@
> +/**
> + * @file dwmac_common.h
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief [SHORT DESCRIPTION OF MODULE]
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems./license/LICENSE.
> + */
> +
> +#ifndef DWMAC_COMMON_H_
> +#define DWMAC_COMMON_H_
> +
> +#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
> +#define __BSD_VISIBLE 1
> +
> +#include <stdint.h>
> +#include <rtems.h>
> +#include <rtems/rtems_bsdnet.h>
> +#include <rtems/rtems_mii_ioctl.h>
> +
> +#include <sys/param.h>
> +#include <sys/socket.h>
> +#include <sys/sockio.h>
> +#include <sys/mbuf.h>
> +
> +#include <net/if.h>
> +#include <net/if_arp.h>
> +#include <netinet/in.h>
> +#include <netinet/if_ether.h>
> +#include <netinet/in_systm.h>
> +#include <netinet/ip.h>
> +
> +#include <libchip/dwmac.h>
> +#include "dwmac-desc.h"
> +#include "dwmac-regs.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +#define DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD 1 /* DMA STORE-AND-FORWARD Operation Mode */
> +
> +/* Events */
> +/* Common task events */
> +#define DWMAC_COMMON_EVENT_TASK_INIT RTEMS_EVENT_1
> +#define DWMAC_COMMON_EVENT_TASK_STOP RTEMS_EVENT_2
> +
> +/* Events for the transmit task */
> +#define DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME RTEMS_EVENT_3
> +#define DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED RTEMS_EVENT_4
> +#define DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD RTEMS_EVENT_5
> +#define DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE RTEMS_EVENT_6
> +
> +/* Events for the receive task */
> +#define DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED RTEMS_EVENT_3
> +
> +/* Foreward declarations */
> +typedef struct dwmac_common_core_ops dwmac_common_core_ops;
> +typedef struct dwmac_common_dma_ops dwmac_common_dma_ops;
> +typedef struct dwmac_common_desc_ops dwmac_common_desc_ops;
> +
> +typedef enum { /* IPC status */
> +  DWMAC_COMMON_RX_FRAME_STATUS_GOOD,
> +  DWMAC_COMMON_RX_FRAME_STATUS_DISCARD,
> +  DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE,
> +  DWMAC_COMMON_RX_FRAME_STATUS_LLC_SNAP
> +} dwmac_common_rx_frame_status;
> +
> +typedef enum {
> +  DWMAC_COMMON_STATE_DOWN,
> +  DWMAC_COMMON_STATE_UP,
> +
> +  DWMAC_COMMON_STATE_COUNT
> +} dwmac_common_state;
> +
> +typedef struct {
> +  uint32_t link_down;
> +  uint32_t link_up;
> +} dwmac_common_phy_status_counts;
> +
> +typedef struct {
> +  uint32_t receive;
> +  uint32_t transmit;
> +  uint32_t tx_underflow;
> +  uint32_t tx_jabber;
> +  uint32_t rx_overflow;
> +  uint32_t rx_early;
> +  uint32_t rx_buf_unav;
> +  uint32_t rx_process_stopped;
> +  uint32_t rx_watchdog;
> +  uint32_t tx_early;
> +  uint32_t tx_buf_unav;
> +  uint32_t tx_process_stopped;
> +  uint32_t fatal_bus_error;
> +  uint32_t unhandled;
> +} dwmac_common_dma_irq_counts;
> +
> +typedef struct {
> +  uint32_t dest_addr_fail; /* When set, this bit indicates a frame that failed in the DA Filter in the MAC. */
> +  uint32_t crc_error; /* When set, this bit indicates that a CRC error occurred on the received frame. This field is valid only when the Last
> +                         Descriptor (RDES0[8]) is set. */
> +  uint32_t receive_error; /* When set, this bit indicates that the gmii_rxer_i signal is asserted while gmii_rxdv_i is asserted during frame
> +                             reception. Error can be of less or no extension, or error (rxd !=0xf) during extension. */
> +  uint32_t watchdog_timeout; /* When set, this bit indicates that the receive Watchdog Timer has expired while receiving the current frame and the
> +                                current frame is truncated after the Watchdog Timeout. */
> +  uint32_t late_collision; /* When set, this bit indicates that a late collision has occurred while receiving the frame in the half-duplex mode. */
> +  uint32_t giant_frame; /* When advanced timestamp feature is present, when set, this bit indicates that a snapshot of the Timestamp is
> +                           written in descriptor words 6 (RDES6) and 7 (RDES7). This is valid only when the Last Descriptor bit (RDES0[8]) is
> +                           set.
> +                           When IP Checksum Engine (Type 1) is selected, this bit, when set, indicates that the 16-bit IPv4 Header checksum
> +                           calculated by the EMAC did not match the received checksum bytes.
> +                           Otherwise, this bit, when set, indicates the Giant frame Status. Giant frames are larger than 1,518-byte (or
> +                           1,522-byte for VLAN or 2,000-byte when Bit 27 (2KPE) of MAC Configuration register is set) normal frames and
> +                           larger than 9,018-byte (9,022-byte for VLAN) frame when Jumbo frame processing is enabled. */
> +  uint32_t overflow_error; /* When set, this bit indicates that the received frame was damaged because of buffer overflow in MTL.
> +                              Note: This bit is set only when the DMA transfers a partial frame to the application. This happens only when the RX
> +                              FIFO buffer is operating in the threshold mode. In the store-and-forward mode, all partial frames are dropped
> +                              completely in RX FIFO buffer. */
> +  uint32_t descriptor_error; /* When set, this bit indicates a frame truncation caused by a frame that does not fit within the current descriptor
> +                                buffers, and that the DMA does not own the Next descriptor. The frame is truncated. This field is valid only when the
> +                                Last Descriptor (RDES0[8]) is set. */
> +  uint32_t source_addr_fail; /* When set, this bit indicates that the SA field of frame failed the SA Filter in the MAC. */
> +  uint32_t length_error; /* When set, this bit indicates that the actual length of the frame received and that the Length/ Type field does not
> +                            match. This bit is valid only when the Frame Type (RDES0[5]) bit is reset. */
> +  uint32_t vlan_tag; /* When set, this bit indicates that the frame to which this descriptor is pointing is a VLAN frame tagged by the MAC.
> +                        The VLAN tagging depends on checking the VLAN fields of received frame based on the Register 7 (VLAN Tag
> +                        Register) setting. */
> +  uint32_t ethernet_frames; /* When set, this bit indicates that the receive frame is an Ethernet-type frame (the LT field is greater than or equal to
> +                               0x0600). When this bit is reset, it indicates that the received frame is an IEEE802.3 frame. This bit is not valid for
> +                               Runt frames less than 14 bytes. */
> +  uint32_t dribble_bit_error; /* When set, this bit indicates that the received frame has a non-integer multiple of bytes (odd nibbles). This bit is valid
> +                                 only in the MII Mode. */
> +} dwmac_common_desc_status_counts_rx;
> +
> +typedef struct {
> +  uint32_t jabber; /* When set, this bit indicates the MAC transmitter has experienced a jabber time-out. This bit is only set when Bit 22
> +                      (Jabber Disable) of Register 0 (MAC Configuration Register) is not set. */
> +  uint32_t frame_flushed; /* When set, this bit indicates that the DMA or MTL flushed the frame because of a software Flush command given by
> +                             the CPU. */
> +  uint32_t losscarrier; /* When set, this bit indicates that a loss of carrier occurred during frame transmission (that is, the gmii_crs_i
> +                           signal was inactive for one or more transmit clock periods during frame transmission). This is valid only for the
> +                           frames transmitted without collision when the MAC operates in the half-duplex mode. */
> +  uint32_t no_carrier; /* When set, this bit indicates that the Carrier Sense signal form the PHY was not asserted during transmission. */
> +  uint32_t excessive_collisions; /* When set, this bit indicates that the transmission was aborted after 16 successive collisions while attempting to
> +                                    transmit the current frame. If Bit 9 (Disable Retry) bit in the Register 0 (MAC Configuration Register) is set, this bit
> +                                    is set after the first collision, and the transmission of the frame is aborted. */
> +  uint32_t excessive_deferral; /* When set, this bit indicates that the transmission has ended because of excessive deferral of over 24,288 bit times
> +                                  (155,680 bits times in 1,000-Mbps mode or if Jumbo frame is enabled) if Bit 4 (Deferral Check) bit in Register 0
> +                                  (MAC Configuration Register) is set high. */
> +  uint32_t underflow; /* When set, this bit indicates that the MAC aborted the frame because the data arrived late from the Host memory.
> +                         Underflow Error indicates that the DMA encountered an empty transmit buffer while transmitting the frame. The
> +                         transmission process enters the Suspended state and sets both Transmit Underflow (Register 5[5]) and Transmit
> +                         Interrupt (Register 5[0]). */
> +  uint32_t ip_header_error; /* When set, this bit indicates that the MAC transmitter detected an error in the IP datagram header. The transmitter
> +                               checks the header length in the IPv4 packet against the number of header bytes received from the application and
> +                               indicates an error status if there is a mismatch. For IPv6 frames, a header error is reported if the main header length
> +                               is not 40 bytes. Furthermore, the Ethernet Length/Type field value for an IPv4 or IPv6 frame must match the IP
> +                               header version received with the packet. For IPv4 frames, an error status is also indicated if the Header Length field
> +                               has a value less than 0x5. */
> +  uint32_t payload_error; /* When set, this bit indicates that MAC transmitter detected an error in the TCP, UDP, or ICMP IP datagram payload.
> +                             The transmitter checks the payload length received in the IPv4 or IPv6 header against the actual number of TCP,
> +                             UDP, or ICMP packet bytes received from the application and issues an error status in case of a mismatch. */
> +  uint32_t deferred; /* When set, this bit indicates that the MAC defers before transmission because of the presence of carrier. This bit is
> +                        valid only in the half-duplex mode. */
> +  uint32_t vlan; /* When set, this bit indicates that the transmitted frame is a VLAN-type frame. */
> +} dwmac_common_desc_status_counts_tx;
> +
> +typedef struct {
> +  uint32_t errors; /* Frames with errors */
> +  uint32_t dropped; /* Frames dropped */
> +  uint32_t frames_good; /* Frames passed to the network stack */
> +  uint32_t bytes_good; /* Sum of bytes passed to the network stack */
> +  uint32_t frames; /* Frames handled (good or bad) */
> +  uint32_t dma_suspended; /* The receive DMA was supended due to lack of descriptors */
> +} dwmac_common_rx_frame_counts;
> +
> +typedef struct {
> +  uint32_t frames_from_stack; /* Frames received from the network stack fro tranmission */
> +  uint32_t frames_to_dma; /* Number of frames transmitted to DMA */
> +  uint32_t packets_to_dma; /* Number of packets transmitted to DMA*/
> +  uint32_t bytes_to_dma; /* Number of bytes transmitted */
> +  uint32_t packet_errors; /* Packets with errors */
> +  uint32_t packets_tranmitted_by_DMA; /* Packets tranmitted by the DMA */
> +} dwmac_common_tx_frame_counts;
> +
> +typedef struct {
> +  dwmac_common_phy_status_counts phy_status_counts;
> +  dwmac_common_dma_irq_counts dma_irq_counts;
> +  dwmac_common_desc_status_counts_rx desc_status_counts_rx;
> +  dwmac_common_desc_status_counts_tx desc_status_counts_tx;
> +  dwmac_common_rx_frame_counts frame_counts_rx;
> +  dwmac_common_tx_frame_counts frame_counts_tx;
> +} dwmac_common_stats;
> +
> +typedef struct {
> +  struct arpcom arpcom;
> +  struct rtems_bsdnet_ifconfig *bsd_config;
> +  struct rtems_mdio_info mdio;
> +  rtems_id task_id_rx;
> +  rtems_id task_id_tx;
> +  rtems_id task_id_control;
> +  void *arg;
> +  volatile macgrp *macgrp;
> +  volatile dmagrp *dmagrp;
> +  unsigned int csr_clock;
> +  dwmac_common_state state;
> +  dwmac_common_stats stats;
> +  unsigned int dma_threshold_control;
> +  volatile dwmac_desc *dma_tx;
> +  volatile dwmac_desc *dma_rx;
> +  unsigned int idx_rx;
> +  struct mbuf **mbuf_addr_rx;
> +  struct mbuf **mbuf_addr_tx;
> +  const dwmac_cfg *CFG;
> +} dwmac_common_context;
> +
> +struct dwmac_common_core_ops {
> +  /* MAC core initialization */
> +  void (*core_init) ( dwmac_common_context *self );
> +
> +  /* Multicast filter setting */
> +  void (*set_hash_filter) (
> +    dwmac_common_context *self,
> +    const bool            add,
> +    struct ifreq         *ifr );
> +
> +  /* Set/Get Unicast MAC addresses */
> +  void (*set_umac_addr) (
> +    dwmac_common_context *ioaddr,
> +    const unsigned char  *addr,
> +    const unsigned int    reg_n );
> +};
> +
> +struct dwmac_common_dma_ops {
> +  /* DMA core initialization */
> +  int (*init) (
> +    dwmac_common_context *self,
> +    const uint32_t        pbl,
> +    const uint32_t        fb,
> +    const uint32_t        mb,
> +    const bool            use_enhanced_desc,
> +    const uint32_t        burst_len_4_support,
> +    const uint32_t        burst_len_8_support,
> +    const uint32_t        burst_len_16_support,
> +    const uint32_t        burst_boundary,
> +    volatile dwmac_desc  *dma_tx,
> +    volatile dwmac_desc  *dma_rx );
> +
> +  /* Set tx/rx threshold in the csr6 register
> +   * An invalid value enables the store-and-forward mode */
> +  void (*dma_mode) (
> +    dwmac_common_context *self,
> +    const unsigned int    txmode,
> +    const unsigned int    rxmode );
> +};
> +
> +struct dwmac_common_desc_ops {
> +  /* Verify that it is OK to use the selected descriptor operations */
> +  int (*validate) ( dwmac_common_context *self );
> +  bool (*use_enhanced_descs) ( dwmac_common_context *self );
> +
> +  /* DMA RX descriptor ring allocation */
> +  int (*create_rx_desc) ( dwmac_common_context *self );
> +
> +  /* DMA TX descriptor ring allocation */
> +  int (*create_tx_desc) ( dwmac_common_context *self );
> +
> +  /* Free DMA RX descriptor ring */
> +  int (*destroy_rx_desc) ( dwmac_common_context *self );
> +
> +  /* Free DMA TX descriptor ring */
> +  int (*destroy_tx_desc) ( dwmac_common_context *self );
> +
> +  /* DMA RX descriptor initialization */
> +  void (*init_rx_desc) (
> +    dwmac_common_context *self,
> +    const unsigned int    index );
> +
> +  /* DMA TX descriptor ring initialization */
> +  void (*init_tx_desc) ( dwmac_common_context *self );
> +
> +  /* Free rx data buffers */
> +  void (*release_rx_bufs) ( dwmac_common_context *self );
> +
> +  /* Allocate a data buffer */
> +  struct mbuf *(*alloc_data_buf)( dwmac_common_context *self );
> +
> +  /* Free tx data buffers */
> +  void (*release_tx_bufs) ( dwmac_common_context *self );
> +
> +  /* Invoked by the xmit function to prepare the tx descriptor */
> +  void (*prepare_tx_desc) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx,
> +    const bool            is_first,
> +    const size_t          len,
> +    const void           *pdata );
> +
> +  /* Set/get the owner of the descriptor */
> +  void (*release_tx_ownership) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +  bool (*am_i_tx_owner) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +
> +  /* Invoked by the xmit function to close the tx descriptor */
> +  void (*close_tx_desc) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +
> +  /* Clean the tx descriptor as soon as the tx irq is received */
> +  void (*release_tx_desc) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +
> +  /* Last tx segment reports the transmit status */
> +  int (*get_tx_ls) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +
> +  /* Return the transmit status looking at the TDES1 */
> +  int (*tx_status) (
> +    dwmac_common_context *self,
> +    const unsigned int    idx_tx );
> +
> +  /* Handle extra events on specific interrupts hw dependent */
> +  bool (*am_i_rx_owner) (
> +    dwmac_common_context *self,
> +    const unsigned int    desc_idx );
> +
> +  /* Get the receive frame size */
> +  size_t (*get_rx_frame_len) (
> +    dwmac_common_context *self,
> +    const unsigned int    desc_idx );
> +
> +  /* Return the reception status looking at the RDES1 */
> +  dwmac_common_rx_frame_status (*rx_status) (
> +    dwmac_common_context *self,
> +    const unsigned int    desc_idx );
> +  bool (*is_first_rx_segment) (
> +    dwmac_common_context *self,
> +    const unsigned int    descriptor_index );
> +  bool (*is_last_rx_segment) (
> +    dwmac_common_context *self,
> +    const unsigned int    descriptor_index );
> +  void (*print_tx_desc) (
> +    volatile dwmac_desc *p,
> +    const unsigned int   count );
> +  void (*print_rx_desc) (
> +    volatile dwmac_desc *p,
> +    const unsigned int   count );
> +};
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* DWMAC_COMMON_H_ */
> diff --git a/c/src/libchip/network/dwmac-core.c b/c/src/libchip/network/dwmac-core.c
> new file mode 100644
> index 0000000..93b6347
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-core.c
> @@ -0,0 +1,408 @@
> +/**
> + * @file dwmac-lib.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 10/100/1000 Network Interface Controllers Core Handling
> + *
> + * DWMAC 10/100/1000 on-chip Synopsys IP Ethernet controllers.
> + * Driver core handling.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include "dwmac-core.h"
> +#include "dwmac-common.h"
> +#include "dwmac-regs.h"
> +
> +#undef DWMAC_CORE_DEBUG
> +#ifdef DWMAC_CORE_DEBUG
> +#define DWMAC_CORE_PRINT_DBG( fmt, args ... )  printk( fmt, ## args )
> +#else
> +#define DWMAC_CORE_PRINT_DBG( fmt, args ... )  do { } while ( 0 )
> +#endif
> +
> +/* DMA default interrupt masks */
> +#define DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_RX \
> +  ( \
> +    DMAGRP_INTERRUPT_ENABLE_NIE \
> +    | DMAGRP_INTERRUPT_ENABLE_RIE \
> +  )
> +#define DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_TX \
> +  ( \
> +    DMAGRP_INTERRUPT_ENABLE_NIE \
> +    | DMAGRP_INTERRUPT_ENABLE_TIE \
> +    | DMAGRP_INTERRUPT_ENABLE_FBE \
> +    | DMAGRP_INTERRUPT_ENABLE_UNE \
> +    | DMAGRP_INTERRUPT_ENABLE_AIE \
> +  )
> +
> +#define DWMAC_CORE_INTR_STATUS_DEFAULT_MASK_RX \
> +  ( \
> +    DMAGRP_STATUS_NIS \
> +    | DMAGRP_STATUS_RI \
> +  )
> +#define DWMAC_CORE_INTR_STATUS_DEFAULT_MASK_TX \
> +  ( \
> +    DMAGRP_STATUS_NIS \
> +    | DMAGRP_STATUS_TI \
> +    | DMAGRP_STATUS_FBI \
> +    | DMAGRP_STATUS_UNF \
> +    | DMAGRP_STATUS_AIS \
> +  )
> +
> +/* CSR1 enables the transmit DMA to check for new descriptor */
> +void dwmac_core_dma_restart_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->transmit_poll_demand = 1;
> +}
> +
> +void dwmac_core_enable_dma_irq_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->interrupt_enable |= DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_TX;
> +}
> +
> +void dwmac_core_enable_dma_irq_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->interrupt_enable |= DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_RX;
> +}
> +
> +void dwmac_core_disable_dma_irq_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->interrupt_enable &= ~DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_TX;
> +}
> +
> +void dwmac_core_reset_dma_irq_status_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->status = DWMAC_CORE_INTR_STATUS_DEFAULT_MASK_TX;
> +}
> +
> +void dwmac_core_reset_dma_irq_status_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->status = DWMAC_CORE_INTR_STATUS_DEFAULT_MASK_RX;
> +}
> +
> +void dwmac_core_disable_dma_irq_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->interrupt_enable &= ~DWMAC_CORE_INTR_ENABLE_DEFAULT_MASK_RX;
> +}
> +
> +void dwmac_core_dma_start_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->operation_mode |= DMAGRP_OPERATION_MODE_ST;
> +}
> +
> +void dwmac_core_dma_stop_tx( dwmac_common_context *self )
> +{
> +  self->dmagrp->operation_mode &= ~DMAGRP_OPERATION_MODE_ST;
> +}
> +
> +void dwmac_core_dma_start_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->operation_mode |= DMAGRP_OPERATION_MODE_SR;
> +}
> +
> +void dwmac_core_dma_stop_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->operation_mode &= ~DMAGRP_OPERATION_MODE_SR;
> +}
> +
> +void dwmac_core_dma_restart_rx( dwmac_common_context *self )
> +{
> +  self->dmagrp->receive_poll_demand = 1;
> +}
> +
> +#ifdef DWMAC_CORE_DEBUG
> +static void show_tx_process_state( const uint32_t status )
> +{
> +  const uint32_t STATE = DMAGRP_STATUS_TS_GET( status );
> +
> +
> +  switch ( STATE ) {
> +    case 0:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Stopped): Reset or Stop command\n" );
> +      break;
> +    case 1:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Running):Fetching the Tx desc\n" );
> +      break;
> +    case 2:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Running): Waiting for end of tx\n" );
> +      break;
> +    case 3:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Running): Reading the data "
> +                            "and queuing the data into the Tx buf\n" );
> +      break;
> +    case 6:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Suspended): Tx Buff Underflow "
> +                            "or an unavailable Transmit descriptor\n" );
> +      break;
> +    case 7:
> +      DWMAC_CORE_PRINT_DBG( "- TX (Running): Closing Tx descriptor\n" );
> +      break;
> +    default:
> +      break;
> +  }
> +}
> +
> +static void show_rx_process_state( const uint32_t status )
> +{
> +  const uint32_t STATE = DMAGRP_STATUS_RS_GET( status );
> +
> +
> +  switch ( STATE ) {
> +    case 0:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Stopped): Reset or Stop command\n" );
> +      break;
> +    case 1:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Running): Fetching the Rx desc\n" );
> +      break;
> +    case 2:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Running):Checking for end of pkt\n" );
> +      break;
> +    case 3:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Running): Waiting for Rx pkt\n" );
> +      break;
> +    case 4:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Suspended): Unavailable Rx buf\n" );
> +      break;
> +    case 5:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Running): Closing Rx descriptor\n" );
> +      break;
> +    case 6:
> +      DWMAC_CORE_PRINT_DBG( "- RX(Running): Flushing the current frame"
> +                            " from the Rx buf\n" );
> +      break;
> +    case 7:
> +      DWMAC_CORE_PRINT_DBG( "- RX (Running): Queuing the Rx frame"
> +                            " from the Rx buf into memory\n" );
> +      break;
> +    default:
> +      break;
> +  }
> +}
> +
> +#else /*  DWMAC_CORE_DEBUG */
> +  #define show_tx_process_state( status )
> +  #define show_rx_process_state( status )
> +#endif /* DWMAC_CORE_DEBUG */
> +
> +void dwmac_core_dma_interrupt( void *arg )
> +{
> +  dwmac_common_context        *self            = (dwmac_common_context *) arg;
> +  dwmac_common_dma_irq_counts *count           = &self->stats.dma_irq_counts;
> +  rtems_event_set              events_receive  = 0;
> +  rtems_event_set              events_transmit = 0;
> +
> +  /* Get interrupt status */
> +  uint32_t irq_status  = self->dmagrp->status & self->dmagrp->interrupt_enable;
> +  uint32_t irq_handled = 0;
> +  uint32_t irq_disable = 0;
> +
> +
> +  DWMAC_CORE_PRINT_DBG( "%s: [CSR5: 0x%08x]\n", __func__, irq_status );
> +
> +  /* It displays the DMA process states (CSR5 register) if DWMAC_CORE_DEBUG is #defined */
> +  show_tx_process_state( self->dmagrp->status );
> +  show_rx_process_state( self->dmagrp->status );
> +
> +  /* Is there any abnormal interrupt? */
> +  if ( irq_status & DMAGRP_STATUS_AIS ) {
> +    DWMAC_CORE_PRINT_DBG( "CSR5[15] DMA ABNORMAL IRQ: " );
> +
> +    if ( irq_status & DMAGRP_STATUS_UNF ) {
> +      DWMAC_CORE_PRINT_DBG( "transmit underflow\n" );
> +      events_transmit |= DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD;
> +      irq_handled     |= DMAGRP_STATUS_UNF;
> +      irq_disable     |= DMAGRP_INTERRUPT_ENABLE_UNE;
> +      ++count->tx_underflow;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_TJT ) {
> +      DWMAC_CORE_PRINT_DBG( "transmit jabber\n" );
> +      irq_handled |= DMAGRP_STATUS_TJT;
> +      ++count->tx_jabber;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_OVF ) {
> +      DWMAC_CORE_PRINT_DBG( "recv overflow\n" );
> +      irq_handled |= DMAGRP_STATUS_OVF;
> +      ++count->rx_overflow;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_TU ) {
> +      DWMAC_CORE_PRINT_DBG( "transmit buffer unavailable\n" );
> +      irq_handled |= DMAGRP_STATUS_TU;
> +      ++count->tx_buf_unav;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_RU ) {
> +      DWMAC_CORE_PRINT_DBG( "receive buffer unavailable\n" );
> +      irq_handled |= DMAGRP_STATUS_RU;
> +      ++count->rx_buf_unav;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_RPS ) {
> +      DWMAC_CORE_PRINT_DBG( "receive process stopped\n" );
> +      irq_handled |= DMAGRP_STATUS_RPS;
> +      ++count->rx_process_stopped;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_RWT ) {
> +      DWMAC_CORE_PRINT_DBG( "receive watchdog\n" );
> +      irq_handled |= DMAGRP_STATUS_RWT;
> +      ++count->rx_watchdog;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_ETI ) {
> +      DWMAC_CORE_PRINT_DBG( "transmit early interrupt\n" );
> +      irq_handled |= DMAGRP_STATUS_ETI;
> +      ++count->tx_early;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_ERI ) {
> +      DWMAC_CORE_PRINT_DBG( "receive early interrupt\n" );
> +      irq_handled |= DMAGRP_STATUS_ERI;
> +      ++count->rx_early;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_TPS ) {
> +      DWMAC_CORE_PRINT_DBG( "transmit process stopped\n" );
> +      events_transmit |= DWMAC_COMMON_EVENT_TASK_INIT;
> +      irq_handled     |= DMAGRP_STATUS_TPS;
> +      irq_disable     |= DMAGRP_INTERRUPT_ENABLE_TSE;
> +      ++count->tx_process_stopped;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_FBI ) {
> +      DWMAC_CORE_PRINT_DBG( "fatal bus error\n" );
> +      events_transmit |= DWMAC_COMMON_EVENT_TASK_INIT;
> +      irq_handled     |= DMAGRP_STATUS_FBI;
> +      irq_disable     |= DMAGRP_INTERRUPT_ENABLE_FBE;
> +      ++count->fatal_bus_error;
> +    }
> +
> +    irq_handled |= DMAGRP_STATUS_AIS;
> +  }
> +
> +  /* Is there any normal interrupt? */
> +  if ( irq_status & DMAGRP_STATUS_NIS ) {
> +    /* Transmit interrupt */
> +    if ( irq_status & DMAGRP_STATUS_TI ) {
> +      events_transmit |= DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED;
> +      irq_handled     |= DMAGRP_STATUS_TI;
> +      irq_disable     |= DMAGRP_INTERRUPT_ENABLE_TIE;
> +      ++count->transmit;
> +    }
> +
> +    /* Receive interrupt */
> +    if ( irq_status & DMAGRP_STATUS_RI ) {
> +      events_receive |= DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED;
> +      irq_handled    |= DMAGRP_STATUS_RI;
> +      irq_disable    |= DMAGRP_INTERRUPT_ENABLE_RIE;
> +      ++count->receive;
> +    }
> +
> +    irq_handled |= DMAGRP_STATUS_NIS;
> +  }
> +
> +  /* Optional hardware blocks, interrupts should be disabled */
> +  if ( irq_status
> +       & ( DMAGRP_STATUS_GMI | DMAGRP_STATUS_GLI ) ) {
> +    DWMAC_CORE_PRINT_DBG( "%s: unexpected status %08x\n", __func__,
> +                          irq_status );
> +
> +    if ( irq_status & DMAGRP_STATUS_GMI ) {
> +      irq_handled |= DMAGRP_STATUS_GMI;
> +      ++count->unhandled;
> +    }
> +
> +    if ( irq_status & DMAGRP_STATUS_GLI ) {
> +      irq_handled |= DMAGRP_STATUS_GLI;
> +      ++count->unhandled;
> +    }
> +  }
> +
> +  /* Count remaining unhandled interrupts (there should not be any)  */
> +  if ( ( irq_status & 0x1FFCF ) != irq_handled ) {
> +    ++count->unhandled;
> +  }
> +
> +  /* Disable interrupts which need further handling by tasks.
> +   * The tasks will re-enable them. */
> +  self->dmagrp->interrupt_enable &= ~irq_disable;
> +
> +  /* Clear interrupts */
> +  self->dmagrp->status = irq_handled;
> +
> +  /* Send events to receive task */
> +  if ( events_receive != 0 ) {
> +    (void) rtems_bsdnet_event_send( self->task_id_rx, events_receive );
> +  }
> +
> +  /* Send events to transmit task */
> +  if ( events_transmit != 0 ) {
> +    (void) rtems_bsdnet_event_send( self->task_id_tx, events_transmit );
> +  }
> +
> +  DWMAC_CORE_PRINT_DBG( "\n\n" );
> +}
> +
> +void dwmac_core_dma_flush_tx_fifo( dwmac_common_context *self )
> +{
> +  self->dmagrp->operation_mode |= DMAGRP_OPERATION_MODE_FTF;
> +
> +  do {
> +  } while ( ( self->dmagrp->operation_mode & DMAGRP_OPERATION_MODE_FTF ) != 0 );
> +}
> +
> +void dwmac_core_set_mac_addr(
> +  const uint8_t      addr[6],
> +  volatile uint32_t *reg_high,
> +  volatile uint32_t *reg_low )
> +{
> +  uint32_t data = MAC_HIGH_ADDRHI( ( addr[5] << 8 ) | addr[4] );
> +
> +
> +  /* For MAC Addr registers se have to set the Address Enable (AE)
> +   * bit that has no effect on the High Reg 0 where the bit 31 (MO)
> +   * is RO.
> +   */
> +  data     |= MAC_HIGH_AE;
> +  *reg_high = data;
> +
> +  data      =
> +    ( (uint32_t) addr[3] << 24 )
> +    | ( (uint32_t) addr[2] << 16 )
> +    | ( (uint32_t) addr[1] << 8 )
> +    | addr[0];
> +  *reg_low = data;
> +}
> +
> +/* Enable disable MAC RX/TX */
> +void dwmac_core_set_mac(
> +  dwmac_common_context *self,
> +  const bool            enable )
> +{
> +  uint32_t value = self->macgrp->mac_configuration;
> +
> +
> +  if ( enable ) {
> +    value |= MACGRP_MAC_CONFIGURATION_RE | MACGRP_MAC_CONFIGURATION_TE;
> +  } else {
> +    value &= ~( MACGRP_MAC_CONFIGURATION_RE | MACGRP_MAC_CONFIGURATION_TE );
> +  }
> +
> +  self->macgrp->mac_configuration = value;
> +}
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-core.h b/c/src/libchip/network/dwmac-core.h
> new file mode 100644
> index 0000000..b9b6a96
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-core.h
> @@ -0,0 +1,78 @@
> +/**
> + * @file dwmac-core.h
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 10/100/1000 Network Interface Controllers Core Handling
> + *
> + * DWMAC 10/100/1000 on-chip Synopsys IP Ethernet controllers.
> + * Driver core handling.
> + * This header file is NOT part of the driver API.
> + */
> +
> +/*
> + * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#ifndef DWMAC_CORE_H_
> +#define DWMAC_CORE_H_
> +
> +#include <stdint.h>
> +#include "dwmac-common.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +void dwmac_core_set_mac_addr(
> +  const uint8_t      addr[6],
> +  volatile uint32_t *reg_high,
> +  volatile uint32_t *reg_low );
> +
> +void dwmac_core_set_mac(
> +  dwmac_common_context *self,
> +  const bool            enable );
> +
> +void dwmac_core_dma_start_tx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_stop_tx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_start_rx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_stop_rx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_restart_rx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_restart_tx( dwmac_common_context *self );
> +
> +void dwmac_core_enable_dma_irq_rx( dwmac_common_context *self );
> +
> +void dwmac_core_enable_dma_irq_tx( dwmac_common_context *self );
> +
> +void dwmac_core_disable_dma_irq_tx( dwmac_common_context *self );
> +
> +void dwmac_core_disable_dma_irq_rx( dwmac_common_context *self );
> +
> +void dwmac_core_reset_dma_irq_status_tx( dwmac_common_context *self );
> +
> +void dwmac_core_reset_dma_irq_status_rx( dwmac_common_context *self );
> +
> +void dwmac_core_dma_interrupt( void *arg );
> +
> +void dwmac_core_dma_flush_tx_fifo( dwmac_common_context *self );
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* DWMAC_CORE_H_ */
> diff --git a/c/src/libchip/network/dwmac-desc-com.c b/c/src/libchip/network/dwmac-desc-com.c
> new file mode 100644
> index 0000000..a3292c5
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-desc-com.c
> @@ -0,0 +1,62 @@
> +/**
> + * @file dwmac-desc-enh.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief  DWMAC 10/100/1000 Common Descriptor Handling
> + *
> + * DWMAC 10/100/1000 on-chip Ethernet controllers.
> + * Functions which are common to normal and enhanced DMA descriptors.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include "dwmac-desc-com.h"
> +
> +#undef DWMAC_DESC_COM_DEBUG
> +#ifdef DWMAC_DESC_COM_DEBUG
> +#define DWMAC_DESC_COM_PRINT_DBG( fmt, args ... )  printk( fmt, ## args )
> +#else
> +#define DWMAC_DESC_COM_PRINT_DBG( fmt, args ... )  do { } while ( 0 )
> +#endif
> +
> +struct mbuf *dwmac_desc_com_new_mbuf( dwmac_common_context *self ) {
> +  struct  ifnet *ifp = &self->arpcom.ac_if;
> +  struct  mbuf  *m   = NULL;
> +
> +
> +  MGETHDR( m, M_DONTWAIT, MT_DATA );
> +
> +  if ( m != NULL ) {
> +    MCLGET( m, M_DONTWAIT );
> +
> +    if ( m->m_ext.ext_buf != NULL ) {
> +      if ( ( m->m_flags & M_EXT ) != 0 ) {
> +        /* Set receive interface */
> +        m->m_pkthdr.rcvif = ifp;
> +
> +        /* Make sure packet data will be aligned */
> +        m->m_data = mtod( m, char * ) + ETHER_ALIGN;
> +        return m;
> +      } else {
> +        m_free( m );
> +      }
> +    } else {
> +      m_free( m );
> +    }
> +  }
> +
> +  return NULL;
> +}
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-desc-com.h b/c/src/libchip/network/dwmac-desc-com.h
> new file mode 100644
> index 0000000..3b0dd9f
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-desc-com.h
> @@ -0,0 +1,46 @@
> +/**
> + * @file dwmac-desc-com.h
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 10/100/1000 Common Descriptor Handling.
> + *
> + * DWMAC 10/100/1000 on-chip Ethernet controllers.
> + * Functions and data which are common to normal and enhanced DMA descriptors.
> + * This header file is NOT part of the driver API.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#ifndef DWMAC_DESC_COM_H_
> +#define DWMAC_DESC_COM_H_
> +
> +#include "dwmac-common.h"
> +#include <sys/queue.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +#define DWMAC_DESC_COM_HW_CRC_BYTES 4
> +#define DWMAC_DESC_COM_BUF_SIZE ( ETHER_MAX_LEN + DWMAC_DESC_COM_HW_CRC_BYTES )
> +
> +struct mbuf *dwmac_desc_com_new_mbuf( dwmac_common_context *self );
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* DWMAC_DESC_COM_H_ */
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-desc-enh.c b/c/src/libchip/network/dwmac-desc-enh.c
> new file mode 100644
> index 0000000..df11b69
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-desc-enh.c
> @@ -0,0 +1,1053 @@
> +/**
> + * @file dwmac-desc-enh.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 10/100/1000 Enhanced DMA Descriptor Handling.
> + *
> + * DWMAC 10/100/1000 on-chip Ethernet controllers.
> + * Functions and data for the handling of enhanced DMA descriptors.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <assert.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include "dwmac-common.h"
> +#include "dwmac-desc-com.h"
> +#include "dwmac-core.h"
> +#include <sys/queue.h>
> +
> +#undef DWMAC_DESC_ENH_DEBUG
> +#ifdef DWMAC_DESC_ENH_DEBUG
> +#define DWMAC_DESC_ENH_PRINT_DBG( fmt, args ... )  printk( fmt, ## args )
> +#else
> +#define DWMAC_DESC_ENH_PRINT_DBG( fmt, args ... )  do { } while ( 0 )
> +#endif
> +
> +typedef enum {
> +  DWMAC_IP_PAYLOAD_TYPE_UNKNOWN,
> +  DWMAC_IP_PAYLOAD_TYPE_UDP,
> +  DWMAC_IP_PAYLOAD_TYPE_TCP,
> +  DWMAC_IP_PAYLOAD_TYPE_ICMP
> +} dwmac_ip_payload_type;
> +
> +static void dwmac_desc_enh_rx_set_on_ring_chain(
> +  volatile dwmac_desc_ext *p, int end )
> +{
> +  /* For simplicity reasons we will not use the second buffer.
> +   * If we would use it we would have to set the size to MCLBYTES -1 */
> +  p->erx.des0_3.des1 = DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_2_SIZE_SET(
> +    p->erx.des0_3.des1, 0
> +    );
> +  p->erx.des0_3.des3 = (uint32_t) NULL;
> +
> +  if ( end )
> +    p->erx.des0_3.des1 |= DWMAC_DESC_ERX_DES1_RECEIVE_END_OF_RING;
> +}
> +
> +static void dwmac_desc_enh_tx_set_on_ring_chain(
> +  volatile dwmac_desc_ext *p, const bool end )
> +{
> +  if ( end )
> +    p->etx.des0_3.des0 |= DWMAC_DESC_ETX_DES0_TRANSMIT_END_OF_RING;
> +}
> +
> +static void dwmac_desc_enh_set_tx_desc_len(
> +  volatile dwmac_desc_ext *p_enh, size_t len )
> +{
> +  p_enh->etx.des0_3.des1 = DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_1_SIZE_SET(
> +    p_enh->etx.des0_3.des1,
> +    len
> +    );
> +}
> +
> +static bool dwmac_desc_enh_is_giant_frame( const uint32_t des0 )
> +{
> +  return (
> +    ( des0
> +      & DWMAC_DESC_ERX_DES0_TIMESTAMP_AVAIL_OR_CHECKSUM_ERROR_OR_GIANT_FRAME
> +    ) != 0
> +    );
> +}
> +
> +static bool dwmac_desc_enh_is_udp_payload( const uint32_t des4 )
> +{
> +  return (
> +    DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE_GET( des4 )
> +    == DWMAC_IP_PAYLOAD_TYPE_UDP
> +    );
> +}
> +
> +static bool dwmac_desc_enh_is_tcp_payload( const uint32_t des4 )
> +{
> +  return (
> +    DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE_GET( des4 )
> +    == DWMAC_IP_PAYLOAD_TYPE_TCP
> +    );
> +}
> +
> +static bool dwmac_desc_enh_is_icmp_payload( const uint32_t des4 )
> +{
> +  return (
> +    DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE_GET( des4 )
> +    == DWMAC_IP_PAYLOAD_TYPE_ICMP
> +    );
> +}
> +
> +static dwmac_common_rx_frame_status dwmac_desc_enh_coe_status(
> +  volatile dwmac_desc_ext *p_enh )
> +{
> +  dwmac_common_rx_frame_status ret  = DWMAC_COMMON_RX_FRAME_STATUS_GOOD;
> +  const uint32_t               DES0 = p_enh->erx.des0_3.des0;
> +  const uint32_t               DES4 = p_enh->erx.des4;
> +
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_EXT_STATUS_AVAIL_OR_RX_MAC_ADDR_STATUS )
> +       != 0 ) {
> +    if ( !dwmac_desc_enh_is_giant_frame( DES0 )
> +         && ( DES0 & DWMAC_DESC_ERX_DES0_FREAME_TYPE ) == 0
> +         && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) == 0
> +         && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED ) == 0
> +         && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_ERROR ) == 0
> +         && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_HEADER_ERROR ) == 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IEEE 802.3 Type frame.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_LLC_SNAP;
> +    } else if ( ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) != 0
> +                  || ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                  != 0 )
> +                && dwmac_desc_enh_is_giant_frame( DES0 ) ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 No CSUM Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_GOOD;
> +    } else if ( ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) != 0
> +                  || ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                  != 0 )
> +                && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 Payload Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) != 0
> +                  || ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                  != 0 )
> +                && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_HEADER_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 Header Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) != 0
> +                  || ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                  != 0 )
> +                && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_ERROR ) != 0
> +                && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IP_HEADER_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG(
> +        "RX Des0 status: IPv4/6 Header and Payload Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) != 0
> +                  || ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                  != 0 )
> +                && ( !dwmac_desc_enh_is_udp_payload( DES4 ) )
> +                && ( !dwmac_desc_enh_is_tcp_payload( DES4 ) )
> +                && ( !dwmac_desc_enh_is_icmp_payload( DES4 ) ) ) {
> +      DWMAC_DESC_ENH_PRINT_DBG(
> +        "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +    } else if ( ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED ) == 0
> +                && ( DES4 & DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED )
> +                == 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: No IPv4, IPv6 frame.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +    }
> +  } else {
> +    uint32_t status = (
> +      (uint32_t) ( dwmac_desc_enh_is_giant_frame( DES0 ) << 2U )
> +      | (uint32_t) ( ( ( DES0 & DWMAC_DESC_ERX_DES0_FREAME_TYPE )
> +                       != 0 ) << 1U ) )
> +                      & 0x7U;
> +
> +    /* bits 5 7 0 | Frame status
> +     * ----------------------------------------------------------
> +     *      0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
> +     *      1 0 0 | IPv4/6 No CSUM errorS.
> +     *      1 0 1 | IPv4/6 CSUM PAYLOAD error
> +     *      1 1 0 | IPv4/6 CSUM IP HR error
> +     *      1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
> +     *      0 0 1 | IPv4/6 unsupported IP PAYLOAD
> +     *      0 1 1 | COE bypassed.. no IPv4/6 frame
> +     *      0 1 0 | Reserved.
> +     */
> +    if ( status == 0x0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IEEE 802.3 Type frame.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_LLC_SNAP;
> +    } else if ( status == 0x4 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 No CSUM errorS.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_GOOD;
> +    } else if ( status == 0x5 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 Payload Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( status == 0x6 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: IPv4/6 Header Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( status == 0x7 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG(
> +        "RX Des0 status: IPv4/6 Header and Payload Error.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE;
> +    } else if ( status == 0x1 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG(
> +        "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +    } else if ( status == 0x3 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "RX Des0 status: No IPv4, IPv6 frame.\n" );
> +      ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +    }
> +  }
> +
> +  return ret;
> +}
> +
> +static int dwmac_desc_enh_get_tx_status(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  int                                 ret    = 0;
> +  volatile dwmac_desc_ext            *dma_tx =
> +    (volatile dwmac_desc_ext *) self->dma_tx;
> +  volatile dwmac_desc_ext            *p_desc = &dma_tx[idx_tx];
> +  dwmac_common_desc_status_counts_tx *counts =
> +    &self->stats.desc_status_counts_tx;
> +
> +
> +  if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_ERROR_SUMMARY ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "DWMAC TX error... 0x%08x\n", p->des01.etx );
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_JABBER_TIMEOUT )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tjabber_timeout error\n" );
> +      ++counts->jabber;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_FRAME_FLUSHED )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tframe_flushed error\n" );
> +      ++counts->frame_flushed;
> +      dwmac_core_dma_flush_tx_fifo( self );
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_LOSS_OF_CARRIER )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tloss_carrier error\n" );
> +      ++counts->losscarrier;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_NO_CARRIER )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tno_carrier error\n" );
> +      ++counts->no_carrier;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_EXCESSIVE_COLLISION )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\texcessive_collisions\n" );
> +      ++counts->excessive_collisions;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_EXCESSIVE_DEFERAL )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\texcessive tx_deferral\n" );
> +      ++counts->excessive_deferral;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_UNDERFLOW_ERROR )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tunderflow error\n" );
> +      dwmac_core_dma_flush_tx_fifo( self );
> +      ++counts->underflow;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_IP_HEADER_ERROR )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tTX IP header csum error\n" );
> +      ++counts->ip_header_error;
> +    }
> +
> +    if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_IP_PAYLOAD_ERROR )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tAddr/Payload csum error\n" );
> +      ++counts->payload_error;
> +      dwmac_core_dma_flush_tx_fifo( self );
> +    }
> +
> +    ret = -1;
> +  }
> +
> +  if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_DEFERRED_BIT ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC TX status: tx deferred\n" );
> +    ++counts->deferred;
> +  }
> +
> +  if ( ( p_desc->etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_VLAN_FRAME ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC TX status: VLAN frame\n" );
> +    ++counts->vlan;
> +  }
> +
> +  return ret;
> +}
> +
> +static dwmac_common_rx_frame_status dwmac_desc_enh_get_rx_status(
> +  dwmac_common_context *self,
> +  const unsigned int    desc_idx )
> +{
> +  dwmac_common_desc_status_counts_rx *counts =
> +    &self->stats.desc_status_counts_rx;
> +  dwmac_common_rx_frame_status        ret    =
> +    DWMAC_COMMON_RX_FRAME_STATUS_GOOD;
> +  volatile dwmac_desc_ext            *dma_rx =
> +    (volatile dwmac_desc_ext *) self->dma_rx;
> +  const uint32_t                      DES0   = dma_rx[desc_idx].erx.des0_3.des0;
> +
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_ERROR_SUMMARY ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX Error Summary 0x%08x\n",
> +                              DES0 );
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_DESCRIPTOR_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tdescriptor error\n" );
> +      ++counts->descriptor_error;
> +    }
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_OVERFLOW_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\toverflow error\n" );
> +      ++counts->overflow_error;
> +    }
> +
> +    if ( dwmac_desc_enh_is_giant_frame( DES0 ) ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tIPC Csum Error/Giant frame\n" );
> +      ++counts->giant_frame;
> +    }
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_LATE_COLLISION ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tlate_collision error\n" );
> +      ++counts->late_collision;
> +    }
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_RECEIVE_WATCHDOG_TIMEOUT )
> +         != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\treceive_watchdog error\n" );
> +      ++counts->watchdog_timeout;
> +    }
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_RECEIVE_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tReceive Error\n" );
> +      ++counts->receive_error;
> +    }
> +
> +    if ( ( DES0 & DWMAC_DESC_ERX_DES0_CRC_ERROR ) != 0 ) {
> +      DWMAC_DESC_ENH_PRINT_DBG( "\tCRC error\n" );
> +      ++counts->crc_error;
> +    }
> +
> +    ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +  }
> +
> +  if ( ret == DWMAC_COMMON_RX_FRAME_STATUS_GOOD ) {
> +    /* After a payload csum error, the ES bit is set.
> +     * It doesn't match with the information reported into the databook.
> +     * At any rate, we need to understand if the CSUM hw computation is ok
> +     * and report this info to the upper layers. */
> +    ret = dwmac_desc_enh_coe_status( &dma_rx[desc_idx] );
> +  }
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_DRIBBLE_BIT_ERROR ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX: dribbling error\n" );
> +    ++counts->dribble_bit_error;
> +  }
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_SRC_ADDR_FILTER_FAIL ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX : Source Address filter fail\n" );
> +    ++counts->source_addr_fail;
> +    ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +  }
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_DEST_ADDR_FILTER_FAIL ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX : Dest Address filter fail\n" );
> +    ++counts->dest_addr_fail;
> +    ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +  }
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_LENGTH_ERROR ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX: length_error error\n" );
> +    ++counts->length_error;
> +    ret = DWMAC_COMMON_RX_FRAME_STATUS_DISCARD;
> +  }
> +
> +  if ( ( DES0 & DWMAC_DESC_ERX_DES0_VLAN_TAG ) != 0 ) {
> +    DWMAC_DESC_ENH_PRINT_DBG( "GMAC RX: VLAN frame tagged\n" );
> +    ++counts->vlan_tag;
> +  }
> +
> +  return ret;
> +}
> +
> +static void dwmac_desc_enh_print_tx_desc(
> +  volatile dwmac_desc *p,
> +  const unsigned int   count )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) p;
> +  unsigned int             index;
> +
> +
> +  if ( p_enh != NULL ) {
> +    for ( index = 0; index < count; ++index ) {
> +      printf( "Transmit DMA Descriptor %d\n", index );
> +      printf( "des0\n" );
> +      printf(
> +        " %u own bit\n"
> +        " %u IRQ on Completion\n"
> +        " %u Last Segment\n"
> +        " %u First Segment\n"
> +        " %u Disable CRC\n"
> +        " %u Disable Pad\n"
> +        " %u Transmit Timestamp Enable\n"
> +        " %lu Checksum Insertion Control\n"
> +        " %u Transmit End of Ring\n"
> +        " %u Second Address Chained\n"
> +        " %u Transmit Timestamp Status\n"
> +        " %u IP Header Error\n"
> +        " %u VLAN Frame\n"
> +        " %lu Collision Count\n"
> +        " %u Deferred Bit\n",
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_OWN_BIT ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_IRQ_ON_COMPLETION ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_LAST_SEGMENT ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_FIRST_SEGMENT ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_DISABLE_CRC ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_DISABLE_PAD ) != 0,
> +        ( p_enh[index].etx.des0_3.des0
> +          & DWMAC_DESC_ETX_DES0_TRANSMIT_TIMESTAMP_ENABLE ) != 0,
> +        DWMAC_DESC_ETX_DES0_CHECKSUM_INSERTION_CONTROL_GET( p_enh[index].etx.
> +                                                            des0_3.des0 ),
> +        ( p_enh[index].etx.des0_3.des0
> +          & DWMAC_DESC_ETX_DES0_TRANSMIT_END_OF_RING ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_SECOND_ADDR_CHAINED ) != 0,
> +        ( p_enh[index].etx.des0_3.des0
> +          & DWMAC_DESC_ETX_DES0_TRANSMIT_TIMESTAMP_STATUS ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_IP_HEADER_ERROR ) != 0,
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_VLAN_FRAME ) != 0,
> +        DWMAC_DESC_ETX_DES0_COLLISION_COUNT_GET( p_enh[index].etx.des0_3.des0 ),
> +        ( p_enh[index].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_DEFERRED_BIT ) != 0
> +        );
> +
> +      if ( ( p_enh[index].etx.des0_3.des0
> +             & DWMAC_DESC_ETX_DES0_ERROR_SUMMARY ) != 0 ) {
> +        printf( " Error Summary:\n" );
> +
> +        if ( p_enh[index].etx.des0_3.des0
> +             & DWMAC_DESC_ETX_DES0_JABBER_TIMEOUT ) {
> +          printf( "  Jabber Timeout\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_FRAME_FLUSHED ) != 0 ) {
> +          printf( "  Frame Flush\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_IP_PAYLOAD_ERROR ) != 0 ) {
> +          printf( "  Payload Error\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_LOSS_OF_CARRIER ) != 0 ) {
> +          printf( "  Loss of Carrier\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_NO_CARRIER ) != 0 ) {
> +          printf( "  No Carrier\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_EXCESSIVE_COLLISION ) != 0 ) {
> +          printf( "  Excessive Collision\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_EXCESSIVE_COLLISION ) != 0 ) {
> +          printf( "  Ecessive Deferral\n" );
> +        }
> +
> +        if ( ( p_enh[index].etx.des0_3.des0
> +               & DWMAC_DESC_ETX_DES0_UNDERFLOW_ERROR ) != 0 ) {
> +          printf( "  Undeflow Error\n" );
> +        }
> +      }
> +
> +      printf( "des1\n" );
> +      printf(
> +        " %lu Transmit Buffer 2 Size\n"
> +        " %lu Transmit Buffer 1 Size\n",
> +        DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_2_SIZE_GET( p_enh[index].etx.des0_3.
> +                                                        des1 ),
> +        DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_1_SIZE_GET( p_enh[index].etx.des0_3.
> +                                                        des1 )
> +        );
> +      printf( "des2\n" );
> +      printf( " %p Buffer 1 Address\n", (void *) p_enh[index].etx.des0_3.des2 );
> +      printf( "des3\n" );
> +      printf( " %p Buffer 2 Address\n", (void *) p_enh[index].etx.des0_3.des3 );
> +    }
> +  }
> +}
> +
> +static void dwmac_desc_enh_print_rx_desc(
> +  volatile dwmac_desc *p,
> +  const unsigned int   count )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) p;
> +  unsigned int             index;
> +
> +
> +  if ( p_enh != NULL ) {
> +    for ( index = 0; index < count; ++index ) {
> +      printf( "Receive DMA Descriptor %d\n", index );
> +      printf( "des0\n" );
> +      printf(
> +        " %u Own Bit\n"
> +        " %u Dest. Addr. Filter Fail\n"
> +        " %lu Frame Length\n"
> +        " %u Source Addr. Filter Fail\n"
> +        " %u Length Error\n"
> +        " %u VLAN Tag\n"
> +        " %u First Descriptor\n"
> +        " %u Last Descriptor\n"
> +        " %u Frame Type\n"
> +        " %u Dribble Bit Error\n"
> +        " %u Extended Status Available\n",
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_OWN_BIT ) != 0,
> +        ( p_enh[index].erx.des0_3.des0
> +          & DWMAC_DESC_ERX_DES0_DEST_ADDR_FILTER_FAIL ) != 0,
> +        DWMAC_DESC_ERX_DES0_FRAME_LENGTH_GET(
> +          p_enh[index].erx.des0_3.des0 ),
> +        ( p_enh[index].erx.des0_3.des0
> +          & DWMAC_DESC_ERX_DES0_SRC_ADDR_FILTER_FAIL ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_LENGTH_ERROR ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_VLAN_TAG ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_FIRST_DESCRIPTOR ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_LAST_DESCRIPTOR ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_FREAME_TYPE ) != 0,
> +        ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_DRIBBLE_BIT_ERROR ) != 0,
> +        ( p_enh[index].erx.des0_3.des0
> +          & DWMAC_DESC_ERX_DES0_EXT_STATUS_AVAIL_OR_RX_MAC_ADDR_STATUS ) != 0
> +        );
> +
> +      if ( ( p_enh[index].erx.des0_3.des0
> +             & DWMAC_DESC_ERX_DES0_ERROR_SUMMARY ) != 0 ) {
> +        printf( " Error Summary:\n" );
> +
> +        if ( ( p_enh[index].erx.des0_3.des0
> +               & DWMAC_DESC_ERX_DES0_DESCRIPTOR_ERROR ) != 0 ) {
> +          printf( "  Descriptor Error\n" );
> +        }
> +
> +        if ( ( p_enh[index].erx.des0_3.des0
> +               & DWMAC_DESC_ERX_DES0_OVERFLOW_ERROR ) != 0 ) {
> +          printf( "  Overflow Error\n" );
> +        }
> +
> +        if ( ( p_enh[index].erx.des0_3.des0
> +               &
> +               DWMAC_DESC_ERX_DES0_TIMESTAMP_AVAIL_OR_CHECKSUM_ERROR_OR_GIANT_FRAME )
> +             != 0 ) {
> +          printf( "  Giant Frame\n" );
> +        }
> +
> +        if ( ( p_enh[index].erx.des0_3.des0
> +               & DWMAC_DESC_ERX_DES0_LATE_COLLISION ) != 0 ) {
> +          printf( "  Late Collision\n" );
> +        }
> +
> +        if ( ( p_enh[index].erx.des0_3.des0
> +               & DWMAC_DESC_ERX_DES0_RECEIVE_WATCHDOG_TIMEOUT ) != 0
> +             || ( p_enh[index].erx.des0_3.des0
> +                  & DWMAC_DESC_ERX_DES0_RECEIVE_ERROR ) != 0 ) {
> +          printf( "  IP Header or IP Payload:\n" );
> +
> +          if ( ( p_enh[index].erx.des0_3.des0
> +                 & DWMAC_DESC_ERX_DES0_RECEIVE_WATCHDOG_TIMEOUT ) != 0 ) {
> +            printf( "   Watchdog Timeout\n" );
> +          }
> +
> +          if ( ( p_enh[index].erx.des0_3.des0
> +                 & DWMAC_DESC_ERX_DES0_RECEIVE_ERROR ) != 0 ) {
> +            printf( "   Receive Error\n" );
> +          }
> +        }
> +
> +        if ( ( p_enh[index].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_CRC_ERROR )
> +             != 0 ) {
> +          printf( "  CRC Error\n" );
> +        }
> +      }
> +
> +      printf( "des1\n" );
> +      printf(
> +        " %u Disable Interrupt on Completion\n"
> +        " %lu Receive Buffer 2 Size\n"
> +        " %u Receive End of Ring\n"
> +        " %u Second Addr. Chained\n"
> +        " %lu Receive Buffer 1 Size\n",
> +        ( p_enh[index].erx.des0_3.des1
> +          & DWMAC_DESC_ERX_DES1_DISABLE_IRQ_ON_COMPLETION ) != 0,
> +        DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_2_SIZE_GET( p_enh[index].erx.des0_3.
> +                                                     des1 ),
> +        ( p_enh[index].erx.des0_3.des1 & DWMAC_DESC_ERX_DES1_RECEIVE_END_OF_RING ) != 0,
> +        ( p_enh[index].erx.des0_3.des1 & DWMAC_DESC_ERX_DES1_SECOND_ADDR_CHAINED ) != 0,
> +        DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE_GET( p_enh[index].erx.des0_3.
> +                                                     des1 )
> +        );
> +      printf( "des2\n" );
> +      printf( " %p Buffer 1 Address\n", (void *) p_enh[index].erx.des0_3.des2 );
> +      printf( "des3\n" );
> +      printf( " %p Buffer 2 Address\n", (void *) p_enh[index].erx.des0_3.des3 );
> +    }
> +  }
> +}
> +
> +static int dwmac_desc_enh_create_rx_desc( dwmac_common_context *self )
> +{
> +  int          eno        = 0;
> +  const size_t NUM_DESCS  = (size_t) self->bsd_config->rbuf_count;
> +  const size_t SIZE_DESCS = NUM_DESCS * sizeof( dwmac_desc_ext );
> +  void        *desc_mem   = NULL;
> +
> +
> +  assert( NULL == self->dma_rx );
> +
> +  /* Allocate an array of mbuf pointers */
> +  self->mbuf_addr_rx = calloc( NUM_DESCS, sizeof( struct mbuf * ) );
> +
> +  if ( self->mbuf_addr_rx == NULL ) {
> +    eno = ENOMEM;
> +  }
> +
> +  /* Allocate an array of dma descriptors */
> +  if ( eno == 0 ) {
> +    eno = ( self->CFG->CALLBACK.mem_alloc_nocache )(
> +      self->arg,
> +      &desc_mem,
> +      SIZE_DESCS
> +      );
> +  }
> +
> +  if ( eno == 0 ) {
> +    if ( desc_mem != NULL ) {
> +      memset( desc_mem, 0, SIZE_DESCS );
> +      _ARM_Data_synchronization_barrier();
> +    } else {
> +      eno = ENOMEM;
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    self->dma_rx = (volatile dwmac_desc *) desc_mem;
> +    _ARM_Data_synchronization_barrier();
> +  }
> +
> +  return eno;
> +}
> +
> +static void dwmac_desc_enh_init_rx_desc(
> +  dwmac_common_context *self,
> +  const unsigned int    index )
> +{
> +  volatile dwmac_desc_ext *p_enh       =
> +    (volatile dwmac_desc_ext *) self->dma_rx;
> +  const size_t             NUM_DESCS   = (size_t) self->bsd_config->rbuf_count;
> +  char                    *clust_start =
> +    mtod( self->mbuf_addr_rx[index], char * );
> +
> +
> +  assert( NULL != p_enh );
> +
> +  _ARM_Data_synchronization_barrier();
> +
> +  rtems_cache_invalidate_multiple_data_lines(
> +    clust_start,
> +    DWMAC_DESC_COM_BUF_SIZE + ETHER_ALIGN
> +    );
> +
> +  if ( self->mbuf_addr_rx[index] != NULL ) {
> +    p_enh[index].erx.des0_3.des1 = DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE_SET(
> +      p_enh->erx.des0_3.des1,
> +      DWMAC_DESC_COM_BUF_SIZE );
> +  } else {
> +    p_enh[index].erx.des0_3.des1 = DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE_SET(
> +      p_enh->erx.des0_3.des1,
> +      0 );
> +  }
> +
> +  p_enh[index].erx.des0_3.des2 = (uint32_t) clust_start;
> +
> +  /* The network controller supports adding a second data buffer to
> +   * p_enh->erx.des0_3.des3. For simplicity reasons we will not do this */
> +  dwmac_desc_enh_rx_set_on_ring_chain( &p_enh[index],
> +                                       ( index == NUM_DESCS - 1 ) );
> +  _ARM_Data_synchronization_barrier();
> +  p_enh[index].erx.des0_3.des0 = DWMAC_DESC_ERX_DES0_OWN_BIT;
> +}
> +
> +static int dwmac_desc_enh_destroy_rx_desc( dwmac_common_context *self )
> +{
> +  int   eno      = 0;
> +  void *desc_mem = __DEVOLATILE( void *, self->dma_rx );
> +
> +
> +  if ( self->mbuf_addr_rx != NULL ) {
> +    free( self->mbuf_addr_rx, 0 );
> +    self->mbuf_addr_rx = NULL;
> +  }
> +
> +  if ( desc_mem != NULL ) {
> +    eno          = self->CFG->CALLBACK.mem_free_nocache( self->arg, desc_mem );
> +    desc_mem     = NULL;
> +    self->dma_rx = (volatile dwmac_desc *) desc_mem;
> +  }
> +
> +  _ARM_Data_synchronization_barrier();
> +
> +  return eno;
> +}
> +
> +static void dwmac_desc_enh_release_rx_bufs( dwmac_common_context *self )
> +{
> +  volatile dwmac_desc_ext *p_enh     = (volatile dwmac_desc_ext *) self->dma_rx;
> +  const size_t             NUM_DESCS = (size_t) self->bsd_config->rbuf_count;
> +  unsigned int             i;
> +
> +
> +  assert( p_enh != NULL );
> +
> +  for ( i = 0; i < NUM_DESCS; ++i ) {
> +    if ( p_enh[i].erx.des0_3.des2 != 0 ) {
> +      struct mbuf *dummy;
> +
> +      assert( self->mbuf_addr_rx[i] != NULL );
> +
> +      MFREE( self->mbuf_addr_rx[i], dummy );
> +      (void) dummy;
> +      memset( __DEVOLATILE( void *,
> +                            &p_enh[i].erx ), 0, sizeof( dwmac_desc_ext ) );
> +    }
> +  }
> +
> +  self->dma_rx = (volatile dwmac_desc *) p_enh;
> +  _ARM_Data_synchronization_barrier();
> +}
> +
> +static int dwmac_desc_enh_create_tx_desc( dwmac_common_context *self )
> +{
> +  int          eno        = 0;
> +  void        *mem_desc   = __DEVOLATILE( void *, self->dma_tx );
> +  const size_t NUM_DESCS  = (size_t) self->bsd_config->xbuf_count;
> +  const size_t SIZE_DESCS = NUM_DESCS * sizeof( dwmac_desc_ext );
> +
> +
> +  assert( mem_desc == NULL );
> +
> +  /* Allocate an array of mbuf pointers */
> +  self->mbuf_addr_tx = calloc( NUM_DESCS, sizeof( struct mbuf * ) );
> +
> +  if ( self->mbuf_addr_tx == NULL ) {
> +    eno = ENOMEM;
> +  }
> +
> +  if ( eno == 0 ) {
> +    eno = ( self->CFG->CALLBACK.mem_alloc_nocache )(
> +      self->arg,
> +      &mem_desc,
> +      SIZE_DESCS
> +      );
> +  }
> +
> +  if ( eno == 0 ) {
> +    if ( mem_desc != NULL ) {
> +      memset( mem_desc, 0, SIZE_DESCS );
> +      _ARM_Data_synchronization_barrier();
> +    } else {
> +      eno = ENOMEM;
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    self->dma_tx = (volatile dwmac_desc *) mem_desc;
> +    _ARM_Data_synchronization_barrier();
> +  }
> +
> +  return eno;
> +}
> +
> +static void dwmac_desc_enh_init_tx_desc( dwmac_common_context *self )
> +{
> +  volatile dwmac_desc_ext *p_enh     = (volatile dwmac_desc_ext *) self->dma_tx;
> +  const size_t             NUM_DESCS = (size_t) self->bsd_config->xbuf_count;
> +  unsigned int             i;
> +
> +
> +  assert( p_enh != NULL );
> +
> +  for ( i = 0; i < NUM_DESCS; ++i ) {
> +    dwmac_desc_enh_tx_set_on_ring_chain( &p_enh[i], ( i == NUM_DESCS - 1 ) );
> +  }
> +
> +  self->dma_tx = (volatile dwmac_desc *) &p_enh[0];
> +  _ARM_Data_synchronization_barrier();
> +}
> +
> +static int dwmac_desc_enh_destroy_tx_desc( dwmac_common_context *self )
> +{
> +  int   eno      = 0;
> +  void *mem_desc = __DEVOLATILE( void *, self->dma_tx );
> +
> +
> +  if ( self->mbuf_addr_tx != NULL ) {
> +    free( self->mbuf_addr_tx, 0 );
> +    self->mbuf_addr_tx = NULL;
> +  }
> +
> +  if ( mem_desc != NULL ) {
> +    eno          = self->CFG->CALLBACK.mem_free_nocache( self->arg, mem_desc );
> +    mem_desc     = NULL;
> +    self->dma_tx = (volatile dwmac_desc *) mem_desc;
> +  }
> +
> +  _ARM_Data_synchronization_barrier();
> +
> +  return eno;
> +}
> +
> +static void dwmac_desc_enh_release_tx_bufs( dwmac_common_context *self )
> +{
> +  volatile dwmac_desc_ext *p_enh     = (volatile dwmac_desc_ext *) self->dma_tx;
> +  const size_t             NUM_DESCS = (size_t) self->bsd_config->xbuf_count;
> +  unsigned int             i;
> +
> +
> +  assert( p_enh != NULL );
> +
> +  for ( i = 0; i < NUM_DESCS; ++i ) {
> +    if ( p_enh[i].etx.des0_3.des1 != 0 ) {
> +      struct mbuf *dummy;
> +
> +      assert( self->mbuf_addr_tx[i] != NULL );
> +
> +      MFREE( self->mbuf_addr_tx[i], dummy );
> +      (void) dummy;
> +      memset( __DEVOLATILE( void *,
> +                            &p_enh[i].etx ), 0, sizeof( dwmac_desc_ext ) );
> +    }
> +  }
> +
> +  self->dma_tx = (volatile dwmac_desc *) p_enh;
> +  _ARM_Data_synchronization_barrier();
> +}
> +
> +static inline size_t dwmac_desc_enh_get_rx_frame_len(
> +  dwmac_common_context *self,
> +  const unsigned int    desc_idx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_rx;
> +
> +
> +  /* The type-1 checksum offload engines append the checksum at
> +   * the end of frame and the two bytes of checksum are added in
> +   * the length.
> +   * Adjust for that in the framelen for type-1 checksum offload
> +   * engines. */
> +  if ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_RXTYP1COE ) {
> +    return DWMAC_DESC_ERX_DES0_FRAME_LENGTH_GET( p_enh[desc_idx].erx.des0_3.des0 )
> +           - 2U;
> +  } else {
> +    return DWMAC_DESC_ERX_DES0_FRAME_LENGTH_GET( p_enh[desc_idx].erx.des0_3.des0 );
> +  }
> +}
> +
> +static bool dwmac_desc_enh_am_i_rx_owner(
> +  dwmac_common_context *self,
> +  const unsigned int    desc_idx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_rx;
> +  bool                     am_i_owner;
> +
> +
> +  _ARM_Data_synchronization_barrier();
> +  am_i_owner =
> +    ( p_enh[desc_idx].erx.des0_3.des0 & DWMAC_DESC_ERX_DES0_OWN_BIT ) == 0;
> +
> +  return am_i_owner;
> +}
> +
> +static bool dwmac_desc_enh_am_i_tx_owner(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +  bool                     am_i_owner;
> +
> +
> +  _ARM_Data_synchronization_barrier();
> +  am_i_owner =
> +    ( p_enh[idx_tx].etx.des0_3.des0 & DWMAC_DESC_ETX_DES0_OWN_BIT ) == 0;
> +
> +  return am_i_owner;
> +}
> +
> +static void dwmac_desc_enh_release_tx_ownership(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +
> +
> +  _ARM_Data_synchronization_barrier();
> +  p_enh[idx_tx].erx.des0_3.des0 |= DWMAC_DESC_ETX_DES0_OWN_BIT;
> +}
> +
> +static int dwmac_desc_enh_get_tx_ls(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +
> +
> +  return ( ( p_enh[idx_tx].etx.des0_3.des0
> +             & DWMAC_DESC_ETX_DES0_LAST_SEGMENT ) != 0 );
> +}
> +
> +static void dwmac_desc_enh_release_tx_desc(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +
> +
> +  p_enh[idx_tx].etx.des0_3.des0 =
> +    p_enh[idx_tx].etx.des0_3.des0
> +    & ( DWMAC_DESC_ETX_DES0_TRANSMIT_END_OF_RING
> +        | DWMAC_DESC_ETX_DES0_SECOND_ADDR_CHAINED );
> +
> +  p_enh[idx_tx].etx.des0_3.des1 = 0;
> +}
> +
> +static void dwmac_desc_enh_prepare_tx_desc(
> +  dwmac_common_context *self,
> +  const unsigned int    idx,
> +  const bool            is_first,
> +  const size_t          len,
> +  const void           *pdata )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +
> +
> +  if ( is_first ) {
> +    p_enh[idx].etx.des0_3.des0 |= DWMAC_DESC_ETX_DES0_FIRST_SEGMENT;
> +  }
> +
> +  dwmac_desc_enh_set_tx_desc_len( &p_enh[idx], len );
> +
> +  p_enh[idx].etx.des0_3.des2 = (uintptr_t) pdata;
> +}
> +
> +static void dwmac_desc_enh_close_tx_desc(
> +  dwmac_common_context *self,
> +  const unsigned int    idx_tx )
> +{
> +  volatile dwmac_desc_ext *p_enh = (volatile dwmac_desc_ext *) self->dma_tx;
> +
> +
> +  p_enh[idx_tx].etx.des0_3.des0 |= DWMAC_DESC_ETX_DES0_LAST_SEGMENT;
> +  p_enh[idx_tx].etx.des0_3.des0 |= DWMAC_DESC_ETX_DES0_IRQ_ON_COMPLETION;
> +}
> +
> +static bool dwmac_desc_enh_is_first_rx_segment(
> +  dwmac_common_context *self,
> +  const unsigned int    descriptor_index )
> +{
> +  volatile dwmac_desc_ext *p_descs = (volatile dwmac_desc_ext *) self->dma_rx;
> +
> +
> +  return ( ( p_descs[descriptor_index].erx.des0_3.des0
> +             & DWMAC_DESC_ERX_DES0_FIRST_DESCRIPTOR ) != 0 );
> +}
> +
> +static bool dwmac_desc_enh_is_last_rx_segment(
> +  dwmac_common_context *self,
> +  const unsigned int    descriptor_index )
> +{
> +  volatile dwmac_desc_ext *p_descs = (volatile dwmac_desc_ext *) self->dma_rx;
> +
> +
> +  return ( ( p_descs[descriptor_index].erx.des0_3.des0
> +             & DWMAC_DESC_ERX_DES0_LAST_DESCRIPTOR ) != 0 );
> +}
> +
> +int dwmac_desc_enh_validate( dwmac_common_context *self )
> +{
> +  /* Does the hardware support enhanced descriptors? */
> +  if ( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_ENHDESSEL ) != 0 ) {
> +    return 0;
> +  } else {
> +    return EINVAL;
> +  }
> +}
> +
> +bool dwmac_desc_enh_use_enhanced_descs( dwmac_common_context *self )
> +{
> +  (void) self;
> +
> +  /* Yes, we use enhanced descriptors */
> +  return true;
> +}
> +
> +const dwmac_common_desc_ops dwmac_desc_ops_enhanced = {
> +  .validate             = dwmac_desc_enh_validate,
> +  .use_enhanced_descs   = dwmac_desc_enh_use_enhanced_descs,
> +  .tx_status            = dwmac_desc_enh_get_tx_status,
> +  .rx_status            = dwmac_desc_enh_get_rx_status,
> +  .create_rx_desc       = dwmac_desc_enh_create_rx_desc,
> +  .create_tx_desc       = dwmac_desc_enh_create_tx_desc,
> +  .destroy_rx_desc      = dwmac_desc_enh_destroy_rx_desc,
> +  .destroy_tx_desc      = dwmac_desc_enh_destroy_tx_desc,
> +  .init_rx_desc         = dwmac_desc_enh_init_rx_desc,
> +  .init_tx_desc         = dwmac_desc_enh_init_tx_desc,
> +  .release_rx_bufs      = dwmac_desc_enh_release_rx_bufs,
> +  .release_tx_bufs      = dwmac_desc_enh_release_tx_bufs,
> +  .alloc_data_buf       = dwmac_desc_com_new_mbuf,
> +  .am_i_tx_owner        = dwmac_desc_enh_am_i_tx_owner,
> +  .am_i_rx_owner        = dwmac_desc_enh_am_i_rx_owner,
> +  .release_tx_desc      = dwmac_desc_enh_release_tx_desc,
> +  .prepare_tx_desc      = dwmac_desc_enh_prepare_tx_desc,
> +  .close_tx_desc        = dwmac_desc_enh_close_tx_desc,
> +  .get_tx_ls            = dwmac_desc_enh_get_tx_ls,
> +  .release_tx_ownership = dwmac_desc_enh_release_tx_ownership,
> +  .get_rx_frame_len     = dwmac_desc_enh_get_rx_frame_len,
> +  .is_first_rx_segment  = dwmac_desc_enh_is_first_rx_segment,
> +  .is_last_rx_segment   = dwmac_desc_enh_is_last_rx_segment,
> +  .print_tx_desc        = dwmac_desc_enh_print_tx_desc,
> +  .print_rx_desc        = dwmac_desc_enh_print_rx_desc,
> +};
> +
> +/* This wrapped function pointer struct can be passed into the
> + * configuration initializer for the driver */
> +const dwmac_descriptor_ops DWMAC_DESCRIPTOR_OPS_ENHANCED =
> +  DWMAC_DESCRIPTOR_OPS_INITIALIZER(
> +    &dwmac_desc_ops_enhanced
> +    );
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac-desc.h b/c/src/libchip/network/dwmac-desc.h
> new file mode 100644
> index 0000000..bc5b54a
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-desc.h
> @@ -0,0 +1,257 @@
> +#ifndef DWMAC_DESC_RX_REGS_H
> +#define DWMAC_DESC_RX_REGS_H
> +
> +#include <bsp/utility.h>
> +
> +typedef struct {
> +       uint32_t des0;
> +#define DWMAC_DESC_RX_DES0_OWN_BIT BSP_BIT32(31)
> +#define DWMAC_DESC_RX_DES0_DEST_ADDR_FILTER_FAIL BSP_BIT32(30)
> +#define DWMAC_DESC_RX_DES0_FRAME_LENGTH(val) BSP_FLD32(val, 16, 29)
> +#define DWMAC_DESC_RX_DES0_FRAME_LENGTH_GET(reg) BSP_FLD32GET(reg, 16, 29)
> +#define DWMAC_DESC_RX_DES0_FRAME_LENGTH_SET(reg, val) BSP_FLD32SET(reg, val, 16, 29)
> +#define DWMAC_DESC_RX_DES0_ERROR_SUMMARY BSP_BIT32(15)
> +#define DWMAC_DESC_RX_DES0_DESCRIPTOR_ERROR BSP_BIT32(14)
> +#define DWMAC_DESC_RX_DES0_SRC_ADDR_FILTER_FAIL BSP_BIT32(13)
> +#define DWMAC_DESC_RX_DES0_LENGTH_ERROR BSP_BIT32(12)
> +#define DWMAC_DESC_RX_DES0_OVERFLOW_ERROR BSP_BIT32(11)
> +#define DWMAC_DESC_RX_DES0_VLAN_TAG BSP_BIT32(10)
> +#define DWMAC_DESC_RX_DES0_FIRST_DESCRIPTOR BSP_BIT32(9)
> +#define DWMAC_DESC_RX_DES0_LAST_DESCRIPTOR BSP_BIT32(8)
> +#define DWMAC_DESC_RX_DES0_CHECKSUM_ERROR BSP_BIT32(7)
> +#define DWMAC_DESC_RX_DES0_LATE_COLLISION BSP_BIT32(6)
> +#define DWMAC_DESC_RX_DES0_FRAME_TYPE BSP_BIT32(5)
> +#define DWMAC_DESC_RX_DES0_RECEIVE_WATCHDOG_TIMEOUT BSP_BIT32(4)
> +#define DWMAC_DESC_RX_DES0_RECEIVE_ERROR BSP_BIT32(3)
> +#define DWMAC_DESC_RX_DES0_DRIBBLE_BIT_ERROR BSP_BIT32(2)
> +#define DWMAC_DESC_RX_DES0_CRC_ERROR BSP_BIT32(1)
> +#define DWMAC_DESC_RX_DES0_RX_MAC_ADDR_OR_PAYLOAD_CHECKSUM_ERROR BSP_BIT32(0)
> +       uint32_t des1;
> +#define DWMAC_DESC_RX_DES1_DISABLE_IRQ_ON_COMPLETION BSP_BIT32(31)
> +#define DWMAC_DESC_RX_DES1_RECEIVE_END_OF_RING BSP_BIT32(25)
> +#define DWMAC_DESC_RX_DES1_SECOND_ADDR_CHAINED BSP_BIT32(24)
> +#define DWMAC_DESC_RX_DES1_RECEIVE_BUFFER_2_SIZE(val) BSP_FLD32(val, 11, 21)
> +#define DWMAC_DESC_RX_DES1_RECEIVE_BUFFER_2_SIZE_GET(reg) BSP_FLD32GET(reg, 11, 21)
> +#define DWMAC_DESC_RX_DES1_RECEIVE_BUFFER_2_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 11, 21)
> +#define DWMAC_DESC_RX_DES1_RECIVE_BUFFER_1_SIZE(val) BSP_FLD32(val, 0, 10)
> +#define DWMAC_DESC_RX_DES1_RECIVE_BUFFER_1_SIZE_GET(reg) BSP_FLD32GET(reg, 0, 10)
> +#define DWMAC_DESC_RX_DES1_RECIVE_BUFFER_1_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 10)
> +       uint32_t des2;
> +#define DWMAC_DESC_RX_DES2_BUFF_1_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_RX_DES2_BUFF_1_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_RX_DES2_BUFF_1_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +#define DWMAC_DESC_RX_DES2_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_RX_DES2_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_RX_DES2_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des3;
> +#define DWMAC_DESC_RX_DES3_BUFF_2_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_RX_DES3_BUFF_2_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_RX_DES3_BUFF_2_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +#define DWMAC_DESC_RX_DES3_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_RX_DES3_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_RX_DES3_IEEE_RECEIVE_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_rx;
> +
> +typedef struct {
> +       uint32_t des0;
> +#define DWMAC_DESC_TX_DES0_OWN_BIT BSP_BIT32(31)
> +#define DWMAC_DESC_TX_DES0_TX_TIMESTAMP_STATUS BSP_BIT32(17)
> +#define DWMAC_DESC_TX_DES0_IP_HEADER_ERROR BSP_BIT32(16)
> +#define DWMAC_DESC_TX_DES0_ERROR_SUMMARY BSP_BIT32(15)
> +#define DWMAC_DESC_TX_DES0_JABBER_TIMEOUT BSP_BIT32(14)
> +#define DWMAC_DESC_TX_DES0_FRAME_FLUSHED BSP_BIT32(13)
> +#define DWMAC_DESC_TX_DES0_PAYLOAD_CHECKSUM_ERROR BSP_BIT32(12)
> +#define DWMAC_DESC_TX_DES0_LOSS_OF_CARRIER BSP_BIT32(11)
> +#define DWMAC_DESC_TX_DES0_NO_CARRIER BSP_BIT32(10)
> +#define DWMAC_DESC_TX_DES0_EXCESSIVE_COLLISION BSP_BIT32(8)
> +#define DWMAC_DESC_TX_DES0_VLAN_FRAME BSP_BIT32(7)
> +#define DWMAC_DESC_TX_DES0_COLLISION_TIMEOUT(val) BSP_FLD32(val, 3, 6)
> +#define DWMAC_DESC_TX_DES0_COLLISION_TIMEOUT_GET(reg) BSP_FLD32GET(reg, 3, 6)
> +#define DWMAC_DESC_TX_DES0_COLLISION_TIMEOUT_SET(reg, val) BSP_FLD32SET(reg, val, 3, 6)
> +#define DWMAC_DESC_TX_DES0_EXCESSIVE_DEFERAL BSP_BIT32(2)
> +#define DWMAC_DESC_TX_DES0_UNDERFLOW_ERROR BSP_BIT32(1)
> +#define DWMAC_DESC_TX_DES0_DEFERED_BIT BSP_BIT32(0)
> +       uint32_t des1;
> +#define DWMAC_DESC_TX_DES1_IRQ_ON_COMPLETION BSP_BIT32(31)
> +#define DWMAC_DESC_TX_DES1_LAST_SEGMENT BSP_BIT32(30)
> +#define DWMAC_DESC_TX_DES1_FIRST_SEGMENT BSP_BIT32(29)
> +#define DWMAC_DESC_TX_DES1_CHECKSUM_INSERTION_CONTROL(val) BSP_FLD32(val, 27, 28)
> +#define DWMAC_DESC_TX_DES1_CHECKSUM_INSERTION_CONTROL_GET(reg) BSP_FLD32GET(reg, 27, 28)
> +#define DWMAC_DESC_TX_DES1_CHECKSUM_INSERTION_CONTROL_SET(reg, val) BSP_FLD32SET(reg, val, 27, 28)
> +#define DWMAC_DESC_TX_DES1_DISABLE_CRC BSP_BIT32(26)
> +#define DWMAC_DESC_TX_DES1_TRANSMIT_END_OF_RING BSP_BIT32(25)
> +#define DWMAC_DESC_TX_DES1_SECOND_ADDRESS_CHAINED BSP_BIT32(24)
> +#define DWMAC_DESC_TX_DES1_DISABLE_PADDING BSP_BIT32(23)
> +#define DWMAC_DESC_TX_DES1_TRANSMIT_TIMESTAMP_ENABLE BSP_BIT32(22)
> +#define DWMAC_DESC_TX_DES1_TRANMIT_BUFFER_2_SIZE(val) BSP_FLD32(val, 11, 21)
> +#define DWMAC_DESC_TX_DES1_TRANMIT_BUFFER_2_SIZE_GET(reg) BSP_FLD32GET(reg, 11, 21)
> +#define DWMAC_DESC_TX_DES1_TRANMIT_BUFFER_2_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 11, 21)
> +#define DWMAC_DESC_TX_DES1_TRANSMIT_BUFFER_1_SIZE(val) BSP_FLD32(val, 0, 10)
> +#define DWMAC_DESC_TX_DES1_TRANSMIT_BUFFER_1_SIZE_GET(reg) BSP_FLD32GET(reg, 0, 10)
> +#define DWMAC_DESC_TX_DES1_TRANSMIT_BUFFER_1_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 10)
> +       uint32_t des2;
> +#define DWMAC_DESC_TX_DES2_BUFF_1_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_TX_DES2_BUFF_1_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_TX_DES2_BUFF_1_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +#define DWMAC_DESC_TX_DES2_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_TX_DES2_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_TX_DES2_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des3;
> +#define DWMAC_DESC_TX_DES3_BUFF_2_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_TX_DES3_BUFF_2_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_TX_DES3_BUFF_2_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +#define DWMAC_DESC_TX_DES3_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_TX_DES3_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_TX_DES3_IEEE_TRANSMIT_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_tx;
> +
> +typedef struct {
> +       uint32_t des0;
> +#define DWMAC_DESC_ERX_DES0_OWN_BIT BSP_BIT32(31)
> +#define DWMAC_DESC_ERX_DES0_DEST_ADDR_FILTER_FAIL BSP_BIT32(30)
> +#define DWMAC_DESC_ERX_DES0_FRAME_LENGTH(val) BSP_FLD32(val, 16, 29)
> +#define DWMAC_DESC_ERX_DES0_FRAME_LENGTH_GET(reg) BSP_FLD32GET(reg, 16, 29)
> +#define DWMAC_DESC_ERX_DES0_FRAME_LENGTH_SET(reg, val) BSP_FLD32SET(reg, val, 16, 29)
> +#define DWMAC_DESC_ERX_DES0_ERROR_SUMMARY BSP_BIT32(15)
> +#define DWMAC_DESC_ERX_DES0_DESCRIPTOR_ERROR BSP_BIT32(14)
> +#define DWMAC_DESC_ERX_DES0_SRC_ADDR_FILTER_FAIL BSP_BIT32(13)
> +#define DWMAC_DESC_ERX_DES0_LENGTH_ERROR BSP_BIT32(12)
> +#define DWMAC_DESC_ERX_DES0_OVERFLOW_ERROR BSP_BIT32(11)
> +#define DWMAC_DESC_ERX_DES0_VLAN_TAG BSP_BIT32(10)
> +#define DWMAC_DESC_ERX_DES0_FIRST_DESCRIPTOR BSP_BIT32(9)
> +#define DWMAC_DESC_ERX_DES0_LAST_DESCRIPTOR BSP_BIT32(8)
> +#define DWMAC_DESC_ERX_DES0_TIMESTAMP_AVAIL_OR_CHECKSUM_ERROR_OR_GIANT_FRAME BSP_BIT32(7)
> +#define DWMAC_DESC_ERX_DES0_LATE_COLLISION BSP_BIT32(6)
> +#define DWMAC_DESC_ERX_DES0_FREAME_TYPE BSP_BIT32(5)
> +#define DWMAC_DESC_ERX_DES0_RECEIVE_WATCHDOG_TIMEOUT BSP_BIT32(4)
> +#define DWMAC_DESC_ERX_DES0_RECEIVE_ERROR BSP_BIT32(3)
> +#define DWMAC_DESC_ERX_DES0_DRIBBLE_BIT_ERROR BSP_BIT32(2)
> +#define DWMAC_DESC_ERX_DES0_CRC_ERROR BSP_BIT32(1)
> +#define DWMAC_DESC_ERX_DES0_EXT_STATUS_AVAIL_OR_RX_MAC_ADDR_STATUS BSP_BIT32(0)
> +       uint32_t des1;
> +#define DWMAC_DESC_ERX_DES1_DISABLE_IRQ_ON_COMPLETION BSP_BIT32(31)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_2_SIZE(val) BSP_FLD32(val, 16, 28)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_2_SIZE_GET(reg) BSP_FLD32GET(reg, 16, 28)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_2_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 16, 28)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_END_OF_RING BSP_BIT32(15)
> +#define DWMAC_DESC_ERX_DES1_SECOND_ADDR_CHAINED BSP_BIT32(14)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE(val) BSP_FLD32(val, 0, 12)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE_GET(reg) BSP_FLD32GET(reg, 0, 12)
> +#define DWMAC_DESC_ERX_DES1_RECEIVE_BUFF_1_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 12)
> +       uint32_t des2;
> +#define DWMAC_DESC_ERX_DES2_BUFF_1_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_ERX_DES2_BUFF_1_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_ERX_DES2_BUFF_1_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des3;
> +#define DWMAC_DESC_ERX_DES3_BUFF_2_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_ERX_DES3_BUFF_2_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_ERX_DES3_BUFF_2_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_erx;
> +
> +typedef struct {
> +       uint32_t des0;
> +#define DWMAC_DESC_ETX_DES0_OWN_BIT BSP_BIT32(31)
> +#define DWMAC_DESC_ETX_DES0_IRQ_ON_COMPLETION BSP_BIT32(30)
> +#define DWMAC_DESC_ETX_DES0_LAST_SEGMENT BSP_BIT32(29)
> +#define DWMAC_DESC_ETX_DES0_FIRST_SEGMENT BSP_BIT32(28)
> +#define DWMAC_DESC_ETX_DES0_DISABLE_CRC BSP_BIT32(27)
> +#define DWMAC_DESC_ETX_DES0_DISABLE_PAD BSP_BIT32(26)
> +#define DWMAC_DESC_ETX_DES0_TRANSMIT_TIMESTAMP_ENABLE BSP_BIT32(25)
> +#define DWMAC_DESC_ETX_DES0_CHECKSUM_INSERTION_CONTROL(val) BSP_FLD32(val, 22, 23)
> +#define DWMAC_DESC_ETX_DES0_CHECKSUM_INSERTION_CONTROL_GET(reg) BSP_FLD32GET(reg, 22, 23)
> +#define DWMAC_DESC_ETX_DES0_CHECKSUM_INSERTION_CONTROL_SET(reg, val) BSP_FLD32SET(reg, val, 22, 23)
> +#define DWMAC_DESC_ETX_DES0_TRANSMIT_END_OF_RING BSP_BIT32(21)
> +#define DWMAC_DESC_ETX_DES0_SECOND_ADDR_CHAINED BSP_BIT32(20)
> +#define DWMAC_DESC_ETX_DES0_TRANSMIT_TIMESTAMP_STATUS BSP_BIT32(17)
> +#define DWMAC_DESC_ETX_DES0_IP_HEADER_ERROR BSP_BIT32(16)
> +#define DWMAC_DESC_ETX_DES0_ERROR_SUMMARY BSP_BIT32(15)
> +#define DWMAC_DESC_ETX_DES0_JABBER_TIMEOUT BSP_BIT32(14)
> +#define DWMAC_DESC_ETX_DES0_FRAME_FLUSHED BSP_BIT32(13)
> +#define DWMAC_DESC_ETX_DES0_IP_PAYLOAD_ERROR BSP_BIT32(12)
> +#define DWMAC_DESC_ETX_DES0_LOSS_OF_CARRIER BSP_BIT32(11)
> +#define DWMAC_DESC_ETX_DES0_NO_CARRIER BSP_BIT32(10)
> +#define DWMAC_DESC_ETX_DES0_EXCESSIVE_COLLISION BSP_BIT32(8)
> +#define DWMAC_DESC_ETX_DES0_VLAN_FRAME BSP_BIT32(7)
> +#define DWMAC_DESC_ETX_DES0_COLLISION_COUNT(val) BSP_FLD32(val, 3, 6)
> +#define DWMAC_DESC_ETX_DES0_COLLISION_COUNT_GET(reg) BSP_FLD32GET(reg, 3, 6)
> +#define DWMAC_DESC_ETX_DES0_COLLISION_COUNT_SET(reg, val) BSP_FLD32SET(reg, val, 3, 6)
> +#define DWMAC_DESC_ETX_DES0_EXCESSIVE_DEFERAL BSP_BIT32(2)
> +#define DWMAC_DESC_ETX_DES0_UNDERFLOW_ERROR BSP_BIT32(1)
> +#define DWMAC_DESC_ETX_DES0_DEFERRED_BIT BSP_BIT32(0)
> +       uint32_t des1;
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_2_SIZE(val) BSP_FLD32(val, 16, 28)
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_2_SIZE_GET(reg) BSP_FLD32GET(reg, 16, 28)
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_2_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 16, 28)
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_1_SIZE(val) BSP_FLD32(val, 0, 12)
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_1_SIZE_GET(reg) BSP_FLD32GET(reg, 0, 12)
> +#define DWMAC_DESC_ETX_DES1_TRANSMIT_BUFFER_1_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 12)
> +       uint32_t des2;
> +#define DWMAC_DESC_ETX_DES2_BUFF_1_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_ETX_DES2_BUFF_1_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_ETX_DES2_BUFF_1_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des3;
> +#define DWMAC_DESC_ETX_DES3_BUFF_2_ADDR_PTR(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_ETX_DES3_BUFF_2_ADDR_PTR_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_ETX_DES3_BUFF_2_ADDR_PTR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_etx;
> +
> +typedef union {
> +       dwmac_desc_rx rx;
> +       dwmac_desc_tx tx;
> +       dwmac_desc_erx erx;
> +       dwmac_desc_etx etx;
> +} dwmac_desc;
> +
> +typedef struct {
> +       dwmac_desc_erx des0_3;
> +       uint32_t des4;
> +#define DWMAC_DESC_EXT_ERX_DES4_LAYER3_AND_LAYER4_FILTER_MATCHED(val) BSP_FLD32(val, 26, 27)
> +#define DWMAC_DESC_EXT_ERX_DES4_LAYER3_AND_LAYER4_FILTER_MATCHED_GET(reg) BSP_FLD32GET(reg, 26, 27)
> +#define DWMAC_DESC_EXT_ERX_DES4_LAYER3_AND_LAYER4_FILTER_MATCHED_SET(reg, val) BSP_FLD32SET(reg, val, 26, 27)
> +#define DWMAC_DESC_EXT_ERX_DES4_LAYER4_FILTER_MATCH BSP_BIT32(25)
> +#define DWMAC_DESC_EXT_ERX_DES4_LAYER3_FILTER_MATCH BSP_BIT32(24)
> +#define DWMAC_DESC_EXT_ERX_DES4_TIMESTAMP_DROPPED BSP_BIT32(14)
> +#define DWMAC_DESC_EXT_ERX_DES4_PTP_VERSION BSP_BIT32(13)
> +#define DWMAC_DESC_EXT_ERX_DES4_PTP_FRAME_TYPE BSP_BIT32(12)
> +#define DWMAC_DESC_EXT_ERX_DES4_MESSAGE_TYPE(val) BSP_FLD32(val, 8, 11)
> +#define DWMAC_DESC_EXT_ERX_DES4_MESSAGE_TYPE_GET(reg) BSP_FLD32GET(reg, 8, 11)
> +#define DWMAC_DESC_EXT_ERX_DES4_MESSAGE_TYPE_SET(reg, val) BSP_FLD32SET(reg, val, 8, 11)
> +#define DWMAC_DESC_EXT_ERX_DES4_IPV6_PACKET_RECEIVED BSP_BIT32(7)
> +#define DWMAC_DESC_EXT_ERX_DES4_IPV4_PACKET_RECEIVED BSP_BIT32(6)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_CHECKSUM_BYPASSED BSP_BIT32(5)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_ERROR BSP_BIT32(4)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_HEADER_ERROR BSP_BIT32(3)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE(val) BSP_FLD32(val, 0, 2)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE_GET(reg) BSP_FLD32GET(reg, 0, 2)
> +#define DWMAC_DESC_EXT_ERX_DES4_IP_PAYLOAD_TYPE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 2)
> +       uint32_t des5;
> +       uint32_t des6;
> +#define DWMAC_DESC_EXT_ERX_DES6_RECEIVE_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_EXT_ERX_DES6_RECEIVE_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_EXT_ERX_DES6_RECEIVE_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des7;
> +#define DWMAC_DESC_EXT_ERX_DES7_RECEIVE_FRAME_TIMESTAMP_HIGH(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_EXT_ERX_DES7_RECEIVE_FRAME_TIMESTAMP_HIGH_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_EXT_ERX_DES7_RECEIVE_FRAME_TIMESTAMP_HIGH_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_ext_erx;
> +
> +typedef struct {
> +       dwmac_desc_etx des0_3;
> +       uint32_t des4;
> +       uint32_t des5;
> +       uint32_t des6;
> +#define DWMAC_DESC_EXT_ETX_DES6_TRANSMIT_FRAME_TIMESTAMP_LOW(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_EXT_ETX_DES6_TRANSMIT_FRAME_TIMESTAMP_LOW_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_EXT_ETX_DES6_TRANSMIT_FRAME_TIMESTAMP_LOW_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t des7;
> +#define DWMAC_DESC_EXT_ETX_DES7_TRANSMIT_FRAME_TIMESTAMP_HIGH(val) BSP_FLD32(val, 0, 31)
> +#define DWMAC_DESC_EXT_ETX_DES7_TRANSMIT_FRAME_TIMESTAMP_HIGH_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DWMAC_DESC_EXT_ETX_DES7_TRANSMIT_FRAME_TIMESTAMP_HIGH_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +} dwmac_desc_ext_etx;
> +
> +typedef union {
> +       dwmac_desc_ext_erx erx;
> +       dwmac_desc_ext_etx etx;
> +} dwmac_desc_ext;
> +
> +#endif /* DWMAC_DESC_RX_REGS_H */
> diff --git a/c/src/libchip/network/dwmac-regs.h b/c/src/libchip/network/dwmac-regs.h
> new file mode 100644
> index 0000000..53d7486
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac-regs.h
> @@ -0,0 +1,515 @@
> +#ifndef MAC_REGS_H
> +#define MAC_REGS_H
> +
> +#include <bsp/utility.h>
> +
> +typedef struct {
> +       uint32_t high;
> +#define MAC_HIGH_ADDRHI(val) BSP_FLD32(val, 0, 15)
> +#define MAC_HIGH_ADDRHI_GET(reg) BSP_FLD32GET(reg, 0, 15)
> +#define MAC_HIGH_ADDRHI_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15)
> +#define MAC_HIGH_MBC0 BSP_BIT32(24)
> +#define MAC_HIGH_MBC1 BSP_BIT32(25)
> +#define MAC_HIGH_MBC2 BSP_BIT32(26)
> +#define MAC_HIGH_MBC3 BSP_BIT32(27)
> +#define MAC_HIGH_MBC4 BSP_BIT32(28)
> +#define MAC_HIGH_MBC5 BSP_BIT32(29)
> +#define MAC_HIGH_SA BSP_BIT32(30)
> +#define MAC_HIGH_AE BSP_BIT32(31)
> +       uint32_t low;
> +#define MAC_LOW_ADDRLO(val) BSP_FLD32(val, 0, 32)
> +#define MAC_LOW_ADDRLO_GET(reg) BSP_FLD32GET(reg, 0, 32)
> +#define MAC_LOW_ADDRLO_SET(reg, val) BSP_FLD32SET(reg, val, 0, 32)
> +} mac;
> +
> +typedef struct {
> +       uint32_t mac_configuration;
> +#define MACGRP_MAC_CONFIGURATION_PRELEN(val) BSP_FLD32(val, 0, 1)
> +#define MACGRP_MAC_CONFIGURATION_PRELEN_GET(reg) BSP_FLD32GET(reg, 0, 1)
> +#define MACGRP_MAC_CONFIGURATION_PRELEN_SET(reg, val) BSP_FLD32SET(reg, val, 0, 1)
> +#define MACGRP_MAC_CONFIGURATION_RE BSP_BIT32(2)
> +#define MACGRP_MAC_CONFIGURATION_TE BSP_BIT32(3)
> +#define MACGRP_MAC_CONFIGURATION_DC BSP_BIT32(4)
> +#define MACGRP_MAC_CONFIGURATION_BL(val) BSP_FLD32(val, 5, 6)
> +#define MACGRP_MAC_CONFIGURATION_BL_GET(reg) BSP_FLD32GET(reg, 5, 6)
> +#define MACGRP_MAC_CONFIGURATION_BL_SET(reg, val) BSP_FLD32SET(reg, val, 5, 6)
> +#define MACGRP_MAC_CONFIGURATION_ACS BSP_BIT32(7)
> +#define MACGRP_MAC_CONFIGURATION_LUD BSP_BIT32(8)
> +#define MACGRP_MAC_CONFIGURATION_DR BSP_BIT32(9)
> +#define MACGRP_MAC_CONFIGURATION_IPC BSP_BIT32(10)
> +#define MACGRP_MAC_CONFIGURATION_DM BSP_BIT32(11)
> +#define MACGRP_MAC_CONFIGURATION_LM BSP_BIT32(12)
> +#define MACGRP_MAC_CONFIGURATION_DO BSP_BIT32(13)
> +#define MACGRP_MAC_CONFIGURATION_FES BSP_BIT32(14)
> +#define MACGRP_MAC_CONFIGURATION_PS BSP_BIT32(15)
> +#define MACGRP_MAC_CONFIGURATION_DCRS BSP_BIT32(16)
> +#define MACGRP_MAC_CONFIGURATION_IFG(val) BSP_FLD32(val, 17, 19)
> +#define MACGRP_MAC_CONFIGURATION_IFG_GET(reg) BSP_FLD32GET(reg, 17, 19)
> +#define MACGRP_MAC_CONFIGURATION_IFG_SET(reg, val) BSP_FLD32SET(reg, val, 17, 19)
> +#define MACGRP_MAC_CONFIGURATION_JE BSP_BIT32(20)
> +#define MACGRP_MAC_CONFIGURATION_BE BSP_BIT32(21)
> +#define MACGRP_MAC_CONFIGURATION_JD BSP_BIT32(22)
> +#define MACGRP_MAC_CONFIGURATION_WD BSP_BIT32(23)
> +#define MACGRP_MAC_CONFIGURATION_TC BSP_BIT32(24)
> +#define MACGRP_MAC_CONFIGURATION_CST BSP_BIT32(25)
> +#define MACGRP_MAC_CONFIGURATION_TWOKPE BSP_BIT32(27)
> +       uint32_t mac_frame_filter;
> +#define MACGRP_MAC_FRAME_FILTER_PR BSP_BIT32(0)
> +#define MACGRP_MAC_FRAME_FILTER_HUC BSP_BIT32(1)
> +#define MACGRP_MAC_FRAME_FILTER_HMC BSP_BIT32(2)
> +#define MACGRP_MAC_FRAME_FILTER_DAIF BSP_BIT32(3)
> +#define MACGRP_MAC_FRAME_FILTER_PM BSP_BIT32(4)
> +#define MACGRP_MAC_FRAME_FILTER_DBF BSP_BIT32(5)
> +#define MACGRP_MAC_FRAME_FILTER_PCF(val) BSP_FLD32(val, 6, 7)
> +#define MACGRP_MAC_FRAME_FILTER_PCF_GET(reg) BSP_FLD32GET(reg, 6, 7)
> +#define MACGRP_MAC_FRAME_FILTER_PCF_SET(reg, val) BSP_FLD32SET(reg, val, 6, 7)
> +#define MACGRP_MAC_FRAME_FILTER_SAIF BSP_BIT32(8)
> +#define MACGRP_MAC_FRAME_FILTER_SAF BSP_BIT32(9)
> +#define MACGRP_MAC_FRAME_FILTER_HPF BSP_BIT32(10)
> +#define MACGRP_MAC_FRAME_FILTER_VTFE BSP_BIT32(16)
> +#define MACGRP_MAC_FRAME_FILTER_IPFE BSP_BIT32(20)
> +#define MACGRP_MAC_FRAME_FILTER_DNTU BSP_BIT32(21)
> +#define MACGRP_MAC_FRAME_FILTER_RA BSP_BIT32(31)
> +       uint32_t reserved_08[2];
> +       uint32_t gmii_address;
> +#define MACGRP_GMII_ADDRESS_GMII_BUSY BSP_BIT32(0)
> +#define MACGRP_GMII_ADDRESS_GMII_WRITE BSP_BIT32(1)
> +#define MACGRP_GMII_ADDRESS_CSR_CLOCK_RANGE(val) BSP_FLD32(val, 2, 5)
> +#define MACGRP_GMII_ADDRESS_CSR_CLOCK_RANGE_GET(reg) BSP_FLD32GET(reg, 2, 5)
> +#define MACGRP_GMII_ADDRESS_CSR_CLOCK_RANGE_SET(reg, val) BSP_FLD32SET(reg, val, 2, 5)
> +#define MACGRP_GMII_ADDRESS_GMII_REGISTER(val) BSP_FLD32(val, 6, 10)
> +#define MACGRP_GMII_ADDRESS_GMII_REGISTER_GET(reg) BSP_FLD32GET(reg, 6, 10)
> +#define MACGRP_GMII_ADDRESS_GMII_REGISTER_SET(reg, val) BSP_FLD32SET(reg, val, 6, 10)
> +#define MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS(val) BSP_FLD32(val, 11, 15)
> +#define MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_GET(reg) BSP_FLD32GET(reg, 11, 15)
> +#define MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_SET(reg, val) BSP_FLD32SET(reg, val, 11, 15)
> +       uint32_t gmii_data;
> +#define MACGRP_GMII_DATA_GMII_DATA(val) BSP_FLD32(val, 0, 15)
> +#define MACGRP_GMII_DATA_GMII_DATA_GET(reg) BSP_FLD32GET(reg, 0, 15)
> +#define MACGRP_GMII_DATA_GMII_DATA_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15)
> +       uint32_t reserved_18[9];
> +       uint32_t interrupt_mask;
> +#define MACGRP_INTERRUPT_MASK_RGSMIIIM BSP_BIT32(0)
> +#define MACGRP_INTERRUPT_MASK_PCSLCHGIM BSP_BIT32(1)
> +#define MACGRP_INTERRUPT_MASK_PCSANCIM BSP_BIT32(2)
> +#define MACGRP_INTERRUPT_MASK_TSIM BSP_BIT32(9)
> +#define MACGRP_INTERRUPT_MASK_LPIIM BSP_BIT32(10)
> +       mac mac_addr0_15[16];
> +       uint32_t reserved_c0[16];
> +       uint32_t mmc_control;
> +#define MACGRP_MMC_CONTROL_CNTRST BSP_BIT32(0)
> +#define MACGRP_MMC_CONTROL_CNTSTOPRO BSP_BIT32(1)
> +#define MACGRP_MMC_CONTROL_RSTONRD BSP_BIT32(2)
> +#define MACGRP_MMC_CONTROL_CNTFREEZ BSP_BIT32(3)
> +#define MACGRP_MMC_CONTROL_CNTPRST BSP_BIT32(4)
> +#define MACGRP_MMC_CONTROL_CNTPRSTLVL BSP_BIT32(5)
> +#define MACGRP_MMC_CONTROL_UCDBC BSP_BIT32(8)
> +       uint32_t mmc_receive_interrupt;
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXGBFRMIS BSP_BIT32(0)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXGBOCTIS BSP_BIT32(1)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXGOCTIS BSP_BIT32(2)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXBCGFIS BSP_BIT32(3)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXMCGFIS BSP_BIT32(4)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXCRCERFIS BSP_BIT32(5)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXALGNERFIS BSP_BIT32(6)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXRUNTFIS BSP_BIT32(7)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXJABERFIS BSP_BIT32(8)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXUSIZEGFIS BSP_BIT32(9)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXOSIZEGFIS BSP_BIT32(10)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX64OCTGBFIS BSP_BIT32(11)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX65T127OCTGBFIS BSP_BIT32(12)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX128T255OCTGBFIS BSP_BIT32(13)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX256T511OCTGBFIS BSP_BIT32(14)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX512T1023OCTGBFIS BSP_BIT32(15)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RX1024TMAXOCTGBFIS BSP_BIT32(16)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXUCGFIS BSP_BIT32(17)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXLENERFIS BSP_BIT32(18)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXORANGEFIS BSP_BIT32(19)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXPAUSFIS BSP_BIT32(20)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXFOVFIS BSP_BIT32(21)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXVLANGBFIS BSP_BIT32(22)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXWDOGFIS BSP_BIT32(23)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXRCVERRFIS BSP_BIT32(24)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_RXCTRLFIS BSP_BIT32(25)
> +       uint32_t mmc_transmit_interrupt;
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXGBOCTIS BSP_BIT32(0)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXGBFRMIS BSP_BIT32(1)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXBCGFIS BSP_BIT32(2)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXMCGFIS BSP_BIT32(3)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX64OCTGBFIS BSP_BIT32(4)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX65T127OCTGBFIS BSP_BIT32(5)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX128T255OCTGBFIS BSP_BIT32(6)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX256T511OCTGBFIS BSP_BIT32(7)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX512T1023OCTGBFIS BSP_BIT32(8)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TX1024TMAXOCTGBFIS BSP_BIT32(9)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXUCGBFIS BSP_BIT32(10)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXMCGBFIS BSP_BIT32(11)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXBCGBFIS BSP_BIT32(12)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXUFLOWERFIS BSP_BIT32(13)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXSCOLGFIS BSP_BIT32(14)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXMCOLGFIS BSP_BIT32(15)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXDEFFIS BSP_BIT32(16)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXLATCOLFIS BSP_BIT32(17)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXEXCOLFIS BSP_BIT32(18)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXCARERFIS BSP_BIT32(19)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXGOCTIS BSP_BIT32(20)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXGFRMIS BSP_BIT32(21)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXEXDEFFIS BSP_BIT32(22)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXPAUSFIS BSP_BIT32(23)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXVLANGFIS BSP_BIT32(24)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_TXOSIZEGFIS BSP_BIT32(25)
> +       uint32_t mmc_receive_interrupt_mask;
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXGBFRMIM BSP_BIT32(0)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXGBOCTIM BSP_BIT32(1)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXGOCTIM BSP_BIT32(2)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXBCGFIM BSP_BIT32(3)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXMCGFIM BSP_BIT32(4)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXCRCERFIM BSP_BIT32(5)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXALGNERFIM BSP_BIT32(6)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXRUNTFIM BSP_BIT32(7)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXJABERFIM BSP_BIT32(8)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXUSIZEGFIM BSP_BIT32(9)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXOSIZEGFIM BSP_BIT32(10)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX64OCTGBFIM BSP_BIT32(11)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX65T127OCTGBFIM BSP_BIT32(12)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX128T255OCTGBFIM BSP_BIT32(13)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX256T511OCTGBFIM BSP_BIT32(14)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX512T1023OCTGBFIM BSP_BIT32(15)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RX1024TMAXOCTGBFIM BSP_BIT32(16)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXUCGFIM BSP_BIT32(17)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXLENERFIM BSP_BIT32(18)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXORANGEFIM BSP_BIT32(19)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXPAUSFIM BSP_BIT32(20)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXFOVFIM BSP_BIT32(21)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXVLANGBFIM BSP_BIT32(22)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXWDOGFIM BSP_BIT32(23)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXRCVERRFIM BSP_BIT32(24)
> +#define MACGRP_MMC_RECEIVE_INTERRUPT_MASK_RXCTRLFIM BSP_BIT32(25)
> +       uint32_t mmc_transmit_interrupt_mask;
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXGBOCTIM BSP_BIT32(0)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXGBFRMIM BSP_BIT32(1)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXBCGFIM BSP_BIT32(2)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXMCGFIM BSP_BIT32(3)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX64OCTGBFIM BSP_BIT32(4)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX65T127OCTGBFIM BSP_BIT32(5)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX128T255OCTGBFIM BSP_BIT32(6)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX256T511OCTGBFIM BSP_BIT32(7)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX512T1023OCTGBFIM BSP_BIT32(8)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TX1024TMAXOCTGBFIM BSP_BIT32(9)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXUCGBFIM BSP_BIT32(10)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXMCGBFIM BSP_BIT32(11)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXBCGBFIM BSP_BIT32(12)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXUFLOWERFIM BSP_BIT32(13)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXSCOLGFIM BSP_BIT32(14)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXMCOLGFIM BSP_BIT32(15)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXDEFFIM BSP_BIT32(16)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXLATCOLFIM BSP_BIT32(17)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXEXCOLFIM BSP_BIT32(18)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXCARERFIM BSP_BIT32(19)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXGOCTIM BSP_BIT32(20)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXGFRMIM BSP_BIT32(21)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXEXDEFFIM BSP_BIT32(22)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXPAUSFIM BSP_BIT32(23)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXVLANGFIM BSP_BIT32(24)
> +#define MACGRP_MMC_TRANSMIT_INTERRUPT_MASK_TXOSIZEGFIM BSP_BIT32(25)
> +       uint32_t txoctetcount_gb;
> +       uint32_t txframecount_gb;
> +       uint32_t txbroadcastframes_g;
> +       uint32_t txmulticastframes_g;
> +       uint32_t tx64octets_gb;
> +       uint32_t tx65to127octets_gb;
> +       uint32_t tx128to255octets_gb;
> +       uint32_t tx256to511octets_gb;
> +       uint32_t tx512to1023octets_gb;
> +       uint32_t tx1024tomaxoctets_gb;
> +       uint32_t txunicastframes_gb;
> +       uint32_t txmulticastframes_gb;
> +       uint32_t txbroadcastframes_gb;
> +       uint32_t txunderflowerror;
> +       uint32_t txsinglecol_g;
> +       uint32_t txmulticol_g;
> +       uint32_t txdeferred;
> +       uint32_t txlatecol;
> +       uint32_t txexesscol;
> +       uint32_t txcarriererr;
> +       uint32_t txoctetcnt;
> +       uint32_t txframecount_g;
> +       uint32_t txexcessdef;
> +       uint32_t txpauseframes;
> +       uint32_t txvlanframes_g;
> +       uint32_t txoversize_g;
> +       uint32_t reserved_17c;
> +       uint32_t rxframecount_gb;
> +       uint32_t rxoctetcount_gb;
> +       uint32_t rxoctetcount_g;
> +       uint32_t rxbroadcastframes_g;
> +       uint32_t rxmulticastframes_g;
> +       uint32_t rxcrcerror;
> +       uint32_t rxalignmenterror;
> +       uint32_t rxrunterror;
> +       uint32_t rxjabbererror;
> +       uint32_t rxundersize_g;
> +       uint32_t rxoversize_g;
> +       uint32_t rx64octets_gb;
> +       uint32_t rx65to127octets_gb;
> +       uint32_t rx128to255octets_gb;
> +       uint32_t rx256to511octets_gb;
> +       uint32_t rx512to1023octets_gb;
> +       uint32_t rx1024tomaxoctets_gb;
> +       uint32_t rxunicastframes_g;
> +       uint32_t rxlengtherror;
> +       uint32_t rxoutofrangetype;
> +       uint32_t rxpauseframes;
> +       uint32_t rxfifooverflow;
> +       uint32_t rxvlanframes_gb;
> +       uint32_t rxwatchdogerror;
> +       uint32_t rxrcverror;
> +       uint32_t rxctrlframes_g;
> +       uint32_t reserved_1e8[6];
> +       uint32_t mmc_ipc_receive_interrupt_mask;
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4GFIM BSP_BIT32(0)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4HERFIM BSP_BIT32(1)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4NOPAYFIM BSP_BIT32(2)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4FRAGFIM BSP_BIT32(3)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4UDSBLFIM BSP_BIT32(4)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6GFIM BSP_BIT32(5)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6HERFIM BSP_BIT32(6)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6NOPAYFIM BSP_BIT32(7)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXUDPGFIM BSP_BIT32(8)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXUDPERFIM BSP_BIT32(9)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXTCPGFIM BSP_BIT32(10)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXTCPERFIM BSP_BIT32(11)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXICMPGFIM BSP_BIT32(12)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXICMPERFIM BSP_BIT32(13)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4GOIM BSP_BIT32(16)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4HEROIM BSP_BIT32(17)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4NOPAYOIM BSP_BIT32(18)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4FRAGOIM BSP_BIT32(19)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV4UDSBLOIM BSP_BIT32(20)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6GOIM BSP_BIT32(21)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6HEROIM BSP_BIT32(22)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXIPV6NOPAYOIM BSP_BIT32(23)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXUDPGOIM BSP_BIT32(24)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXUDPEROIM BSP_BIT32(25)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXTCPGOIM BSP_BIT32(26)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXTCPEROIM BSP_BIT32(27)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXICMPGOIM BSP_BIT32(28)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_MASK_RXICMPEROIM BSP_BIT32(29)
> +       uint32_t reserved_204;
> +       uint32_t mmc_ipc_receive_interrupt;
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4GFIS BSP_BIT32(0)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4HERFIS BSP_BIT32(1)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4NOPAYFIS BSP_BIT32(2)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4FRAGFIS BSP_BIT32(3)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4UDSBLFIS BSP_BIT32(4)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6GFIS BSP_BIT32(5)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6HERFIS BSP_BIT32(6)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6NOPAYFIS BSP_BIT32(7)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXUDPGFIS BSP_BIT32(8)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXUDPERFIS BSP_BIT32(9)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXTCPGFIS BSP_BIT32(10)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXTCPERFIS BSP_BIT32(11)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXICMPGFIS BSP_BIT32(12)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXICMPERFIS BSP_BIT32(13)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4GOIS BSP_BIT32(16)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4HEROIS BSP_BIT32(17)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4NOPAYOIS BSP_BIT32(18)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4FRAGOIS BSP_BIT32(19)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV4UDSBLOIS BSP_BIT32(20)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6GOIS BSP_BIT32(21)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6HEROIS BSP_BIT32(22)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXIPV6NOPAYOIS BSP_BIT32(23)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXUDPGOIS BSP_BIT32(24)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXUDPEROIS BSP_BIT32(25)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXTCPGOIS BSP_BIT32(26)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXTCPEROIS BSP_BIT32(27)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXICMPGOIS BSP_BIT32(28)
> +#define MACGRP_MMC_IPC_RECEIVE_INTERRUPT_RXICMPEROIS BSP_BIT32(29)
> +       uint32_t reserved_20c;
> +       uint32_t rxipv4_gd_frms;
> +       uint32_t rxipv4_hdrerr_frms;
> +       uint32_t rxipv4_nopay_frms;
> +       uint32_t rxipv4_frag_frms;
> +       uint32_t rxipv4_udsbl_frms;
> +       uint32_t rxipv6_gd_frms;
> +       uint32_t rxipv6_hdrerr_frms;
> +       uint32_t rxipv6_nopay_frms;
> +       uint32_t rxudp_gd_frms;
> +       uint32_t rxudp_err_frms;
> +       uint32_t rxtcp_gd_frms;
> +       uint32_t rxtcp_err_frms;
> +       uint32_t rxicmp_gd_frms;
> +       uint32_t rxicmp_err_frms;
> +       uint32_t reserved_248[2];
> +       uint32_t rxipv4_gd_octets;
> +       uint32_t rxipv4_hdrerr_octets;
> +       uint32_t rxipv4_nopay_octets;
> +       uint32_t rxipv4_frag_octets;
> +       uint32_t rxipv4_udsbl_octets;
> +       uint32_t rxipv6_gd_octets;
> +       uint32_t rxipv6_hdrerr_octets;
> +       uint32_t rxipv6_nopay_octets;
> +       uint32_t rxudp_gd_octets;
> +       uint32_t rxudp_err_octets;
> +       uint32_t rxtcp_gd_octets;
> +       uint32_t rxtcperroctets;
> +       uint32_t rxicmp_gd_octets;
> +       uint32_t rxicmp_err_octets;
> +       uint32_t reserved_288[158];
> +       uint32_t hash_table_reg[8];
> +       uint32_t reserved_520[184];
> +       mac mac_addr16_127[112];
> +} macgrp;
> +
> +typedef struct {
> +       uint32_t bus_mode;
> +#define DMAGRP_BUS_MODE_SWR BSP_BIT32(0)
> +#define DMAGRP_BUS_MODE_DSL(val) BSP_FLD32(val, 2, 6)
> +#define DMAGRP_BUS_MODE_DSL_GET(reg) BSP_FLD32GET(reg, 2, 6)
> +#define DMAGRP_BUS_MODE_DSL_SET(reg, val) BSP_FLD32SET(reg, val, 2, 6)
> +#define DMAGRP_BUS_MODE_ATDS BSP_BIT32(7)
> +#define DMAGRP_BUS_MODE_PBL(val) BSP_FLD32(val, 8, 13)
> +#define DMAGRP_BUS_MODE_PBL_GET(reg) BSP_FLD32GET(reg, 8, 13)
> +#define DMAGRP_BUS_MODE_PBL_SET(reg, val) BSP_FLD32SET(reg, val, 8, 13)
> +#define DMAGRP_BUS_MODE_FB BSP_BIT32(16)
> +#define DMAGRP_BUS_MODE_RPBL(val) BSP_FLD32(val, 17, 22)
> +#define DMAGRP_BUS_MODE_RPBL_GET(reg) BSP_FLD32GET(reg, 17, 22)
> +#define DMAGRP_BUS_MODE_RPBL_SET(reg, val) BSP_FLD32SET(reg, val, 17, 22)
> +#define DMAGRP_BUS_MODE_USP BSP_BIT32(23)
> +#define DMAGRP_BUS_MODE_EIGHTXPBL BSP_BIT32(24)
> +#define DMAGRP_BUS_MODE_AAL BSP_BIT32(25)
> +#define DMAGRP_BUS_MODE_MB BSP_BIT32(26)
> +       uint32_t transmit_poll_demand;
> +#define DMAGRP_TRANSMIT_POLL_DEMAND_TPD(val) BSP_FLD32(val, 0, 31)
> +#define DMAGRP_TRANSMIT_POLL_DEMAND_TPD_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DMAGRP_TRANSMIT_POLL_DEMAND_TPD_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t receive_poll_demand;
> +#define DMAGRP_RECEIVE_POLL_DEMAND_RPD(val) BSP_FLD32(val, 0, 31)
> +#define DMAGRP_RECEIVE_POLL_DEMAND_RPD_GET(reg) BSP_FLD32GET(reg, 0, 31)
> +#define DMAGRP_RECEIVE_POLL_DEMAND_RPD_SET(reg, val) BSP_FLD32SET(reg, val, 0, 31)
> +       uint32_t receive_descr_list_addr;
> +#define DMAGRP_RECEIVE_DESCR_LIST_ADDR_RDESLA_32BIT(val) BSP_FLD32(val, 2, 31)
> +#define DMAGRP_RECEIVE_DESCR_LIST_ADDR_RDESLA_32BIT_GET(reg) BSP_FLD32GET(reg, 2, 31)
> +#define DMAGRP_RECEIVE_DESCR_LIST_ADDR_RDESLA_32BIT_SET(reg, val) BSP_FLD32SET(reg, val, 2, 31)
> +       uint32_t transmit_descr_list_addr;
> +#define DMAGRP_TRANSMIT_DESCR_LIST_ADDR_TDESLA_32BIT(val) BSP_FLD32(val, 2, 31)
> +#define DMAGRP_TRANSMIT_DESCR_LIST_ADDR_TDESLA_32BIT_GET(reg) BSP_FLD32GET(reg, 2, 31)
> +#define DMAGRP_TRANSMIT_DESCR_LIST_ADDR_TDESLA_32BIT_SET(reg, val) BSP_FLD32SET(reg, val, 2, 31)
> +       uint32_t status;
> +#define DMAGRP_STATUS_TI BSP_BIT32(0)
> +#define DMAGRP_STATUS_TPS BSP_BIT32(1)
> +#define DMAGRP_STATUS_TU BSP_BIT32(2)
> +#define DMAGRP_STATUS_TJT BSP_BIT32(3)
> +#define DMAGRP_STATUS_OVF BSP_BIT32(4)
> +#define DMAGRP_STATUS_UNF BSP_BIT32(5)
> +#define DMAGRP_STATUS_RI BSP_BIT32(6)
> +#define DMAGRP_STATUS_RU BSP_BIT32(7)
> +#define DMAGRP_STATUS_RPS BSP_BIT32(8)
> +#define DMAGRP_STATUS_RWT BSP_BIT32(9)
> +#define DMAGRP_STATUS_ETI BSP_BIT32(10)
> +#define DMAGRP_STATUS_FBI BSP_BIT32(13)
> +#define DMAGRP_STATUS_ERI BSP_BIT32(14)
> +#define DMAGRP_STATUS_AIS BSP_BIT32(15)
> +#define DMAGRP_STATUS_NIS BSP_BIT32(16)
> +#define DMAGRP_STATUS_RS(val) BSP_FLD32(val, 17, 19)
> +#define DMAGRP_STATUS_RS_GET(reg) BSP_FLD32GET(reg, 17, 19)
> +#define DMAGRP_STATUS_RS_SET(reg, val) BSP_FLD32SET(reg, val, 17, 19)
> +#define DMAGRP_STATUS_TS(val) BSP_FLD32(val, 20, 22)
> +#define DMAGRP_STATUS_TS_GET(reg) BSP_FLD32GET(reg, 20, 22)
> +#define DMAGRP_STATUS_TS_SET(reg, val) BSP_FLD32SET(reg, val, 20, 22)
> +#define DMAGRP_STATUS_EB(val) BSP_FLD32(val, 23, 25)
> +#define DMAGRP_STATUS_EB_GET(reg) BSP_FLD32GET(reg, 23, 25)
> +#define DMAGRP_STATUS_EB_SET(reg, val) BSP_FLD32SET(reg, val, 23, 25)
> +#define DMAGRP_STATUS_GLI BSP_BIT32(26)
> +#define DMAGRP_STATUS_GMI BSP_BIT32(27)
> +#define DMAGRP_STATUS_TTI BSP_BIT32(29)
> +#define DMAGRP_STATUS_GLPII BSP_BIT32(30)
> +       uint32_t operation_mode;
> +#define DMAGRP_OPERATION_MODE_SR BSP_BIT32(1)
> +#define DMAGRP_OPERATION_MODE_OSF BSP_BIT32(2)
> +#define DMAGRP_OPERATION_MODE_RTC(val) BSP_FLD32(val, 3, 4)
> +#define DMAGRP_OPERATION_MODE_RTC_GET(reg) BSP_FLD32GET(reg, 3, 4)
> +#define DMAGRP_OPERATION_MODE_RTC_SET(reg, val) BSP_FLD32SET(reg, val, 3, 4)
> +#define DMAGRP_OPERATION_MODE_FUF BSP_BIT32(6)
> +#define DMAGRP_OPERATION_MODE_FEF BSP_BIT32(7)
> +#define DMAGRP_OPERATION_MODE_EFC BSP_BIT32(8)
> +#define DMAGRP_OPERATION_MODE_RFA(val) BSP_FLD32(val, 9, 10)
> +#define DMAGRP_OPERATION_MODE_RFA_GET(reg) BSP_FLD32GET(reg, 9, 10)
> +#define DMAGRP_OPERATION_MODE_RFA_SET(reg, val) BSP_FLD32SET(reg, val, 9, 10)
> +#define DMAGRP_OPERATION_MODE_RFD(val) BSP_FLD32(val, 11, 12)
> +#define DMAGRP_OPERATION_MODE_RFD_GET(reg) BSP_FLD32GET(reg, 11, 12)
> +#define DMAGRP_OPERATION_MODE_RFD_SET(reg, val) BSP_FLD32SET(reg, val, 11, 12)
> +#define DMAGRP_OPERATION_MODE_ST BSP_BIT32(13)
> +#define DMAGRP_OPERATION_MODE_TTC(val) BSP_FLD32(val, 14, 16)
> +#define DMAGRP_OPERATION_MODE_TTC_GET(reg) BSP_FLD32GET(reg, 14, 16)
> +#define DMAGRP_OPERATION_MODE_TTC_SET(reg, val) BSP_FLD32SET(reg, val, 14, 16)
> +#define DMAGRP_OPERATION_MODE_FTF BSP_BIT32(20)
> +#define DMAGRP_OPERATION_MODE_TSF BSP_BIT32(21)
> +#define DMAGRP_OPERATION_MODE_DFF BSP_BIT32(24)
> +#define DMAGRP_OPERATION_MODE_RSF BSP_BIT32(25)
> +#define DMAGRP_OPERATION_MODE_DT BSP_BIT32(26)
> +       uint32_t interrupt_enable;
> +#define DMAGRP_INTERRUPT_ENABLE_TIE BSP_BIT32(0)
> +#define DMAGRP_INTERRUPT_ENABLE_TSE BSP_BIT32(1)
> +#define DMAGRP_INTERRUPT_ENABLE_TUE BSP_BIT32(2)
> +#define DMAGRP_INTERRUPT_ENABLE_TJE BSP_BIT32(3)
> +#define DMAGRP_INTERRUPT_ENABLE_OVE BSP_BIT32(4)
> +#define DMAGRP_INTERRUPT_ENABLE_UNE BSP_BIT32(5)
> +#define DMAGRP_INTERRUPT_ENABLE_RIE BSP_BIT32(6)
> +#define DMAGRP_INTERRUPT_ENABLE_RUE BSP_BIT32(7)
> +#define DMAGRP_INTERRUPT_ENABLE_RSE BSP_BIT32(8)
> +#define DMAGRP_INTERRUPT_ENABLE_RWE BSP_BIT32(9)
> +#define DMAGRP_INTERRUPT_ENABLE_ETE BSP_BIT32(10)
> +#define DMAGRP_INTERRUPT_ENABLE_FBE BSP_BIT32(13)
> +#define DMAGRP_INTERRUPT_ENABLE_ERE BSP_BIT32(14)
> +#define DMAGRP_INTERRUPT_ENABLE_AIE BSP_BIT32(15)
> +#define DMAGRP_INTERRUPT_ENABLE_NIE BSP_BIT32(16)
> +       uint32_t reserved_20[2];
> +       uint32_t axi_bus_mode;
> +#define DMAGRP_AXI_BUS_MODE_UNDEFINED BSP_BIT32(0)
> +#define DMAGRP_AXI_BUS_MODE_BLEND4 BSP_BIT32(1)
> +#define DMAGRP_AXI_BUS_MODE_BLEND8 BSP_BIT32(2)
> +#define DMAGRP_AXI_BUS_MODE_BLEND16 BSP_BIT32(3)
> +#define DMAGRP_AXI_BUS_MODE_AXI_AAL BSP_BIT32(12)
> +#define DMAGRP_AXI_BUS_MODE_ONEKBBE BSP_BIT32(13)
> +#define DMAGRP_AXI_BUS_MODE_RD_OSR_LMT(val) BSP_FLD32(val, 16, 19)
> +#define DMAGRP_AXI_BUS_MODE_RD_OSR_LMT_GET(reg) BSP_FLD32GET(reg, 16, 19)
> +#define DMAGRP_AXI_BUS_MODE_RD_OSR_LMT_SET(reg, val) BSP_FLD32SET(reg, val, 16, 19)
> +#define DMAGRP_AXI_BUS_MODE_WR_OSR_LMT(val) BSP_FLD32(val, 20, 23)
> +#define DMAGRP_AXI_BUS_MODE_WR_OSR_LMT_GET(reg) BSP_FLD32GET(reg, 20, 23)
> +#define DMAGRP_AXI_BUS_MODE_WR_OSR_LMT_SET(reg, val) BSP_FLD32SET(reg, val, 20, 23)
> +#define DMAGRP_AXI_BUS_MODE_LPI_XIT_FRM BSP_BIT32(30)
> +#define DMAGRP_AXI_BUS_MODE_EN_LPI BSP_BIT32(31)
> +       uint32_t reserved_2c[11];
> +       uint32_t hw_feature;
> +#define DMAGRP_HW_FEATURE_MIISEL BSP_BIT32(0)
> +#define DMAGRP_HW_FEATURE_GMIISEL BSP_BIT32(1)
> +#define DMAGRP_HW_FEATURE_HDSEL BSP_BIT32(2)
> +#define DMAGRP_HW_FEATURE_HASHSEL BSP_BIT32(4)
> +#define DMAGRP_HW_FEATURE_ADDMACADRSEL BSP_BIT32(5)
> +#define DMAGRP_HW_FEATURE_PCSSEL BSP_BIT32(6)
> +#define DMAGRP_HW_FEATURE_SMASEL BSP_BIT32(8)
> +#define DMAGRP_HW_FEATURE_RWKSEL BSP_BIT32(9)
> +#define DMAGRP_HW_FEATURE_MGKSEL BSP_BIT32(10)
> +#define DMAGRP_HW_FEATURE_MMCSEL BSP_BIT32(11)
> +#define DMAGRP_HW_FEATURE_TSVER1SEL BSP_BIT32(12)
> +#define DMAGRP_HW_FEATURE_TSVER2SEL BSP_BIT32(13)
> +#define DMAGRP_HW_FEATURE_EEESEL BSP_BIT32(14)
> +#define DMAGRP_HW_FEATURE_AVSEL BSP_BIT32(15)
> +#define DMAGRP_HW_FEATURE_TXOESEL BSP_BIT32(16)
> +#define DMAGRP_HW_FEATURE_RXTYP1COE BSP_BIT32(17)
> +#define DMAGRP_HW_FEATURE_RXTYP2COE BSP_BIT32(18)
> +#define DMAGRP_HW_FEATURE_RXFIFOSIZE BSP_BIT32(19)
> +#define DMAGRP_HW_FEATURE_RXCHCNT(val) BSP_FLD32(val, 20, 21)
> +#define DMAGRP_HW_FEATURE_RXCHCNT_GET(reg) BSP_FLD32GET(reg, 20, 21)
> +#define DMAGRP_HW_FEATURE_RXCHCNT_SET(reg, val) BSP_FLD32SET(reg, val, 20, 21)
> +#define DMAGRP_HW_FEATURE_TXCHCNT(val) BSP_FLD32(val, 22, 23)
> +#define DMAGRP_HW_FEATURE_TXCHCNT_GET(reg) BSP_FLD32GET(reg, 22, 23)
> +#define DMAGRP_HW_FEATURE_TXCHCNT_SET(reg, val) BSP_FLD32SET(reg, val, 22, 23)
> +#define DMAGRP_HW_FEATURE_ENHDESSEL BSP_BIT32(24)
> +#define DMAGRP_HW_FEATURE_ACTPHYIF(val) BSP_FLD32(val, 28, 30)
> +#define DMAGRP_HW_FEATURE_ACTPHYIF_GET(reg) BSP_FLD32GET(reg, 28, 30)
> +#define DMAGRP_HW_FEATURE_ACTPHYIF_SET(reg, val) BSP_FLD32SET(reg, val, 28, 30)
> +} dmagrp;
> +
> +#endif /* MAC_REGS_H */
> diff --git a/c/src/libchip/network/dwmac.c b/c/src/libchip/network/dwmac.c
> new file mode 100644
> index 0000000..f722031
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac.c
> @@ -0,0 +1,2341 @@
> +/**
> + * @file dwmac.c
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief DWMAC 10/100/1000 Network Interface Controller
> + *
> + * DWMAC 10/100/1000 on-chip Ethernet controllers are a Synopsys IP Core.
> + * This is the main mode for the network interface controller.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#include <assert.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <rtems.h>
> +#include <rtems/endian.h>
> +#include "dwmac-common.h"
> +#include "dwmac-core.h"
> +#include <bsp/irq.h>
> +
> +/* PHY events which can be combined to an event set.
> + * The PHY can create an event for a corresponding status change */
> +const dwmac_phy_event PHY_EVENT_JABBER                = 0x80;
> +const dwmac_phy_event PHY_EVENT_RECEIVE_ERROR         = 0x40;
> +const dwmac_phy_event PHY_EVENT_PAGE_RECEIVE          = 0x20;
> +const dwmac_phy_event PHY_EVENT_PARALLEL_DETECT_FAULT = 0x10;
> +const dwmac_phy_event PHY_EVENT_LINK_PARTNER_ACK      = 0x08;
> +const dwmac_phy_event PHY_EVENT_LINK_DOWN             = 0x04;
> +const dwmac_phy_event PHY_EVENT_REMOTE_FAULT          = 0x02;
> +const dwmac_phy_event PHY_EVENT_LINK_UP               = 0x01;
> +
> +/* Default values for the number of DMA descriptors and mbufs to be used */
> +#define DWMAC_CONFIG_RX_UNIT_COUNT_DEFAULT 256
> +#define DWMAC_CONFIG_RX_UNIT_COUNT_MAX INT_MAX
> +#define DWMAC_CONFIG_TX_UNIT_COUNT_DEFAULT 256
> +#define DWMAC_CONFIG_TX_UNIT_COUNT_MAX INT_MAX
> +
> +/* Default values for the DMA configuration */
> +#define DWMAC_DMA_BUS_MODE_PBL_DEFAULT DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_8
> +#define DWMAC_DMA_BUS_MODE_FB_DEFAULT \
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_SINGLE_OR_INCR
> +#define DWMAC_DMA_BUS_MODE_MIXED_BURSTS_DEFAULT \
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_NOT_MIXED
> +#define DWMAC_DMA_AXI_BURST_LENGTH_4_DEFAULT \
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_NOT_SUPPORTED
> +#define DWMAC_DMA_AXI_BURST_LENGTH_8_DEFAULT \
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_NOT_SUPPORTED
> +#define DWMAC_DMA_AXI_BURST_LENGTH_16_DEFAULT \
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_NOT_SUPPORTED
> +#define DWMAC_DMA_AXI_BURST_BOUNDARY_DEFAULT \
> +  DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_4_KB
> +
> +/* CSR Frequency Access Defines*/
> +#define DWCGNAC3504_CSR_F_35M 35000000
> +#define DWCGNAC3504_CSR_F_60M 60000000
> +#define DWCGNAC3504_CSR_F_100M 100000000
> +#define DWCGNAC3504_CSR_F_150M 150000000
> +#define DWCGNAC3504_CSR_F_250M 250000000
> +#define DWCGNAC3504_CSR_F_300M 300000000
> +
> +/* MDC Clock Selection define*/
> +#define DWCGNAC3504_CSR_60_100M 0x0 /* MDC = clk_scr_i/42 */
> +#define DWCGNAC3504_CSR_100_150M 0x1 /* MDC = clk_scr_i/62 */
> +#define DWCGNAC3504_CSR_20_35M 0x2 /* MDC = clk_scr_i/16 */
> +#define DWCGNAC3504_CSR_35_60M 0x3 /* MDC = clk_scr_i/26 */
> +#define DWCGNAC3504_CSR_150_250M 0x4 /* MDC = clk_scr_i/102 */
> +#define DWCGNAC3504_CSR_250_300M 0x5 /* MDC = clk_scr_i/122 */
> +
> +#define DWMAC_ALIGN( value, num_bytes_to_align_to ) \
> +  ( ( ( value ) + ( ( typeof( value ) )( num_bytes_to_align_to ) - 1 ) ) \
> +    & ~( ( typeof( value ) )( num_bytes_to_align_to ) - 1 ) )
> +
> +#undef DWMAC_DEBUG
> +#ifdef DWMAC_DEBUG
> +#define DWMAC_PRINT_DBG( fmt, args ... )  printk( fmt, ## args )
> +#else
> +#define DWMAC_PRINT_DBG( fmt, args ... )  do { } while ( 0 )
> +#endif
> +
> +#define DWMAC_DMA_THRESHOLD_CONTROL_DEFAULT 64
> +
> +static int dwmac_if_mdio_busy_wait( const volatile uint32_t *gmii_address )
> +{
> +  rtems_interval timeout = rtems_clock_get_ticks_per_second();
> +  rtems_interval i       = 0;
> +
> +
> +  while ( ( *gmii_address & MACGRP_GMII_ADDRESS_GMII_BUSY ) != 0
> +          && i < timeout ) {
> +    rtems_task_wake_after( 1 );
> +    ++i;
> +  }
> +
> +  return i < timeout ? 0 : EBUSY;
> +}
> +
> +static int dwmac_if_mdio_read(
> +  int       phy,
> +  void     *arg,
> +  unsigned  phy_reg,
> +  uint32_t *val )
> +{
> +  int                   eno         = 0;
> +  dwmac_common_context *self        = (dwmac_common_context *) arg;
> +  volatile uint32_t    *mii_address = &self->macgrp->gmii_address;
> +  volatile uint32_t    *mii_data    = &self->macgrp->gmii_data;
> +  uint32_t              reg_value   = 0;
> +
> +
> +  if ( phy == -1 ) {
> +    reg_value = MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_SET(
> +      reg_value,
> +      self->CFG->MDIO_BUS_ADDR
> +      );
> +  } else {
> +    reg_value = MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_SET(
> +      reg_value,
> +      phy
> +      );
> +  }
> +
> +  reg_value = MACGRP_GMII_ADDRESS_GMII_REGISTER_SET(
> +    reg_value,
> +    phy_reg
> +    );
> +  reg_value &= ~MACGRP_GMII_ADDRESS_GMII_WRITE;
> +
> +  /* For the 7111 GMAC, we must set BUSY bit  in the MII address register while
> +   * accessing the PHY registers.
> +   * Fortunately, it seems this has no drawback for the 7109 MAC. */
> +  reg_value |= MACGRP_GMII_ADDRESS_GMII_BUSY;
> +  reg_value  = MACGRP_GMII_ADDRESS_CSR_CLOCK_RANGE_SET(
> +    reg_value,
> +    self->csr_clock
> +    );
> +
> +  eno = dwmac_if_mdio_busy_wait( mii_address );
> +
> +  if ( eno == 0 ) {
> +    *mii_address = reg_value;
> +
> +    if ( dwmac_if_mdio_busy_wait( mii_address ) ) {
> +      eno = EBUSY;
> +    } else {
> +      /* Read the value from the MII data register */
> +      *val = MACGRP_GMII_DATA_GMII_DATA_GET( *mii_data );
> +    }
> +  }
> +
> +  return eno;
> +}
> +
> +static int dwmac_if_mdio_write(
> +  int      phy,
> +  void    *arg,
> +  unsigned phy_reg,
> +  uint32_t val )
> +{
> +  int                   eno         = 0;
> +  dwmac_common_context *self        = (dwmac_common_context *) arg;
> +  volatile uint32_t    *mii_address = &self->macgrp->gmii_address;
> +  volatile uint32_t    *mii_data    = &self->macgrp->gmii_data;
> +  uint32_t              reg_value   = *mii_address;
> +
> +
> +  if ( phy == -1 ) {
> +    reg_value = MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_SET(
> +      reg_value,
> +      self->CFG->MDIO_BUS_ADDR
> +      );
> +  } else {
> +    reg_value = MACGRP_GMII_ADDRESS_PHYSICAL_LAYER_ADDRESS_SET(
> +      reg_value,
> +      phy
> +      );
> +  }
> +
> +  reg_value = MACGRP_GMII_ADDRESS_GMII_REGISTER_SET(
> +    reg_value,
> +    phy_reg
> +    );
> +  reg_value |= MACGRP_GMII_ADDRESS_GMII_WRITE;
> +  reg_value |= MACGRP_GMII_ADDRESS_GMII_BUSY;
> +  reg_value  = MACGRP_GMII_ADDRESS_CSR_CLOCK_RANGE_SET(
> +    reg_value,
> +    self->csr_clock
> +    );
> +
> +  /* Wait until any existing MII operation is complete */
> +  eno = dwmac_if_mdio_busy_wait( mii_address );
> +
> +  if ( eno == 0 ) {
> +    /* Set the MII address register to write */
> +    *mii_data    = val;
> +    *mii_address = reg_value;
> +
> +    /* Wait until any existing MII operation is complete */
> +    eno = dwmac_if_mdio_busy_wait( mii_address );
> +  }
> +
> +  return eno;
> +}
> +
> +static int dwmac_get_phy_info(
> +  dwmac_common_context *self,
> +  const uint8_t         mdio_bus_addr,
> +  uint32_t             *oui,
> +  uint8_t              *model,
> +  uint8_t              *revision )
> +{
> +  int      eno = 0;
> +  uint32_t read;
> +
> +
> +  eno = dwmac_if_mdio_read(
> +    mdio_bus_addr,
> +    self,
> +    2,
> +    &read );
> +
> +  if ( eno == 0 ) {
> +    *oui = 0 | ( read << 6 );
> +    eno  = dwmac_if_mdio_read(
> +      mdio_bus_addr,
> +      self,
> +      3,
> +      &read );
> +
> +    if ( eno == 0 ) {
> +      *oui     |= ( read & 0xFC00 ) >> 10;
> +      *model    = (uint8_t) ( ( read & 0x03F0 ) >> 4 );
> +      *revision = read & 0x000F;
> +    }
> +  }
> +
> +  return eno;
> +}
> +
> +static inline void dwmac_enable_irq_rx( dwmac_common_context *self )
> +{
> +  dwmac_core_enable_dma_irq_rx( self );
> +}
> +
> +static inline void dwmac_enable_irq_tx( dwmac_common_context *self )
> +{
> +  dwmac_core_enable_dma_irq_tx( self );
> +}
> +
> +static inline void dwmac_disable_irq_rx( dwmac_common_context *self )
> +{
> +  dwmac_core_disable_dma_irq_rx( self );
> +}
> +
> +static inline void dwmac_diable_irq_tx( dwmac_common_context *self )
> +{
> +  dwmac_core_disable_dma_irq_tx( self );
> +}
> +
> +static void dwmac_control_request_complete( const dwmac_common_context *self )
> +{
> +  rtems_status_code sc = rtems_event_transient_send( self->task_id_control );
> +
> +
> +  assert( sc == RTEMS_SUCCESSFUL );
> +}
> +
> +static int dwmac_control_request(
> +  dwmac_common_context *self,
> +  rtems_id              task,
> +  rtems_event_set       event )
> +{
> +  int               eno        = 0;
> +  rtems_status_code sc         = RTEMS_SUCCESSFUL;
> +  uint32_t          nest_count = 0;
> +
> +
> +  self->task_id_control = rtems_task_self();
> +
> +  sc                    = rtems_bsdnet_event_send( task, event );
> +
> +  eno                   = rtems_status_code_to_errno( sc );
> +
> +  if ( eno == 0 ) {
> +    nest_count = rtems_bsdnet_semaphore_release_recursive();
> +    sc         = rtems_event_transient_receive( RTEMS_WAIT, RTEMS_NO_TIMEOUT );
> +    eno        = rtems_status_code_to_errno( sc );
> +  }
> +
> +  if ( eno == 0 ) {
> +    rtems_bsdnet_semaphore_obtain_recursive( nest_count );
> +    self->task_id_control = 0;
> +  }
> +
> +  return eno;
> +}
> +
> +static bool dwmac_if_media_status(
> +  dwmac_common_context *self,
> +  int                  *media,
> +  uint8_t               phy_address )
> +{
> +  struct ifnet *ifp = &self->arpcom.ac_if;
> +
> +
> +  *media = (int) IFM_MAKEWORD( 0, 0, 0, phy_address );
> +
> +  return ( *ifp->if_ioctl )( ifp, SIOCGIFMEDIA, (caddr_t) media ) == 0;
> +}
> +
> +#define DWMAC_PRINT_COUNTER( fmt, counter, args ... ) \
> +  if ( counter != 0 ) { \
> +    printf( fmt, counter, ## args ); \
> +  }
> +
> +/* Print statistics. Get called via ioctl. */
> +static int dwmac_if_interface_stats( void *arg )
> +{
> +  int                   eno      = 0;
> +  dwmac_common_context *self     = arg;
> +  volatile macgrp      *macgrp   = self->macgrp;
> +  int                   media    = 0;
> +  bool                  media_ok = dwmac_if_media_status(
> +    self, &media, self->CFG->MDIO_BUS_ADDR );
> +  uint32_t              oui;
> +  uint8_t               model;
> +  uint8_t               revision;
> +  uint16_t              giant_frame_size = 1518;
> +
> +
> +  if ( ( MACGRP_MAC_CONFIGURATION_JE & macgrp->mac_configuration ) != 0 ) {
> +    /* Jumbo Frames are enabled */
> +    giant_frame_size = 9018;
> +  }
> +
> +  if ( media_ok ) {
> +    rtems_ifmedia2str( media, NULL, 0 );
> +    printf( "\n" );
> +    eno = dwmac_get_phy_info(
> +      self,
> +      self->CFG->MDIO_BUS_ADDR,
> +      &oui,
> +      &model,
> +      &revision );
> +
> +    if ( eno == 0 ) {
> +      printf( "PHY 0x%02x: OUI = 0x%04" PRIX32 ", Model = 0x%02" PRIX8 ", Rev = "
> +              "0x%02" PRIX8 "\n",
> +              self->CFG->MDIO_BUS_ADDR,
> +              oui,
> +              model,
> +              revision );
> +      printf( "PHY status counters:\n" );
> +      DWMAC_PRINT_COUNTER(
> +        "%" PRIu32 " link down\n",
> +        self->stats.phy_status_counts.link_down
> +        );
> +      DWMAC_PRINT_COUNTER(
> +        "%" PRIu32 " link up\n",
> +        self->stats.phy_status_counts.link_up
> +        );
> +    }
> +  } else {
> +    printf( "PHY %d communication error\n", self->CFG->MDIO_BUS_ADDR );
> +  }
> +
> +  printf( "\nHardware counters:\n" );
> +
> +  if ( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_MMCSEL ) != 0 ) {
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes transmitted, exclusive of preamble and retried bytes, "
> +      "in good and bad frames\n",
> +      macgrp->txoctetcount_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted, exclusive of retried "
> +      "frames\n",
> +      macgrp->txframecount_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good broadcast frames transmitted\n",
> +      macgrp->txbroadcastframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good multicast frames transmitted\n",
> +      macgrp->txmulticastframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length 64 bytes, "
> +      "exclusive of preamble and retried frames\n",
> +      macgrp->tx64octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length between 65 and "
> +      "127 (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->tx65to127octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length between 128 and "
> +      "255 (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->tx128to255octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length between 256 and "
> +      "511 (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->tx256to511octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length between 512 and "
> +      "1,023 (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->tx512to1023octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames transmitted with length between 1,024 and"
> +      " maxsize (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->tx1024tomaxoctets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad unicast frames transmitted\n",
> +      macgrp->txunicastframes_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad multicast frames transmitted\n",
> +      macgrp->txmulticastframes_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad broadcast frames transmitted\n",
> +      macgrp->txbroadcastframes_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames aborted due to frame underflow error\n",
> +      macgrp->txunderflowerror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " successfully transmitted frames after a single collision in "
> +      "Half-duplex mode\n",
> +      macgrp->txsinglecol_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " successfully transmitted frames after more than a single"
> +      " collision in Half-duplex mode\n",
> +      macgrp->txmulticol_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " successfully transmitted frames after a deferral in "
> +      "Halfduplex mode\n",
> +      macgrp->txdeferred
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames aborted due to late collision error\n",
> +      macgrp->txlatecol
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames aborted due to excessive (16) collision errors\n",
> +      macgrp->txexesscol
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames aborted due to carrier sense error (no carrier or loss"
> +      " of carrier)\n",
> +      macgrp->txcarriererr
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes transmitted, exclusive of preamble, in good frames "
> +      "only\n",
> +      macgrp->txoctetcnt
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good frames transmitted\n",
> +      macgrp->txframecount_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames aborted due to excessive deferral error (deferred for"
> +      " more than two max-sized frame times)\n",
> +      macgrp->txexcessdef
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good PAUSE frames transmitted\n",
> +      macgrp->txpauseframes
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good VLAN frames transmitted, exclusive of retried frames\n",
> +      macgrp->txvlanframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received\n",
> +      macgrp->txoversize_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received\n",
> +      macgrp->rxframecount_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received, exclusive of preamble, in good and bad "
> +      "frames\n",
> +      macgrp->rxoctetcount_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received, exclusive of preamble, only in good frames\n",
> +      macgrp->rxoctetcount_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good broadcast frames received\n",
> +      macgrp->rxbroadcastframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good multicast frames received\n",
> +      macgrp->rxmulticastframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with CRC error\n",
> +      macgrp->rxcrcerror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with alignment (dribble) error. Valid only"
> +      " in 10/100 mode\n",
> +      macgrp->rxalignmenterror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with runt (<64 bytes and CRC error) error\n",
> +      macgrp->rxrunterror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " giant frames received with length (including CRC) greater "
> +      "than %" PRIu16 " bytes (%" PRIu16 " bytes for VLAN tagged) and with CRC"
> +      " error\n",
> +      macgrp->rxjabbererror, giant_frame_size, giant_frame_size + 4
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with length less than 64 bytes, without any"
> +      " errors\n",
> +      macgrp->rxundersize_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with length greater than the maxsize (1,518"
> +      " or 1,522 for VLAN tagged frames), without errors\n",
> +      macgrp->rxoversize_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length 64 bytes, exclusive"
> +      " of preamble\n",
> +      macgrp->rx64octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length between 65 and 127"
> +      " (inclusive) bytes, exclusive of preamble\n",
> +      macgrp->rx65to127octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length between 128 and 255"
> +      " (inclusive) bytes, exclusive of preamble\n",
> +      macgrp->rx128to255octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length between 256 and 511"
> +      " (inclusive) bytes, exclusive of preamble\n",
> +      macgrp->rx256to511octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length between 512 and "
> +      "1,023 (inclusive) bytes, exclusive of preamble\n",
> +      macgrp->rx512to1023octets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad frames received with length between 1,024 and"
> +      " maxsize (inclusive) bytes, exclusive of preamble and retried frames\n",
> +      macgrp->rx1024tomaxoctets_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good unicast frames received\n",
> +      macgrp->rxunicastframes_g
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with length error (length type field not "
> +      "equal to frame size), for all frames with valid length field\n",
> +      macgrp->rxlengtherror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with length field not equal to the valid "
> +      "frame size (greater than 1,500 but less than 1,536)\n",
> +      macgrp->rxoutofrangetype
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and valid PAUSE frames received\n",
> +      macgrp->rxpauseframes
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " missed received frames due to FIFO overflow\n",
> +      macgrp->rxfifooverflow
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good and bad VLAN frames received\n",
> +      macgrp->rxvlanframes_gb
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with error due to watchdog timeout error "
> +      "(frames with a data load larger than 2,048 bytes)\n",
> +      macgrp->rxwatchdogerror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " frames received with Receive error or Frame Extension error"
> +      " on the GMII or MII interface\n",
> +      macgrp->rxrcverror
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " received good control frames\n",
> +      macgrp->rxctrlframes_g
> +      );
> +
> +    printf( "\n" );
> +
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IPv4 datagrams received with the TCP, UDP, or ICMP "
> +      "payload\n",
> +      macgrp->rxipv4_gd_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " IPv4 datagrams received with header (checksum, length, or "
> +      "version mismatch) errors\n",
> +      macgrp->rxipv4_hdrerr_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " IPv4 datagram frames received that did not have a TCP, UDP, "
> +      "or ICMP payload processed by the Checksum engine\n",
> +      macgrp->rxipv4_nopay_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IPv4 datagrams with fragmentation\n",
> +      macgrp->rxipv4_frag_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IPv4 datagrams received that had a UDP payload with "
> +      "checksum disabled\n",
> +      macgrp->rxipv4_udsbl_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IPv6 datagrams received with TCP, UDP, or ICMP "
> +      "payloads\n",
> +      macgrp->rxipv6_gd_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " IPv6 datagrams received with header errors (length or "
> +      "version mismatch)\n",
> +      macgrp->rxipv6_hdrerr_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " IPv6 datagram frames received that did not have a TCP, UDP,"
> +      " or ICMP payload. This includes all IPv6 datagrams with fragmentation"
> +      " or security extension headers\n",
> +      macgrp->rxipv6_nopay_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams with a good UDP payload. This counter is "
> +      "not updated when the counter is incremented\n",
> +      macgrp->rxudp_gd_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams whose UDP payload has a checksum error\n",
> +      macgrp->rxudp_err_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams with a good TCP payload\n",
> +      macgrp->rxtcp_gd_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams whose TCP payload has a checksum error\n",
> +      macgrp->rxtcp_err_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams with a good ICMP payload\n",
> +      macgrp->rxicmp_gd_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " good IP datagrams whose ICMP payload has a checksum error\n",
> +      macgrp->rxicmp_err_frms
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in good IPv4 datagrams encapsulating TCP, UDP,"
> +      " or ICMP data\n",
> +      macgrp->rxipv4_gd_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in IPv4 datagrams with header errors (checksum,"
> +      " length, version mismatch). The value in the Length field of IPv4 "
> +      "header is used to update this counter\n",
> +      macgrp->rxipv4_hdrerr_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in IPv4 datagrams that did not have a TCP, UDP"
> +      ", or ICMP payload. The value in the IPv4 headers Length field is used"
> +      " to update this counter\n",
> +      macgrp->rxipv4_nopay_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in fragmented IPv4 datagrams. The value in the"
> +      " IPv4 headers Length field is used to update this counter\n",
> +      macgrp->rxipv4_frag_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a UDP segment that had the UDP checksum "
> +      "disabled. This counter does not count IP Header bytes\n",
> +      macgrp->rxipv4_udsbl_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in good IPv6 datagrams encapsulating TCP, UDP "
> +      "or ICMPv6 data\n",
> +      macgrp->rxipv6_gd_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in IPv6 datagrams with header errors (length, "
> +      "version mismatch). The value in the IPv6 headers Length field is used "
> +      "to update this counter\n",
> +      macgrp->rxipv6_hdrerr_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in IPv6 datagrams that did not have a TCP, UDP"
> +      ", or ICMP payload. The value in the IPv6 headers Length field is used "
> +      "to update this counter\n",
> +      macgrp->rxipv6_nopay_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a good UDP segment. This counter does not "
> +      "count IP header bytes\n",
> +      macgrp->rxudp_gd_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a UDP segment that had checksum errors\n",
> +      macgrp->rxudp_err_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a good TCP segment\n",
> +      macgrp->rxtcp_gd_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a TCP segment with checksum errors\n",
> +      macgrp->rxtcperroctets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in a good ICMP segment\n",
> +      macgrp->rxicmp_gd_octets
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " bytes received in an ICMP segment with checksum errors\n",
> +      macgrp->rxicmp_err_octets
> +      );
> +  }
> +
> +  if ( eno == 0 ) {
> +    printf( "\nInterrupt counts:\n" );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " receive interrputs\n",
> +                         self->stats.dma_irq_counts.receive
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " transmit interrupts\n",
> +                         self->stats.dma_irq_counts.transmit
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " tx jabber interrupts\n",
> +                         self->stats.dma_irq_counts.tx_jabber
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " rx overflow interrupts\n",
> +                         self->stats.dma_irq_counts.rx_overflow
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " rx early interrupts\n",
> +                         self->stats.dma_irq_counts.rx_early
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " rx buffer unavailable interrupts\n",
> +                         self->stats.dma_irq_counts.rx_buf_unav
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " rx process stopped interrupts\n",
> +                         self->stats.dma_irq_counts.rx_process_stopped
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " rx watchdog interrupts\n",
> +                         self->stats.dma_irq_counts.rx_watchdog
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " tx early interrupts\n",
> +                         self->stats.dma_irq_counts.tx_early
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " tx buffer unavailable interrupts\n",
> +                         self->stats.dma_irq_counts.tx_buf_unav
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " tx process stopped interrupts\n",
> +                         self->stats.dma_irq_counts.tx_process_stopped
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " tx underflow interrupts\n",
> +                         self->stats.dma_irq_counts.tx_underflow
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " fatal bus error interrupts\n",
> +                         self->stats.dma_irq_counts.fatal_bus_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " unhandled interrupts\n",
> +                         self->stats.dma_irq_counts.unhandled
> +                         );
> +
> +    printf( "\nRX DMA status counts:\n" );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " CRC errors\n",
> +                         self->stats.desc_status_counts_rx.crc_error
> +                         );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " late collision when receing in half duplex mode\n",
> +      self->stats.desc_status_counts_rx.late_collision
> +      );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " giant frame or timestamp or checksum error\n",
> +      self->stats.desc_status_counts_rx.giant_frame
> +      );
> +
> +    if ( self->stats.desc_status_counts_rx.watchdog_timeout != 0
> +         || self->stats.desc_status_counts_rx.receive_error != 0 ) {
> +      printf( "  IP Header or IP Payload:\n" );
> +      DWMAC_PRINT_COUNTER( "%" PRIu32 " receive watchdog timeout\n",
> +                           self->stats.desc_status_counts_rx.watchdog_timeout
> +                           );
> +      DWMAC_PRINT_COUNTER( "%" PRIu32 " receive error\n",
> +                           self->stats.desc_status_counts_rx.receive_error
> +                           );
> +    }
> +
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " buffer overflows in MTL\n",
> +                         self->stats.desc_status_counts_rx.overflow_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " descriptor buffers too small\n",
> +                         self->stats.desc_status_counts_rx.descriptor_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " length errors\n",
> +                         self->stats.desc_status_counts_rx.length_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " dribble bit errors\n",
> +                         self->stats.desc_status_counts_rx.dribble_bit_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " vlan tags\n",
> +                         self->stats.desc_status_counts_rx.vlan_tag
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " ethernet frames\n",
> +                         self->stats.desc_status_counts_rx.ethernet_frames
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " destination address filter failures\n",
> +                         self->stats.desc_status_counts_rx.dest_addr_fail
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " source addresss filter failures\n",
> +                         self->stats.desc_status_counts_rx.source_addr_fail
> +                         );
> +
> +    printf( "\nTX DMA status counts:\n" );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " jabber time-outs\n",
> +                         self->stats.desc_status_counts_tx.jabber
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frame flushes\n",
> +                         self->stats.desc_status_counts_tx.frame_flushed
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " losses of carrier\n",
> +                         self->stats.desc_status_counts_tx.losscarrier
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " no carriers\n",
> +                         self->stats.desc_status_counts_tx.no_carrier
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " excessive collisions\n",
> +                         self->stats.desc_status_counts_tx.excessive_collisions
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " excessive deferrals\n",
> +                         self->stats.desc_status_counts_tx.excessive_deferral
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " underfolw errors\n",
> +                         self->stats.desc_status_counts_tx.underflow
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " IP header error\n",
> +                         self->stats.desc_status_counts_tx.ip_header_error
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " payload error\n",
> +                         self->stats.desc_status_counts_rx.source_addr_fail
> +                         );
> +    DWMAC_PRINT_COUNTER(
> +      "%" PRIu32 " MAC defers before transmission because of the presence of carrier\n",
> +      self->stats.desc_status_counts_tx.deferred
> +      );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " VLAN frames\n",
> +                         self->stats.desc_status_counts_tx.vlan
> +                         );
> +
> +    printf( "\nRX frame counts:\n" );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames with errors\n",
> +                         self->stats.frame_counts_rx.errors
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames dropped\n",
> +                         self->stats.frame_counts_rx.dropped
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames good\n",
> +                         self->stats.frame_counts_rx.frames_good
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " bytes in good frames\n",
> +                         self->stats.frame_counts_rx.bytes_good
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames good or bad\n",
> +                         self->stats.frame_counts_rx.frames
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " DMA suspended\n",
> +                         self->stats.frame_counts_rx.dma_suspended
> +                         );
> +
> +    printf( "\nTX frame counts:\n" );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames received from network stack\n",
> +                         self->stats.frame_counts_tx.frames_from_stack
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " frames tranmitted to DMA\n",
> +                         self->stats.frame_counts_tx.frames_to_dma
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " packets tranmitted to DMA\n",
> +                         self->stats.frame_counts_tx.packets_to_dma
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " bytes tranmitted to DMA\n",
> +                         self->stats.frame_counts_tx.bytes_to_dma
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " packets tranmitted by DMA\n",
> +                         self->stats.frame_counts_tx.packets_tranmitted_by_DMA
> +                         );
> +    DWMAC_PRINT_COUNTER( "%" PRIu32 " packet errors\n",
> +                         self->stats.frame_counts_tx.packet_errors
> +                         );
> +
> +    printf( "\n" );
> +
> +#ifdef RTEMS_DEBUG
> +    {
> +      const dwmac_common_desc_ops *DESC_OPS =
> +        (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +
> +      ( DESC_OPS->print_rx_desc )(
> +        self->dma_rx,
> +        (unsigned int) self->bsd_config->xbuf_count
> +        );
> +
> +      ( DESC_OPS->print_tx_desc )(
> +        self->dma_tx,
> +        (unsigned int) self->bsd_config->xbuf_count
> +        );
> +    }
> +#endif /* RTEMS_DEBUG */
> +  }
> +
> +  return eno;
> +}
> +
> +static void dwmac_prefetch(
> +  dwmac_common_context *self,
> +  volatile void        *ptr )
> +{
> +  if ( ( self )->CFG->ARCH_HAS_PREFETCH ) {
> +    __asm__ __volatile__ (
> +      "pld\t%a0"
> +      :
> +      : "p" ( ptr )
> +      : "cc" );
> +  }
> +}
> +
> +static inline unsigned int dwmac_increment(
> +  const unsigned int value,
> +  const unsigned int cycle )
> +{
> +  if ( value < cycle ) {
> +    return value + 1;
> +  } else {
> +    return 0;
> +  }
> +}
> +
> +/* Receive task
> + * It handles receiving frames */
> +static void dwmac_task_rx( void *arg )
> +{
> +  dwmac_common_context         *self           = arg;
> +  dwmac_common_rx_frame_counts *counts         = &self->stats.frame_counts_rx;
> +  const unsigned int            INDEX_MAX      =
> +    (unsigned int) self->bsd_config->rbuf_count - 1U;
> +  size_t                        frame_len_last = 0;
> +  const dwmac_common_desc_ops  *DESC_OPS       =
> +    (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +  size_t                        segment_size;
> +
> +
> +  while ( true ) {
> +    rtems_event_set   events;
> +    rtems_status_code sc = rtems_bsdnet_event_receive(
> +      DWMAC_COMMON_EVENT_TASK_INIT
> +      | DWMAC_COMMON_EVENT_TASK_STOP
> +      | DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED,
> +      RTEMS_EVENT_ANY | RTEMS_WAIT,
> +      RTEMS_NO_TIMEOUT,
> +      &events
> +      );
> +    assert( sc == RTEMS_SUCCESSFUL );
> +
> +    /* Stop the task */
> +    if ( ( events & DWMAC_COMMON_EVENT_TASK_STOP ) != 0 ) {
> +      dwmac_core_dma_stop_rx( self );
> +      dwmac_disable_irq_rx( self );
> +
> +      /* Release all tx mbufs at the risk of data loss */
> +      ( DESC_OPS->release_rx_bufs )( self );
> +
> +      dwmac_control_request_complete( self );
> +
> +      /* Return to events reception without re-enabling the interrupts
> +       * The task needs a re-initialization to to resume work */
> +      continue;
> +    }
> +
> +    /* Ininitialize / Re-initialize reception handling */
> +    if ( ( events & DWMAC_COMMON_EVENT_TASK_INIT ) != 0 ) {
> +      unsigned int index;
> +      dwmac_core_dma_stop_rx( self );
> +      ( DESC_OPS->release_rx_bufs )( self );
> +
> +      for ( index = 0; index <= INDEX_MAX; ++index ) {
> +        self->mbuf_addr_rx[index] = ( DESC_OPS->alloc_data_buf )( self );
> +        assert( self->mbuf_addr_rx[index] != NULL );
> +        ( DESC_OPS->init_rx_desc )( self, index );
> +      }
> +
> +      self->idx_rx   = 0;
> +      frame_len_last = 0;
> +
> +      /* Clear our interrupt statuses */
> +      dwmac_core_reset_dma_irq_status_rx( self );
> +
> +      dwmac_core_dma_start_rx( self );
> +
> +      dwmac_control_request_complete( self );
> +      events = events
> +               & (rtems_event_set) ( ~DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED );
> +    }
> +
> +    /* Handle the reception of one or more frames */
> +    if ( ( events & DWMAC_COMMON_EVENT_RX_FRAME_RECEIVED ) != 0 ) {
> +      unsigned int idx = self->idx_rx;
> +
> +      /* Only handle frames for which we own the DMA descriptor */
> +      while ( ( DESC_OPS->am_i_rx_owner )( self, idx ) ) {
> +        struct mbuf                 *p_m_new;
> +        dwmac_common_rx_frame_status status;
> +        unsigned int                 idx_next = dwmac_increment(
> +          self->idx_rx, INDEX_MAX );
> +
> +        /* Assign the next index (with wrap around) */
> +        self->idx_rx = idx_next;
> +
> +        /* read the status of the incoming frame */
> +        status = ( DESC_OPS->rx_status )( self, idx );
> +
> +        if ( status == DWMAC_COMMON_RX_FRAME_STATUS_DISCARD
> +             || status == DWMAC_COMMON_RX_FRAME_STATUS_CSUM_NONE ) {
> +          DWMAC_PRINT_DBG(
> +            "rx discarded: %02u\n",
> +            idx
> +            );
> +          ++counts->errors;
> +
> +          /* simply re-initialize the DMA descriptor */
> +          ( DESC_OPS->init_rx_desc )( self, idx );
> +        } else if ( status == DWMAC_COMMON_RX_FRAME_STATUS_LLC_SNAP ) {
> +          DWMAC_PRINT_DBG(
> +            "rx dropped llc snap: %02u\n",
> +            idx
> +            );
> +          ++counts->dropped;
> +
> +          /* simply re-initialize the DMA descriptor */
> +          ( DESC_OPS->init_rx_desc )( self, idx );
> +        } else {
> +          /* Before actually handling the valid frame, make sure we get a new
> +           * mbuf */
> +          p_m_new = ( DESC_OPS->alloc_data_buf )( self );
> +
> +          if ( p_m_new != NULL ) {
> +            bool         is_first_seg;
> +            bool         is_last_seg;
> +            struct mbuf *p_m;
> +            uint32_t     frame_len = ( DESC_OPS->get_rx_frame_len )(
> +              self, idx );
> +
> +            /* frame_len is the cummulated size of all segments of a frame.
> +             * But what we need is the size of the single segment */
> +            is_first_seg = ( DESC_OPS->is_first_rx_segment )( self, idx );
> +            is_last_seg  = ( DESC_OPS->is_last_rx_segment )( self, idx );
> +
> +            if ( is_first_seg ) {
> +              segment_size = frame_len;
> +            } else {
> +              segment_size = frame_len - frame_len_last;
> +            }
> +
> +            frame_len_last          = frame_len;
> +
> +            p_m                     = self->mbuf_addr_rx[idx];
> +            dwmac_prefetch( self, mtod( p_m - ETHER_ALIGN, void * ) );
> +            self->mbuf_addr_rx[idx] = p_m_new;
> +
> +            /* Initialize the DMA descriptor with the new mbuf */
> +            ( DESC_OPS->init_rx_desc )( self, idx );
> +
> +            if ( p_m != NULL ) {
> +              /* Ethernet header */
> +              struct ether_header *eh = mtod( p_m, struct ether_header * );
> +              int                  sz = (int) segment_size;
> +
> +              rtems_cache_invalidate_multiple_data_lines(
> +                eh, segment_size );
> +
> +              /* Discard Ethernet header and CRC */
> +              if ( is_last_seg ) {
> +                sz -= ( ETHER_HDR_LEN + ETHER_CRC_LEN );
> +              } else {
> +                sz -= ETHER_HDR_LEN;
> +              }
> +
> +              /* Update mbuf */
> +              p_m->m_len        = sz;
> +              p_m->m_pkthdr.len = sz;
> +              p_m->m_data       = mtod( p_m, char * ) + ETHER_HDR_LEN;
> +
> +              _ARM_Data_synchronization_barrier();
> +
> +              DWMAC_PRINT_DBG(
> +                "rx: %02u: %u %s%s\n",
> +                idx,
> +                segment_size,
> +                ( is_first_seg ) ? ( "F" ) : ( "" ),
> +                ( is_last_seg ) ? ( "L" ) : ( "" )
> +                );
> +
> +              ether_input( &self->arpcom.ac_if, eh, p_m );
> +
> +              ++counts->frames_good;
> +              counts->bytes_good += (uint32_t) p_m->m_len;
> +            } else {
> +              DWMAC_PRINT_DBG( "rx: %s: Inconsistent Rx descriptor chain\n",
> +                               self->arpcom.ac_if.if_name );
> +              ++counts->dropped;
> +            }
> +          } else {
> +            /* We have to discard the received frame because we did not get a new
> +             * mbuf to replace the frame's mbuf. */
> +            ++counts->dropped;
> +
> +            /* simply re-initialize the DMA descriptor with the existing mbuf */
> +            ( DESC_OPS->init_rx_desc )( self, idx );
> +            DWMAC_PRINT_DBG(
> +              "rx dropped: %02u\n",
> +              idx
> +              );
> +          }
> +        }
> +
> +        if ( ( self->dmagrp->status & DMAGRP_STATUS_RU ) != 0 ) {
> +          /* The receive DMA is suspended and needs to get restarted */
> +          dwmac_core_dma_restart_rx( self );
> +          DWMAC_PRINT_DBG(
> +            "rx DMA restart: %02u\n",
> +            idx
> +            );
> +          ++counts->dma_suspended;
> +        }
> +
> +        idx = idx_next;
> +        ++counts->frames;
> +      }
> +
> +      /* Clear interrupt */
> +      self->dmagrp->status = DMAGRP_STATUS_RI;
> +    }
> +
> +    /* Re-enable the IRQs */
> +    dwmac_enable_irq_rx( self );
> +  }
> +}
> +
> +static struct mbuf *dwmac_next_fragment(
> +  struct ifnet *ifp,
> +  struct mbuf  *m,
> +  bool         *is_first,
> +  bool         *is_last,
> +  size_t       *size ) {
> +  struct mbuf *n  = NULL;
> +  int          sz = 0;
> +
> +
> +  while ( true ) {
> +    if ( m == NULL ) {
> +      /* Dequeue first fragment of the next frame */
> +      IF_DEQUEUE( &ifp->if_snd, m );
> +
> +      /* Empty queue? */
> +      if ( m == NULL ) {
> +        return m;
> +      }
> +
> +      /* The sum of all fragments lengths must fit into one
> +       * ethernet transfer unit */
> +      assert( ETHER_MAX_LEN >= m->m_pkthdr.len );
> +      *is_first = true;
> +    }
> +
> +    /* Get fragment size */
> +    sz = m->m_len;
> +
> +    if ( sz > 0 ) {
> +      /* Now we have a not empty fragment */
> +      break;
> +    } else {
> +      /* Discard empty fragments */
> +      m = m_free( m );
> +    }
> +  }
> +
> +  /* Set fragment size */
> +  *size = (size_t) sz;
> +
> +  /* Discard empty successive fragments */
> +  n = m->m_next;
> +
> +  while ( n != NULL && n->m_len <= 0 ) {
> +    n = m_free( n );
> +  }
> +
> +  m->m_next = n;
> +
> +  /* Is our fragment the last in the frame? */
> +  if ( n == NULL ) {
> +    *is_last = true;
> +  } else {
> +    *is_last = false;
> +  }
> +
> +  return m;
> +}
> +
> +static int dwmac_update_autonegotiation_params( dwmac_common_context *self )
> +{
> +  int      eno      = 0;
> +  uint32_t value    = self->macgrp->mac_configuration;
> +  int      media    = 0;
> +  bool     media_ok = dwmac_if_media_status(
> +    self, &media, self->CFG->MDIO_BUS_ADDR );
> +
> +
> +  if ( media_ok ) {
> +    /* only ethernet supported, so far */
> +    if ( IFM_ETHER == IFM_TYPE( media ) ) {
> +      if ( IFM_NONE != IFM_SUBTYPE( media ) ) {
> +        if ( IFM_FDX & media ) {
> +          /* Enable duplex mode */
> +          value |= MACGRP_MAC_CONFIGURATION_DM;
> +        } else {
> +          /* Disable duplex mode */
> +          value &= ~MACGRP_MAC_CONFIGURATION_DM;
> +        }
> +
> +        switch ( IFM_SUBTYPE( media ) ) {
> +          case IFM_10_T:
> +
> +            /* Set RMII/RGMII speed to 10Mbps */
> +            value &= ~MACGRP_MAC_CONFIGURATION_FES;
> +
> +            /* MII 10/100 Mbps */
> +            value |= MACGRP_MAC_CONFIGURATION_PS;
> +            break;
> +          case IFM_100_TX:
> +
> +            /* Set RMII/RGMII speed to 100Mbps */
> +            value |= MACGRP_MAC_CONFIGURATION_FES;
> +
> +            /* MII 10/100 Mbps */
> +            value |= MACGRP_MAC_CONFIGURATION_PS;
> +            break;
> +          case IFM_1000_T:
> +
> +            /* RMII/RGMII speed irrelevant for 1000baseT */
> +            value &= ~MACGRP_MAC_CONFIGURATION_FES;
> +
> +            /* GMII 1000 Mbps */
> +            value &= ~MACGRP_MAC_CONFIGURATION_PS;
> +            break;
> +          default:
> +            eno = ENOTSUP;
> +            break;
> +        }
> +      } else {
> +        eno = ENOTSUP;
> +      }
> +    } else {
> +      eno = ENOTSUP;
> +    }
> +  } else {
> +    eno = ENOTSUP;
> +  }
> +
> +  if ( eno == 0 ) {
> +    self->macgrp->mac_configuration = value;
> +  }
> +
> +  return eno;
> +}
> +
> +/* Transmit task
> + * It handles transmitting frames */
> +static void dwmac_task_tx( void *arg )
> +{
> +  dwmac_common_context        *self               = arg;
> +  unsigned int                 idx_transmit       = 0;
> +  unsigned int                 idx_transmit_first = 0;
> +  unsigned int                 idx_transmitted    = 0;
> +  unsigned int                 idx_release        = 0;
> +  struct mbuf                 *p_m                = NULL;
> +  bool                         is_first           = false;
> +  bool                         is_last            = false;
> +  size_t                       size               = 0;
> +  const unsigned int           INDEX_MAX          =
> +    (unsigned int) self->bsd_config->xbuf_count - 1U;
> +  const dwmac_common_dma_ops  *DMA_OPS            =
> +    (const dwmac_common_dma_ops *) self->CFG->MAC_OPS->dma;
> +  const dwmac_common_desc_ops *DESC_OPS           =
> +    (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +  const dwmac_callback_cfg    *CALLBACK           = &self->CFG->CALLBACK;
> +
> +
> +  while ( true ) {
> +    rtems_event_set   events = 0;
> +    rtems_status_code sc     = rtems_bsdnet_event_receive(
> +      DWMAC_COMMON_EVENT_TASK_INIT
> +      | DWMAC_COMMON_EVENT_TASK_STOP
> +      | DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME
> +      | DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED
> +      | DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD
> +      | DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE,
> +      RTEMS_EVENT_ANY | RTEMS_WAIT,
> +      RTEMS_NO_TIMEOUT,
> +      &events
> +      );
> +    assert( sc == RTEMS_SUCCESSFUL );
> +
> +    /* Handle a status change of the ethernet PHY */
> +    if ( ( events & DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE ) != 0 ) {
> +      dwmac_common_phy_status_counts *counts     =
> +        &self->stats.phy_status_counts;
> +      dwmac_phy_event                 phy_events = 0;
> +      int                             eno;
> +
> +      /* Get tripped PHY events */
> +      eno = CALLBACK->phy_events_get(
> +        self->arg,
> +        &phy_events
> +        );
> +
> +      if ( eno == 0 ) {
> +        /* Clear the PHY events */
> +        eno = CALLBACK->phy_event_clear( self->arg );
> +      }
> +
> +      if ( eno == 0 ) {
> +        if ( ( phy_events & PHY_EVENT_LINK_DOWN ) != 0 ) {
> +          ++counts->link_down;
> +        }
> +
> +        if ( ( phy_events & PHY_EVENT_LINK_UP ) != 0 ) {
> +          ++counts->link_up;
> +
> +          /* A link up events means that we have a new connection.
> +           * Thus the autonegotiation paremeters must get updated */
> +          (void) dwmac_update_autonegotiation_params( self );
> +        }
> +      }
> +
> +      assert( eno == 0 );
> +    }
> +
> +    /* Stop the task */
> +    if ( ( events & DWMAC_COMMON_EVENT_TASK_STOP ) != 0 ) {
> +      dwmac_core_dma_stop_tx( self );
> +      dwmac_diable_irq_tx( self );
> +
> +      /* Release all tx mbufs at the risk of data loss */
> +      ( DESC_OPS->release_tx_bufs )( self );
> +
> +      dwmac_control_request_complete( self );
> +
> +      /* Return to events reception without re-enabling the interrupts
> +       * The task needs a re-initialization to to resume work */
> +      continue;
> +    }
> +
> +    /* Ininitialize / Re-initialize transmission handling */
> +    if ( ( events & DWMAC_COMMON_EVENT_TASK_INIT ) != 0 ) {
> +      (void) dwmac_update_autonegotiation_params( self );
> +      dwmac_core_dma_stop_tx( self );
> +      ( DESC_OPS->release_tx_bufs )( self );
> +      idx_transmit       = 0;
> +      idx_transmit_first = 0;
> +      idx_transmitted    = 0;
> +      idx_release        = 0;
> +      p_m                = NULL;
> +      is_first           = false;
> +      is_last            = false;
> +      size               = 0;
> +      ( DESC_OPS->init_tx_desc )( self );
> +      dwmac_core_dma_start_tx( self );
> +      dwmac_core_dma_restart_tx( self );
> +
> +      /* Clear our interrupt statuses */
> +      dwmac_core_reset_dma_irq_status_tx( self );
> +
> +      dwmac_control_request_complete( self );
> +    }
> +
> +    /* Try to bump up the dma threshold due to a failure */
> +    if ( ( events & DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD ) != 0 ) {
> +      if ( self->dma_threshold_control
> +           != DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD
> +           && self->dma_threshold_control <= 256 ) {
> +        self->dma_threshold_control += 64;
> +        ( DMA_OPS->dma_mode )(
> +          self,
> +          self->dma_threshold_control,
> +          DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD
> +          );
> +      }
> +    }
> +
> +    /* Handle one or more transmitted frames */
> +    if ( ( events & DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED ) != 0 ) {
> +      dwmac_common_tx_frame_counts *counts = &self->stats.frame_counts_tx;
> +
> +      /* Next index to be transmitted */
> +      unsigned int idx_transmitted_next = dwmac_increment(
> +        idx_transmitted, INDEX_MAX );
> +
> +      /* Free consumed fragments */
> +      while ( idx_release != idx_transmitted_next
> +              && ( DESC_OPS->am_i_tx_owner )( self, idx_release ) ) {
> +        /* Status handling per packet */
> +        if ( ( DESC_OPS->get_tx_ls )( self, idx_release ) ) {
> +          int status = ( DESC_OPS->tx_status )(
> +            self, idx_release
> +            );
> +
> +          if ( status == 0 ) {
> +            ++counts->packets_tranmitted_by_DMA;
> +          } else {
> +            ++counts->packet_errors;
> +          }
> +        }
> +
> +        DWMAC_PRINT_DBG(
> +          "tx: release %u\n",
> +          idx_release
> +          );
> +
> +        /* Release the DMA descriptor */
> +        ( DESC_OPS->release_tx_desc )( self, idx_release );
> +
> +        /* Release mbuf */
> +        m_free( self->mbuf_addr_tx[idx_release] );
> +        self->mbuf_addr_tx[idx_release] = NULL;
> +
> +        /* Next release index */
> +        idx_release = dwmac_increment(
> +          idx_release, INDEX_MAX );
> +      }
> +
> +      /* Clear transmit interrupt status */
> +      self->dmagrp->status = DMAGRP_STATUS_TI;
> +
> +      if ( ( self->arpcom.ac_if.if_flags & IFF_OACTIVE ) != 0 ) {
> +        /* The last tranmission has been incomplete
> +         * (for example due to lack of DMA descriptors).
> +         * Continue it now! */
> +        events |= DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME;
> +      }
> +    }
> +
> +    /* There are one or more frames to be transmitted. */
> +    if ( ( events & DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME ) != 0 ) {
> +      dwmac_common_tx_frame_counts *counts = &self->stats.frame_counts_tx;
> +
> +      if ( p_m != NULL ) {
> +        /* This frame will get re-counted */
> +        --counts->frames_from_stack;
> +      }
> +
> +      while ( true ) {
> +        unsigned int idx = dwmac_increment(
> +          idx_transmit, INDEX_MAX );
> +
> +        p_m = dwmac_next_fragment(
> +          &self->arpcom.ac_if,
> +          p_m,
> +          &is_first,
> +          &is_last,
> +          &size
> +          );
> +
> +        /* New fragment? */
> +        if ( p_m != NULL ) {
> +          ++counts->frames_from_stack;
> +
> +          /* Queue full? */
> +          if ( idx == idx_release ) {
> +            DWMAC_PRINT_DBG( "tx: full queue: 0x%08x\n", p_m );
> +
> +            /* The queue is full, wait for transmitted interrupt */
> +            break;
> +          }
> +
> +          /* Set the transfer data */
> +          rtems_cache_flush_multiple_data_lines(
> +            mtod( p_m, const void * ),
> +            size
> +            );
> +
> +          ( DESC_OPS->prepare_tx_desc )(
> +            self,
> +            idx_transmit,
> +            is_first,
> +            size,
> +            mtod( p_m, const void * )
> +            );
> +          self->mbuf_addr_tx[idx_transmit] = p_m;
> +
> +          ++counts->frames_to_dma;
> +          counts->bytes_to_dma += size;
> +          DWMAC_PRINT_DBG(
> +            "tx: %02" PRIu32 ": %u %s%s\n",
> +            idx_transmit, size,
> +            ( is_first != false ) ? ( "F" ) : ( "" ),
> +            ( is_last != false ) ? ( "L" ) : ( "" )
> +
> +            );
> +
> +          if ( is_first ) {
> +            idx_transmit_first = idx_transmit;
> +            is_first           = false;
> +          } else {
> +            /* To avoid race condition */
> +            ( DESC_OPS->release_tx_ownership )( self, idx_transmit );
> +          }
> +
> +          if ( is_last ) {
> +            /* Interrupt on completition only for the latest fragment */
> +            ( DESC_OPS->close_tx_desc )( self, idx_transmit );
> +
> +            /* To avoid race condition */
> +            ( DESC_OPS->release_tx_ownership )( self, idx_transmit_first );
> +            idx_transmitted = idx_transmit;
> +
> +            if ( ( self->dmagrp->status & DMAGRP_STATUS_TU ) != 0 ) {
> +              /* Re-enable the tranmit DMA */
> +              dwmac_core_dma_restart_tx( self );
> +              DWMAC_PRINT_DBG(
> +                "tx DMA restart: %02u\n",
> +                idx_transmit_first
> +                );
> +            }
> +          }
> +
> +          /* Next transmit index */
> +          idx_transmit = idx;
> +
> +          if ( is_last ) {
> +            ++counts->packets_to_dma;
> +          }
> +
> +          /* Next fragment of the frame */
> +          p_m = p_m->m_next;
> +        } else {
> +          /* Nothing to transmit */
> +          break;
> +        }
> +      }
> +
> +      /* No more packets and fragments? */
> +      if ( p_m == NULL ) {
> +        /* Interface is now inactive */
> +        self->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
> +      } else {
> +        /* There are more packets pending to be sent,
> +         * but we have run out of DMA descriptors.
> +         * We will continue sending once descriptors
> +         * have been freed due to a transmitted interupt */
> +        DWMAC_PRINT_DBG( "tx: transmission incomplete\n" );
> +      }
> +
> +      /* TODO: Add handling */
> +    }
> +
> +    DWMAC_PRINT_DBG( "tx: enable transmit interrupts\n" );
> +
> +    /* Re-enable transmit interrupts */
> +    dwmac_enable_irq_tx( self );
> +  }
> +}
> +
> +/* Major driver initialization method. Gets called
> + * by the network stack automatically */
> +static void dwmac_if_interface_init( void *arg )
> +{
> +  (void) arg;
> +}
> +
> +static void dwmac_if_set_promiscous_mode(
> +  dwmac_common_context *self,
> +  const bool            enabled )
> +{
> +  if ( enabled ) {
> +    /* Enable promiscuos mode */
> +    self->macgrp->mac_frame_filter |= MACGRP_MAC_FRAME_FILTER_PR;
> +  } else {
> +    /* Hash filter or perfect match */
> +    self->macgrp->mac_frame_filter &= ~MACGRP_MAC_FRAME_FILTER_PR;
> +    self->macgrp->mac_frame_filter &= ~MACGRP_MAC_FRAME_FILTER_HUC;
> +    self->macgrp->mac_frame_filter |= MACGRP_MAC_FRAME_FILTER_HPF;
> +  }
> +}
> +
> +static int dwmac_create_dma_desc_rings( dwmac_common_context *self )
> +{
> +  int                          eno      = 0;
> +  const dwmac_common_desc_ops *DESC_OPS =
> +    (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +
> +
> +  /* create and initialize the Rx/Tx descriptors */
> +  eno = ( DESC_OPS->create_rx_desc )( self );
> +
> +  if ( eno == 0 ) {
> +    eno = ( DESC_OPS->create_tx_desc )( self );
> +  }
> +
> +  return eno;
> +}
> +
> +static int dwmac_destroy_dma_desc_rings( dwmac_common_context *self )
> +{
> +  int                          eno      = 0;
> +  const dwmac_common_desc_ops *DESC_OPS =
> +    (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +
> +
> +  /* Free the Rx/Tx descriptors and the data buffers */
> +  eno = ( DESC_OPS->destroy_rx_desc )( self );
> +
> +  if ( eno == 0 ) {
> +    eno = ( DESC_OPS->destroy_tx_desc )( self );
> +  }
> +
> +  return eno;
> +}
> +
> +static int dwmac_init_dma_engine( dwmac_common_context *self )
> +{
> +  uint32_t                     pbl                  =
> +    DWMAC_DMA_BUS_MODE_PBL_DEFAULT;
> +  uint32_t                     fixed_burst          =
> +    DWMAC_DMA_BUS_MODE_FB_DEFAULT;
> +  uint32_t                     mixed_burst          =
> +    DWMAC_DMA_BUS_MODE_MIXED_BURSTS_DEFAULT;
> +  uint32_t                     burst_len_4_support  =
> +    DWMAC_DMA_AXI_BURST_LENGTH_4_DEFAULT;
> +  uint32_t                     burst_len_8_support  =
> +    DWMAC_DMA_AXI_BURST_LENGTH_8_DEFAULT;
> +  uint32_t                     burst_len_16_support =
> +    DWMAC_DMA_AXI_BURST_LENGTH_16_DEFAULT;
> +  uint32_t                     burst_boundary       =
> +    DWMAC_DMA_AXI_BURST_BOUNDARY_DEFAULT;
> +  const dwmac_common_dma_ops  *DMA_OPS              =
> +    (const dwmac_common_dma_ops *) self->CFG->MAC_OPS->dma;
> +  const dwmac_common_desc_ops *DESC_OPS             =
> +    (const dwmac_common_desc_ops *) self->CFG->DESC_OPS->ops;
> +
> +
> +  /* The DMA configuration is optional */
> +  if ( self->CFG->DMA_CFG != NULL ) {
> +    const dwmac_dma_cfg *DMA_CFG = self->CFG->DMA_CFG;
> +    pbl                  = DMA_CFG->bus_mode_burst_length;
> +    fixed_burst          = DMA_CFG->bus_mode_burst_mode;
> +    mixed_burst          = DMA_CFG->bus_mode_burst_mixed;
> +    burst_len_4_support  = DMA_CFG->axi_burst_length_4_support;
> +    burst_len_8_support  = DMA_CFG->axi_burst_length_8_support;
> +    burst_len_16_support = DMA_CFG->axi_burst_length_16_support;
> +    burst_boundary       = DMA_CFG->axi_burst_boundary;
> +  }
> +
> +  return ( DMA_OPS->init )(
> +    self,
> +    pbl,
> +    fixed_burst,
> +    mixed_burst,
> +    ( DESC_OPS->use_enhanced_descs )( self ),
> +    burst_len_4_support,
> +    burst_len_8_support,
> +    burst_len_16_support,
> +    burst_boundary,
> +    &self->dma_tx[0],
> +    &self->dma_rx[0]
> +    );
> +}
> +
> +static void dwmac_dma_operation_mode( dwmac_common_context *self )
> +{
> +  const dwmac_common_dma_ops *DMA_OPS =
> +    (const dwmac_common_dma_ops *) self->CFG->MAC_OPS->dma;
> +
> +
> +  if ( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_TXOESEL ) != 0 ) {
> +    ( DMA_OPS->dma_mode )(
> +      self,
> +      DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD,
> +      DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD
> +      );
> +    self->dma_threshold_control = DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD;
> +  } else {
> +    ( DMA_OPS->dma_mode )(
> +      self,
> +      self->dma_threshold_control,
> +      DWMAC_COMMON_DMA_MODE_STORE_AND_FORWARD
> +      );
> +  }
> +}
> +
> +static void dwmac_mmc_setup( dwmac_common_context *self )
> +{
> +  /* Mask MMC irq, counters are managed in HW and registers
> +   * are not cleared on each READ eventually. */
> +
> +  /* No MAC Management Counters available */
> +  assert( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_MMCSEL ) != 0 );
> +
> +  if ( ( self->dmagrp->hw_feature & DMAGRP_HW_FEATURE_MMCSEL ) != 0 ) {
> +    self->macgrp->mmc_control = MACGRP_MMC_CONTROL_CNTRST;
> +  }
> +}
> +
> +static int dwmac_if_up_or_down(
> +  dwmac_common_context *self,
> +  const bool            up )
> +{
> +  int                          eno      = 0;
> +  rtems_status_code            sc       = RTEMS_SUCCESSFUL;
> +  struct ifnet                *ifp      = &self->arpcom.ac_if;
> +  const dwmac_callback_cfg    *CALLBACK = &self->CFG->CALLBACK;
> +  const dwmac_common_core_ops *CORE_OPS =
> +    (const dwmac_common_core_ops *) self->CFG->MAC_OPS->core;
> +
> +
> +  if ( up && self->state == DWMAC_COMMON_STATE_DOWN ) {
> +    eno = CALLBACK->nic_enable( self->arg );
> +
> +    if ( eno == 0 ) {
> +      eno = CALLBACK->phy_enable( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = CALLBACK->phy_event_enable(
> +        self->arg,
> +        PHY_EVENT_LINK_DOWN
> +        | PHY_EVENT_LINK_UP
> +        );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = dwmac_create_dma_desc_rings( self );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = dwmac_init_dma_engine( self );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Copy the MAC addr into the HW  */
> +      ( CORE_OPS->set_umac_addr )( self, self->arpcom.ac_enaddr, 0 );
> +
> +      eno = ( CALLBACK->bus_setup )( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Initialize the MAC Core */
> +      ( CORE_OPS->core_init )( self );
> +
> +      /* Enable the MAC Rx/Tx */
> +      dwmac_core_set_mac( self, true );
> +
> +      /* Set the HW DMA mode and the COE */
> +      dwmac_dma_operation_mode( self );
> +
> +      /* Set up mmc counters */
> +      dwmac_mmc_setup( self );
> +
> +      /* Install interrupt handler */
> +      sc = rtems_interrupt_handler_install(
> +        self->CFG->IRQ_EMAC,
> +        "Ethernet",
> +        RTEMS_INTERRUPT_UNIQUE,
> +        dwmac_core_dma_interrupt,
> +        self
> +        );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Start the ball rolling ... */
> +      sc  = dwmac_control_request(
> +        self, self->task_id_tx, DWMAC_COMMON_EVENT_TASK_INIT );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      sc  = dwmac_control_request(
> +        self, self->task_id_rx, DWMAC_COMMON_EVENT_TASK_INIT );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      dwmac_core_dma_start_rx( self );
> +
> +      /* Start the phy */
> +      eno = ( CALLBACK->phy_start )( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      self->state = DWMAC_COMMON_STATE_UP;
> +    } else {
> +      ifp->if_flags &= ~IFF_UP;
> +      (void) dwmac_control_request(
> +        self, self->task_id_tx, DWMAC_COMMON_EVENT_TASK_STOP );
> +      (void) dwmac_control_request(
> +        self, self->task_id_rx, DWMAC_COMMON_EVENT_TASK_STOP );
> +      (void) rtems_interrupt_handler_remove(
> +        self->CFG->IRQ_EMAC,
> +        dwmac_core_dma_interrupt,
> +        self
> +        );
> +      (void) ( CALLBACK->phy_stop )( self->arg );
> +      (void) ( CALLBACK->phy_disable )( self->arg );
> +
> +      /* Disable the MAC Rx/Tx */
> +      dwmac_core_set_mac( self, false );
> +      (void) ( CALLBACK->nic_disable )( self->arg );
> +      (void) dwmac_destroy_dma_desc_rings( self );
> +    }
> +  } else if ( !up && self->state == DWMAC_COMMON_STATE_UP ) {
> +    if ( eno == 0 ) {
> +      sc  = dwmac_control_request(
> +        self, self->task_id_tx, DWMAC_COMMON_EVENT_TASK_STOP );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      sc  = dwmac_control_request(
> +        self, self->task_id_rx, DWMAC_COMMON_EVENT_TASK_STOP );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      sc = rtems_interrupt_handler_remove(
> +        self->CFG->IRQ_EMAC,
> +        dwmac_core_dma_interrupt,
> +        self
> +        );
> +      eno = rtems_status_code_to_errno( sc );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = ( CALLBACK->phy_stop )( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = ( CALLBACK->phy_disable )( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Disable the MAC Rx/Tx */
> +      dwmac_core_set_mac( self, false );
> +
> +      eno = CALLBACK->nic_disable( self->arg );
> +    }
> +
> +    if ( eno == 0 ) {
> +      eno = dwmac_destroy_dma_desc_rings( self );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Reset counters to be printed */
> +      memset( &self->stats, 0, sizeof( dwmac_common_stats ) );
> +
> +      /* Change state */
> +      self->state = DWMAC_COMMON_STATE_DOWN;
> +    }
> +  }
> +
> +  return eno;
> +}
> +
> +/* Get commands executed by the driver. This method gets called
> + * automatically from the network stack */
> +static int dwmac_if_interface_ioctl(
> +  struct ifnet   *ifp,
> +  ioctl_command_t cmd,
> +  caddr_t         data )
> +{
> +  dwmac_common_context *self = ifp->if_softc;
> +  int                   eno  = 0;
> +
> +
> +  switch ( cmd ) {
> +    case SIOCGIFMEDIA:
> +    case SIOCSIFMEDIA:
> +      rtems_mii_ioctl( &self->mdio, self, cmd, (int *) data );
> +      break;
> +    case SIOCGIFADDR:
> +    case SIOCSIFADDR:
> +      ether_ioctl( ifp, cmd, data );
> +      break;
> +    case SIOCSIFFLAGS:
> +      eno = dwmac_if_up_or_down( self, ( ifp->if_flags & IFF_UP ) != 0 );
> +
> +      if ( eno == 0 && ( ifp->if_flags & IFF_UP ) != 0 ) {
> +        dwmac_if_set_promiscous_mode( self, ( ifp->if_flags & IFF_PROMISC )
> +                                      != 0 );
> +      } else {
> +        assert( eno == 0 );
> +      }
> +
> +      break;
> +    case SIOCADDMULTI:
> +    case SIOCDELMULTI:
> +#ifndef COMMENTED_OUT
> +      eno = ENOTSUP;
> +#else /* COMMENTED_OUT */
> +      {
> +        struct ifreq                *ifr      = (struct ifreq *) data;
> +        const dwmac_common_core_ops *CORE_OPS =
> +          (const dwmac_common_core_ops *) self->CFG->MAC_OPS->core;
> +        ( CORE_OPS->set_hash_filter )( self, cmd == SIOCADDMULTI, ifr );
> +      }
> +#endif /* COMMENTED_OUT */
> +      break;
> +    case SIO_RTEMS_SHOW_STATS:
> +      eno = dwmac_if_interface_stats( self );
> +      break;
> +    default:
> +      eno = EINVAL;
> +      break;
> +  }
> +
> +  return eno;
> +}
> +
> +/* Method called by the network stack if there are frames to be transmitted */
> +static void dwmac_if_interface_start( struct ifnet *ifp )
> +{
> +  rtems_status_code     sc;
> +  dwmac_common_context *self = ifp->if_softc;
> +
> +
> +  /* Mark that we are transmitting */
> +  ifp->if_flags |= IFF_OACTIVE;
> +
> +  if ( self->state == DWMAC_COMMON_STATE_UP ) {
> +    /* Wake up our task */
> +    sc = rtems_bsdnet_event_send( self->task_id_tx,
> +                                  DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME );
> +    assert( sc == RTEMS_SUCCESSFUL );
> +  }
> +}
> +
> +static int dwmac_if_clk_csr_set(
> +  const uint32_t        gmii_clk_rate,
> +  dwmac_common_context *self )
> +{
> +  int eno = 0;
> +
> +
> +  if ( gmii_clk_rate < DWCGNAC3504_CSR_F_35M ) {
> +    self->csr_clock = DWCGNAC3504_CSR_20_35M;
> +  } else if ( ( gmii_clk_rate >= DWCGNAC3504_CSR_F_35M )
> +              && ( gmii_clk_rate < DWCGNAC3504_CSR_F_60M ) ) {
> +    self->csr_clock = DWCGNAC3504_CSR_35_60M;
> +  } else if ( ( gmii_clk_rate >= DWCGNAC3504_CSR_F_60M )
> +              && ( gmii_clk_rate < DWCGNAC3504_CSR_F_100M ) ) {
> +    self->csr_clock = DWCGNAC3504_CSR_60_100M;
> +  } else if ( ( gmii_clk_rate >= DWCGNAC3504_CSR_F_100M )
> +              && ( gmii_clk_rate < DWCGNAC3504_CSR_F_150M ) ) {
> +    self->csr_clock = DWCGNAC3504_CSR_100_150M;
> +  } else if ( ( gmii_clk_rate >= DWCGNAC3504_CSR_F_150M )
> +              && ( gmii_clk_rate < DWCGNAC3504_CSR_F_250M ) ) {
> +    self->csr_clock = DWCGNAC3504_CSR_150_250M;
> +  } else if ( ( gmii_clk_rate >= DWCGNAC3504_CSR_F_250M )
> +              && ( gmii_clk_rate < DWCGNAC3504_CSR_F_300M ) ) {
> +    self->csr_clock = DWCGNAC3504_CSR_250_300M;
> +  } else {
> +    eno = EINVAL;
> +  }
> +
> +  return eno;
> +}
> +
> +static int dwmac_fixup_unit_count(
> +  const dwmac_common_context *self,
> +  const int                   count,
> +  const int                   default_value,
> +  const int                   max )
> +{
> +  int ret = count;
> +
> +
> +  if ( ret <= 0 ) {
> +    ret = DWMAC_ALIGN( default_value, self->CFG->L1_CACHE_LINE_SIZE );
> +  } else if ( ret > max ) {
> +    ret = DWMAC_ALIGN( max, self->CFG->L1_CACHE_LINE_SIZE );
> +  }
> +
> +  return ret;
> +}
> +
> +/* Called during initial setup */
> +static int dwmac_if_attach(
> +  dwmac_common_context         *self,
> +  struct rtems_bsdnet_ifconfig *bsd_config,
> +  const dwmac_cfg              *driver_config,
> +  void                         *arg )
> +{
> +  int           eno                     = 0;
> +  struct ifnet *ifp                     = &self->arpcom.ac_if;
> +  char         *unit_name               = NULL;
> +  int           unit_number             = rtems_bsdnet_parse_driver_name(
> +    bsd_config,
> +    &unit_name );
> +  const dwmac_callback_cfg    *CALLBACK = &driver_config->CALLBACK;
> +  const dwmac_common_desc_ops *DESC_OPS =
> +    (const dwmac_common_desc_ops *) driver_config->DESC_OPS->ops;
> +
> +
> +  assert( self != NULL );
> +  assert( bsd_config != NULL );
> +  assert( driver_config != NULL );
> +  assert( CALLBACK != NULL );
> +
> +  if ( self == NULL
> +       || bsd_config == NULL
> +       || driver_config == NULL
> +       || CALLBACK == NULL
> +       ) {
> +    eno = EINVAL;
> +  } else {
> +    assert( CALLBACK->nic_enable != NULL );
> +    assert( CALLBACK->nic_disable != NULL );
> +    assert( CALLBACK->phy_enable != NULL );
> +    assert( CALLBACK->phy_disable != NULL );
> +    assert( CALLBACK->phy_event_enable != NULL );
> +    assert( CALLBACK->phy_event_clear != NULL );
> +    assert( CALLBACK->phy_events_get != NULL );
> +    assert( CALLBACK->phy_start != NULL );
> +    assert( CALLBACK->phy_stop != NULL );
> +    assert( CALLBACK->mem_alloc_nocache != NULL );
> +    assert( CALLBACK->mem_free_nocache != NULL );
> +    assert( CALLBACK->bus_setup != NULL );
> +
> +    if ( CALLBACK->nic_enable == NULL
> +         || CALLBACK->nic_disable == NULL
> +         || CALLBACK->phy_enable == NULL
> +         || CALLBACK->phy_disable == NULL
> +         || CALLBACK->phy_event_enable == NULL
> +         || CALLBACK->phy_event_clear == NULL
> +         || CALLBACK->phy_events_get == NULL
> +         || CALLBACK->phy_start == NULL
> +         || CALLBACK->phy_stop == NULL
> +         || CALLBACK->mem_alloc_nocache == NULL
> +         || CALLBACK->mem_free_nocache == NULL
> +         || CALLBACK->bus_setup == NULL
> +         ) {
> +      eno = EINVAL;
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    self->dma_threshold_control = DWMAC_DMA_THRESHOLD_CONTROL_DEFAULT;
> +
> +    if ( driver_config->addr_gmac_regs != NULL ) {
> +      self->macgrp = driver_config->addr_gmac_regs;
> +
> +      if ( driver_config->addr_dma_regs != NULL ) {
> +        self->dmagrp = driver_config->addr_dma_regs;
> +      } else {
> +        eno = EINVAL;
> +      }
> +    } else {
> +      eno = EINVAL;
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    eno = dwmac_if_clk_csr_set(
> +      driver_config->GMII_CLK_RATE,
> +      self
> +      );
> +  }
> +
> +  if ( eno == 0 ) {
> +    assert( 32 >= driver_config->MDIO_BUS_ADDR );
> +
> +    if ( 32 < driver_config->MDIO_BUS_ADDR ) {
> +      eno = EINVAL;
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    self->arg        = arg;        /* Optional argument from upper layer */
> +    self->state      = DWMAC_COMMON_STATE_DOWN;
> +    self->bsd_config = bsd_config; /* BSD-Net configuration.
> +                                      Exists for ll BSD based network divers */
> +
> +    /* Device control */
> +    bsd_config->drv_ctrl = NULL;
> +
> +    /* MDIO */
> +    self->mdio.mdio_r = dwmac_if_mdio_read; /* read from phy
> +                                               registers */
> +    self->mdio.mdio_w = dwmac_if_mdio_write; /* write to phy
> +                                                registers */
> +
> +    if ( driver_config->MAC_OPS == &DWMAC_1000_ETHERNET_MAC_OPS ) {
> +      self->mdio.has_gmii = 1;
> +    } else {
> +      self->mdio.has_gmii = 0;
> +
> +      /* dwmac_dma_ops_100 and dwmac_core_ops_100 is not yet implemented! */
> +      assert( driver_config->MAC_OPS == &DWMAC_1000_ETHERNET_MAC_OPS );
> +      eno = ENOTSUP;
> +    }
> +
> +    if ( eno == 0 ) {
> +      self->CFG     = driver_config;
> +      ifp->if_ioctl = dwmac_if_interface_ioctl; /* Execute commands
> +                                                   at runtime */
> +      ifp->if_init  = dwmac_if_interface_init;        /* Initialization
> +                                                         (called once) */
> +
> +      /* Receive unit count */
> +      bsd_config->rbuf_count = dwmac_fixup_unit_count(
> +        self,
> +        bsd_config->rbuf_count,
> +        DWMAC_CONFIG_RX_UNIT_COUNT_DEFAULT,
> +        DWMAC_CONFIG_RX_UNIT_COUNT_MAX
> +        );
> +
> +      /* Transmit unit count */
> +      bsd_config->xbuf_count = dwmac_fixup_unit_count(
> +        self,
> +        bsd_config->xbuf_count,
> +        DWMAC_CONFIG_TX_UNIT_COUNT_DEFAULT,
> +        DWMAC_CONFIG_TX_UNIT_COUNT_MAX
> +        );
> +
> +      /* Copy MAC address */
> +      memcpy(
> +        self->arpcom.ac_enaddr,
> +        bsd_config->hardware_address,
> +        ETHER_ADDR_LEN
> +        );
> +
> +      /* Set interface data */
> +      ifp->if_softc          = self;
> +      ifp->if_unit           = (short) unit_number;
> +      ifp->if_name           = unit_name;
> +
> +      ifp->if_start          = dwmac_if_interface_start;  /* Start transmitting
> +                                                             frames */
> +      ifp->if_output         = ether_output;
> +      ifp->if_watchdog       = NULL;
> +      ifp->if_flags          = IFF_BROADCAST | IFF_SIMPLEX;
> +      ifp->if_snd.ifq_maxlen = ifqmaxlen;
> +      ifp->if_timer          = 0;
> +      ifp->if_mtu            =
> +        bsd_config->mtu > 0 ? (u_long) bsd_config->mtu : ETHERMTU;
> +
> +      eno = DESC_OPS->validate( self );
> +      assert( eno == 0 );
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Create and start the receive task for our driver */
> +      assert( self->task_id_rx == RTEMS_ID_NONE );
> +      self->task_id_rx = rtems_bsdnet_newproc(
> +        "ntrx",
> +        4096,
> +        dwmac_task_rx,
> +        self
> +        );
> +      assert( self->task_id_rx != RTEMS_ID_NONE );
> +
> +      if ( self->task_id_rx == RTEMS_ID_NONE ) {
> +        eno = ENOMEM;
> +      }
> +    }
> +
> +    if ( eno == 0 ) {
> +      /* Create and start the transmit task for our driver */
> +      assert( self->task_id_tx == RTEMS_ID_NONE );
> +      self->task_id_tx = rtems_bsdnet_newproc(
> +        "nttx",
> +        4096,
> +        dwmac_task_tx,
> +        self
> +        );
> +      assert( self->task_id_tx != RTEMS_ID_NONE );
> +
> +      if ( self->task_id_tx == RTEMS_ID_NONE ) {
> +        eno = ENOMEM;
> +      }
> +    }
> +  }
> +
> +  if ( eno == 0 ) {
> +    /* Change status */
> +    ifp->if_flags |= IFF_RUNNING;
> +
> +    /* Attach the interface */
> +    if_attach( ifp );
> +    ether_ifattach( ifp );
> +  }
> +
> +  return eno;
> +}
> +
> +/* Initial setup method. Part of the driver API
> + * Returns the address of the driver context on success and NULL on failure */
> +void *dwmac_network_if_attach_detach(
> +  struct rtems_bsdnet_ifconfig *bsd_config,
> +  const dwmac_cfg              *driver_config,
> +  void                         *arg,
> +  int                           attaching )
> +{
> +  int                   eno     = 0;
> +  dwmac_common_context *context = NULL;
> +
> +
> +  if ( attaching ) {
> +    context = calloc( 1, sizeof( dwmac_common_context ) );
> +    assert( context != NULL );
> +
> +    if ( context != NULL ) {
> +      eno = dwmac_if_attach(
> +        context,
> +        bsd_config,
> +        driver_config,
> +        arg
> +        );
> +
> +      if ( eno != 0 ) {
> +        free( context, 0 );
> +        context = NULL;
> +      }
> +    }
> +  } else {
> +    /* Detaching is not supported */
> +    assert( attaching != false );
> +  }
> +
> +  return context;
> +}
> +
> +int dwmac_if_read_from_phy(
> +  void          *arg,
> +  const unsigned phy_reg,
> +  uint16_t      *val )
> +{
> +  int                   eno  = EINVAL;
> +  dwmac_common_context *self = (dwmac_common_context *) arg;
> +  uint32_t              value;
> +
> +
> +  if ( arg != NULL ) {
> +    eno = dwmac_if_mdio_read(
> +      self->CFG->MDIO_BUS_ADDR,
> +      self,
> +      phy_reg,
> +      &value );
> +  }
> +
> +  if ( eno == 0 ) {
> +    *val = (uint16_t) value;
> +  }
> +
> +  return eno;
> +}
> +
> +int dwmac_if_write_to_phy(
> +  void          *arg,
> +  const unsigned phy_reg,
> +  const uint16_t val )
> +{
> +  int                   eno  = EINVAL;
> +  dwmac_common_context *self = (dwmac_common_context *) arg;
> +
> +
> +  if ( arg != NULL ) {
> +    eno = dwmac_if_mdio_write(
> +      self->CFG->MDIO_BUS_ADDR,
> +      self,
> +      phy_reg,
> +      val );
> +  }
> +
> +  return eno;
> +}
> +
> +int dwmac_if_handle_phy_event( void *arg )
> +{
> +  int                   eno;
> +  rtems_status_code     sc;
> +  dwmac_common_context *self = (dwmac_common_context *) arg;
> +
> +
> +  sc = rtems_bsdnet_event_send(
> +    self->task_id_tx,
> +    DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE
> +    );
> +  eno = rtems_status_code_to_errno( sc );
> +
> +  return eno;
> +}
> \ No newline at end of file
> diff --git a/c/src/libchip/network/dwmac.h b/c/src/libchip/network/dwmac.h
> new file mode 100644
> index 0000000..3592f26
> --- /dev/null
> +++ b/c/src/libchip/network/dwmac.h
> @@ -0,0 +1,867 @@
> +/**
> + * @file dwmac.h
> + *
> + * @ingroup [GROUP NAME]
> + *
> + * @brief API header for the DWMAC 10/100/1000 Network Interface Controllers
> + *
> + * DWMAC 10/100/1000 on-chip Ethernet controllers are a Synopsys IP Core.
> + */
> +
> +/*
> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
> + *
> + *  embedded brains GmbH
> + *  Dornierstr. 4
> + *  82178 Puchheim
> + *  Germany
> + *  <rtems at embedded-brains.de>
> + *
> + * The license and distribution terms for this file may be
> + * found in the file LICENSE in this distribution or at
> + * http://www.rtems.org/license/LICENSE.
> + */
> +
> +#ifndef DWMAC_H_
> +#define DWMAC_H_
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <rtems/rtems_bsdnet.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +/** @brief PHY event.
> + *
> + * Data type to be used for PHY events and event sets.
> + */
> +typedef uint8_t dwmac_phy_event;
> +
> +/** @brief PHY event Jabber. */
> +extern const dwmac_phy_event PHY_EVENT_JABBER;
> +
> +/** @brief PHY event Receive Error. */
> +extern const dwmac_phy_event PHY_EVENT_RECEIVE_ERROR;
> +
> +/** @brief PHY event Page Receive. */
> +extern const dwmac_phy_event PHY_EVENT_PAGE_RECEIVE;
> +
> +/** @brief PHY event Parallel Detect Fault. */
> +extern const dwmac_phy_event PHY_EVENT_PARALLEL_DETECT_FAULT;
> +
> +/** @brief PHY event Link Partner Acknowledge. */
> +extern const dwmac_phy_event PHY_EVENT_LINK_PARTNER_ACK;
> +
> +/** @brief PHY event Ling Down. */
> +extern const dwmac_phy_event PHY_EVENT_LINK_DOWN;
> +
> +/** @brief PHY event Remote Fault. */
> +extern const dwmac_phy_event PHY_EVENT_REMOTE_FAULT;
> +
> +/** @brief PHY event Link Up. */
> +extern const dwmac_phy_event PHY_EVENT_LINK_UP;
> +
> +/** @brief NIC enable
> + *
> + * Enables (powers up) the network interface card.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_nic_enable)( void *arg );
> +
> +/** @brief NIC disable.
> + *
> + * Disables (powers down) the network interface card.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_nic_disable)( void *arg );
> +
> +/** @brief PHY enable.
> + *
> + * Enables (powers up) the network PHY.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_phy_enable)( void *arg );
> +
> +/** @brief PHY disable.
> + *
> + * Disables (powers down) the network PHY.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_phy_disable)( void *arg );
> +
> +/** @brief PHY event enable.
> + *
> + * Enables generation of events for an event set.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @param[in] event_set   Set of events. For these events shall get generated
> + *                        upon PHY status change.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_phy_event_enable)(
> +  void                 *arg,
> +  const dwmac_phy_event event_set );
> +
> +/** @brief Clear phy event status.
> + *
> + * Clears all PHY event statuses.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_phy_event_status_clear)( void *arg );
> +
> +/**
> + * @brief Get the PHY event status.
> + *
> + * Reports status on PHY events (e.g. PHY interrupts).
> + * @param[in]  arg        The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @param[out] event_set  Pointer to a buffer for a set of events for which a
> + *                        PHY status change was detected.
> + *                        For events see @see dwmac_phy_event.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_phy_events_status_get)(
> +  void            *arg,
> +  dwmac_phy_event *event_set );
> +
> +/**
> + * @brief Start the network PHY.
> + *
> + * Do anything necessary to start the network PHY (start generating
> + * events, ...).
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwcmac_if_phy_start)( void *arg );
> +
> +/**
> + * @brief Stop the network PHY.
> + *
> + * Do anything necessary to stop the network PHY (stop generating events, ...).
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwcmac_if_phy_stop)( void *arg );
> +
> +/**
> + * @brief Allocate nocache RAM.
> + *
> + * Allocate uncached RAM.
> + * @param[in]  arg        The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @param[out] memory     Pointer of a buffer to write the address of the
> + *                        allocated memory to.
> + * @param[in]  size       Number of bytes to be allocated
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_mem_alloc_nocache)(
> +  void        *arg,
> +  void       **memory,
> +  const size_t size );
> +
> +/**
> + * @brief Free nocache RAM.
> + *
> + * Release uncached RAM.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @param[in] memory      Pointer to the memory to be freed.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwmac_if_mem_free_nocache)(
> +  void *arg,
> +  void *memory );
> +
> +/**
> + * @brief Bus setup.
> + *
> + * Callback method for setting up the system bus for the network driver.
> + * @param[in] arg         The void pointer argument passed to
> + *                        @see dwmac_network_if_attach_detach.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +typedef int
> +(*dwcmac_if_bus_setup)( void *arg );
> +
> +/**
> + * @brief Callback methods.
> + *
> + * The address of an instance of such a callback struct must get passed
> + * to @see dwmac_network_if_attach_detach() for initialization.
> + * Via these callback methods, those parts of the network driver which
> + * are micro controller specific or PCB specific will get handled.
> + */
> +typedef struct {
> +  /** @brief Enable the network interface controller. */
> +  dwmac_if_nic_enable nic_enable;
> +
> +  /** @brief Disable the network interface controller. */
> +  dwmac_if_nic_disable nic_disable;
> +
> +  /** @brief Enable (power up, ... ) the network PHY. */
> +  dwmac_if_phy_enable phy_enable;
> +
> +  /** @brief Disable (power down, ... ) the network PHY. */
> +  dwmac_if_phy_disable phy_disable;
> +
> +  /** @brief Enable a set of PHY events for generation upon status change. */
> +  dwmac_if_phy_event_enable phy_event_enable;
> +
> +  /** @brief Clear the event status (e.g. interrupt staus) of the PHY. */
> +  dwmac_if_phy_event_status_clear phy_event_clear;
> +
> +  /** @brief Get set of tripped events from PHY. */
> +  dwmac_if_phy_events_status_get phy_events_get;
> +
> +  /** @brief Start the phy (start generating events, ...). */
> +  dwcmac_if_phy_start phy_start;
> +
> +  /** @brief Stop the phy (stop generating events, ...). */
> +  dwcmac_if_phy_stop phy_stop;
> +
> +  /** @brief Allocate uncached memory. */
> +  dwmac_if_mem_alloc_nocache mem_alloc_nocache;
> +
> +  /** @brief Free uncached memory. */
> +  dwmac_if_mem_free_nocache mem_free_nocache;
> +
> +  /** @brief Setup handling for bus upon device up. */
> +  dwcmac_if_bus_setup bus_setup;
> +} dwmac_callback_cfg;
> +
> +/** @brief Initializer for callback methods.
> + *
> + * Initializes a struct which contains pointers to the callback methods
> + * required by the driver.
> + * For the struct see @see dwmac_callback_cfg.
> + * @param[in] nic_enable              Callback method for for enabling the
> + *                                    network interface controller.
> + *                                    (@see dwmac_if_nic_enable)
> + * @param[in] nic_disable             Callback method for disabling the
> + *                                    network interface controller.
> + *                                    (@see dwmac_if_nic_disable)
> + * @param[in] phy_enable              Callback method for enabling the
> + *                                    network PHY.
> + *                                    (@see dwmac_if_phy_enable)
> + * @param[in] phy_disable             Callback method for disabling the
> + *                                    network PHY.
> + *                                    (@see dwmac_if_phy_disable)
> + * @param[in] phy_event_enable        Callback method for enabling PHY status
> + *                                    changes for event generation.
> + *                                    (@see dwmac_if_phy_event_enable)
> + * @param[in] phy_event_clear         Callback method for
> + *                                    clearing/acknowledging PHY events.
> + *                                    (@see dwmac_if_phy_event_status_clear)
> + * @param[in] phy_events_get          Callback method for reading the status of
> + *                                    PHY events.
> + *                                    (@see dwmac_if_phy_events_status_get)
> + * @param[in] phy_start               Callback method for starting event
> + *                                    generation by the network PHY.
> + *                                    (@see dwcmac_if_phy_start)
> + * @param[in] phy_stop                Callback method for stoping event
> + *                                    generation by the network PHY.
> + *                                    (@see dwcmac_if_phy_stop)
> + * @param[in] mem_alloc_nocache       Callback method for allocating uncached
> + *                                    RAM.
> + *                                    (@see dwmac_if_mem_alloc_nocache)
> + * @param[in] mem_free_nocache        Callback method for releasing uncached
> + *                                    RAM.
> + *                                    (@see dwmac_if_mem_free_nocache)
> + * @param[in] bus_setup               Callback method for setting up the system
> + *                                    bus.
> + *                                    (@see dwcmac_if_bus_setup)
> + * @retval An initialized struct of pointers to callback methods.
> + */
> +#define DWMAC_CALLBACK_CFG_INITIALIZER( \
> +    nic_enable, \
> +    nic_disable, \
> +    phy_enable, \
> +    phy_disable, \
> +    phy_event_enable, \
> +    phy_event_clear, \
> +    phy_events_get, \
> +    phy_start, \
> +    phy_stop, \
> +    mem_alloc_nocache, \
> +    mem_free_nocache, \
> +    bus_setup \
> +    ) \
> +  { \
> +    nic_enable, \
> +    nic_disable, \
> +    phy_enable, \
> +    phy_disable, \
> +    phy_event_enable, \
> +    phy_event_clear, \
> +    phy_events_get, \
> +    phy_start, \
> +    phy_stop, \
> +    mem_alloc_nocache, \
> +    mem_free_nocache, \
> +    bus_setup \
> +  }
> +
> +/** @brief Ethernet MAC operations.
> + *
> + * Actually this is a mere wrapper which contains void ponters to the core
> + * operations and DMA operations to be used by the driver (void pointer
> + * for the purpose of information hiding).
> + * There will be two instances of such a struct:
> + * One for DWMAC 10/100 ethernet operations: @see DWMAC_100_ETHERNET_MAC_OPS.
> + * And one for DWMAC 1000 ethernet operations: @see DWMAC_1000_ETHERNET_MAC_OPS.
> + * The address of either of these must get passed to @see DWMAC_CFG_INITIALIZER
> + * for configuring the driver.
> + * For an initializer see @see DWMAC_ETHERNET_MAC_OPS_INITIALIZER
> + */
> +typedef struct {
> +  const void *core;
> +  const void *dma;
> +} dwmac_ethernet_mac_ops;
> +
> +/** @brief Ethernet MAC operations initializer.
> + *
> + * Initializes a structure of ethernet MAC operations.
> + * For the struct @see dwmac_ethernet_mac_ops.
> + * @param core_ops_addr Address of the core operations to be used by the
> + *                      driver.
> + * @param dma_ops_addr  Address of the DMA operations to be used by the driver.
> + * @retval An initialized struct of ethernet mac operations
> + */
> +#define DWMAC_ETHERNET_MAC_OPS_INITIALIZER( \
> +    core_ops_addr, \
> +    dma_ops_addr \
> +    ) \
> +  { \
> +    core_ops_addr, \
> +    dma_ops_addr \
> +  }
> +
> +/** @brief Descriptor operations.
> + *
> + * Actually this is a mere wrapper which contains a void pointer to a
> + * descriptor operations struct which can be used by the driver (void pointer
> + * for the purpose of information hiding).
> + * There will be two instances of such a struct:
> + * One for normal DMA descriptors @see DWMAC_DESCRIPTOR_OPS_NORMAL.
> + * And one for enhanced DMA descriptors @see DWMAC_DESCRIPTOR_OPS_ENHANCED.
> + * The address of either of these must get passed to @see DWMAC_CFG_INITIALIZER
> + * for configuring the driver.
> + * For an initializer @see DWMAC_DESCRIPTOR_OPS_INITIALIZER.
> + */
> +typedef struct {
> +  /** @brief Address of the descriptor operations to be used by the driver */
> +  const void *ops;
> +} dwmac_descriptor_ops;
> +
> +/** @brief Initializer for descriptor operations.
> + *
> + * Initializes a struct of type @see dwmac_descriptor_ops.
> + * @param desc_ops_addr Address of the descriptor operations.
> + * @retval Returns an initialized descriptor operations struct.
> + */
> +#define DWMAC_DESCRIPTOR_OPS_INITIALIZER( \
> +    desc_ops_addr \
> +    ) \
> +  { \
> +    desc_ops_addr \
> +  }
> +
> +/** @brief Ethernet MAC operations for DWMAC 1000.
> + *
> + * Pass the address of DWMAC_1000_ETHERNET_MAC_OPS to
> + * @see DWMAC_CFG_INITIALIZER
> + * if the driver is supposed to control a DWMAC 1000. */
> +extern const dwmac_ethernet_mac_ops DWMAC_1000_ETHERNET_MAC_OPS;
> +
> +/* TODO: To be implemented in the future */
> +
> +/** @brief Ethernet MAC operations for DWMAC 10/100.
> + *
> + * Pass the address of DWMAC_100_ETHERNET_MAC_OPS to
> + * @see DWMAC_CFG_INITIALIZER
> + * if the driver is supposed to control a DWMAC 10/100. */
> +
> +/*extern const dwmac_ethernet_mac_ops DWMAC_100_ETHERNET_MAC_OPS; */
> +
> +/*  TODO: To be implemented in the future */
> +
> +/** @brief DMA Descriptor operations for normal descriptors.
> + *
> + * Pass the address of DWMAC_DESCRIPTOR_OPS_NORMAL to
> + * @see DWMAC_CFG_INITIALIZER
> + * if you intend to use the normal DMA descriptors. */
> +
> +/*extern const dwmac_descriptor_ops   DWMAC_DESCRIPTOR_OPS_NORMAL;*/
> +
> +/** @brief DMA Descriptor operations for enhanced descriptors.
> + *
> + * Pass the address of DWMAC_DESCRIPTOR_OPS_ENHANCED to
> + * @see DWMAC_CFG_INITIALIZER
> + * if you intend to use the enhanced DMA descriptors. */
> +extern const dwmac_descriptor_ops DWMAC_DESCRIPTOR_OPS_ENHANCED;
> +
> +/** @brief Burst size. */
> +typedef enum {
> +  /** @brief Burst size = 1. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_1 = 0,
> +
> +  /** @brief Burst size = 2. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_2 = 1,
> +
> +  /** @brief Burst size = 4. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_4 = 3,
> +
> +  /** @brief Burst size = 8. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_8 = 7,
> +
> +  /** @brief Burst size = 16. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_16 = 15,
> +
> +  /** @brief Burst size = 32. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_32 = 31,
> +
> +  /** @brief Burst size = 64. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_64 = 63,
> +
> +  /** @brief Burst size = 128. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_128 = 127,
> +
> +  /** @brief Burst size = 256. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_256 = 255
> +} dwmac_dma_cfg_bus_mode_burst_length;
> +
> +/** @brief Burst mode. */
> +typedef enum {
> +  /** @brief Single burst or incrment bursts. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_SINGLE_OR_INCR,
> +
> +  /** @brief Fixed burst size. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_FIXED
> +} dwmac_dma_cfg_bus_mode_burst_mode;
> +
> +/** @brief Mixed burst mode support. */
> +typedef enum {
> +  /** @brief Mixed burst mode is not supported. */
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_NOT_MIXED,
> +  DWMAC_DMA_CFG_BUS_MODE_BURST_MIXED
> +} dwmac_dma_cfg_bus_mode_burst_mixed;
> +
> +/** @brief Burst length 4 support. */
> +typedef enum {
> +  /** @brief Bursts of length 4 are not supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_NOT_SUPPORTED,
> +
> +  /** @brief Bursts of length 4 are supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_SUPPORTED
> +} dwmac_dma_cfg_axi_burst_length_4_support;
> +
> +/** @brief Burst length 8 support. */
> +typedef enum {
> +  /** @brief Bursts of length 8 are not supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_NOT_SUPPORTED,
> +
> +  /** @brief Bursts of length 8 are supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_SUPPORTED
> +} dwmac_dma_cfg_axi_burst_length_8_support;
> +
> +/** @brief Burst length 16 support. */
> +typedef enum {
> +  /** @brief Bursts of length 16 are not supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_NOT_SUPPORTED,
> +
> +  /** @brief Bursts of length 16 are supported. */
> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_SUPPORTED
> +} dwmac_dma_cfg_axi_burst_length_16_support;
> +
> +/** @brief DMA Burst Boundary parameters. */
> +typedef enum {
> +  /** @brief Transfers do not cross 4 kB boundary. */
> +  DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_4_KB,
> +
> +  /** @brief Transfers do not cross 1 kB boundary. */
> +  DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_1_KB
> +} dwmac_dma_cfg_axi_burst_boundary;
> +
> +/**
> + * @brief DMA configuration.
> + *
> + * Configuration data for the DMA of the network driver. See
> + * @see DWMAC_DMA_CFG_INITIALIZER
> + * for an inititializer.
> + */
> +typedef union {
> +  uint16_t raw;
> +  struct {
> +    /** @brief Maximum number of beats to be transferred in one DMA transaction.
> +     *
> +     * This is the maximum value that is used in a single block Read or Write.
> +     * The DMA always attempts to burst as specified in bus_mode_burst_length
> +     * each time it starts a Burst transfer on the host bus.
> +     * bus_mode_burst_length can be programmed with permissible values as
> +     * specified in @see dwmac_dma_cfg_bus_mode_burst_length.
> +     * Any other value results in undefined behavior.
> +     * The bus_mode_burst_length values have the following limitation:
> +     * The maximum number of possible beats (bus_mode_burst_length) is limited
> +     * by the size of the Tx FIFO and Rx FIFO in the MTL layer and the data bus
> +     * width on the DMA.
> +     * The FIFO has a constraint that the maximum beat supported is half the
> +     * depth of the FIFO, except when specified. */
> +    uint16_t bus_mode_burst_length       : 6;
> +
> +    /** @brief Controls whether the AXI Master performs fixed bursts or not.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_bus_mode_burst_mode.
> +     * When set to DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_FIXED, the AXI interface
> +     * uses FIXED bursts during the start of the normal burst transfers.
> +     * When set to DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_SINGLE_OR_INCR, the AXI
> +     * interface uses SINGLE and INCR burst transfer operations. */
> +    uint16_t bus_mode_burst_mode         : 1;
> +
> +    /** @brief Controls whether mixed bursts will be used or not.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_bus_mode_burst_mixed.
> +     * Mixed burst has no effect when if DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_FIXED is set. */
> +    uint16_t bus_mode_burst_mixed        : 1;
> +
> +    /** @brief Controls support of burst length 4.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_axi_burst_length_4_support.
> +     * When set to DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_SUPPORTED, the GMAC-AXI is
> +     * allowed to select a burst length of 4 on the AXI Master interface.*/
> +    uint16_t axi_burst_length_4_support  : 1;
> +
> +    /** @brief Controls support of burst length 8.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_axi_burst_length_8_support.
> +     * When set to DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_SUPPORTED, the GMAC-AXI is
> +     * allowed to select a burst length of 8 on the AXI Master interface. */
> +    uint16_t axi_burst_length_8_support  : 1;
> +
> +    /** @brief Controls support of burst length 16.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_axi_burst_length_16_support.
> +     * When set to DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_SUPPORTED fixed bust is
> +     * not selected, the GMAC-AXI is allowed to select a burst length of 16 on
> +     * the AXI Master interface. */
> +    uint16_t axi_burst_length_16_support : 1;
> +
> +    /** @brief Select Burst Boundary.
> +     *
> +     * For valid parameters see:
> +     * @see dwmac_dma_cfg_axi_burst_boundary.
> +     * When set to DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_1_KB, the GMAC-AXI Master
> +     * performs burst transfers that do not cross 1 KB boundary.
> +     * When set to DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_4_KB, the GMAC-AXI Master
> +     * performs burst transfers that do not cross 4 KB boundary.*/
> +    uint16_t axi_burst_boundary          : 1;
> +
> +    uint16_t unused                      : 4;
> +  };
> +} dwmac_dma_cfg;
> +
> +/** @brief DMA Configuration initializer.
> + *
> + * Initializer for a DMA configuration struct.
> + *
> + * @param[in] bus_mode_burst_length       Number of bytes to be sent in one
> + *                                        burst within a DMA transfer on the
> + *                                        bus .
> + *                                        (@see dwmac_dma_cfg_bus_mode_burst_length)
> + * @param[in] bus_mode_burst_mode         Mode to be used for burst transfers.
> + *                                        (@see dwmac_dma_cfg_bus_mode_burst_mode)
> + * @param[in] bus_mode_burst_mixed        Use mixed bursts or not. Fixed bursts
> + *                                        have priority over mixed bursts.
> + *                                        (@see dwmac_dma_cfg_bus_mode_burst_mixed)
> + * @param[in] axi_burst_length_4_support  Support or don't support burst
> + *                                        lengths of 4.
> + *                                        (@see dwmac_dma_cfg_axi_burst_length_4_support)
> + * @param[in] axi_burst_length_8_support  Support or don't support burst
> + *                                        lengths of 8.
> + *                                        (@see dwmac_dma_cfg_axi_burst_length_8_support)
> + * @param[in] axi_burst_length_16_support Support or don't support burst
> + *                                        lengths of 16.
> + *                                        (@see dwmac_dma_cfg_axi_burst_length_16_support)
> + * @param[in] axi_burst_boundary          Select the burst boundary.
> + *                                        (@see dwmac_dma_cfg_axi_burst_boundary)
> + * @retval An initialized struct of DMA configuration parameters.
> + */
> +#define DWMAC_DMA_CFG_INITIALIZER( \
> +    bus_mode_burst_length, \
> +    bus_mode_burst_mode, \
> +    bus_mode_burst_mixed, \
> +    axi_burst_length_4_support, \
> +    axi_burst_length_8_support, \
> +    axi_burst_length_16_support, \
> +    axi_burst_boundary \
> +    ) \
> +  { \
> +    BSP_FLD16( bus_mode_burst_length, 0, 5 ) \
> +    | BSP_FLD16( bus_mode_burst_mode, 6, 6 ) \
> +    | BSP_FLD16( bus_mode_burst_mixed, 7, 7 ) \
> +    | BSP_FLD16( axi_burst_length_4_support, 8, 8 ) \
> +    | BSP_FLD16( axi_burst_length_8_support, 9, 9 ) \
> +    | BSP_FLD16( axi_burst_length_16_support, 10, 10 ) \
> +    | BSP_FLD16( axi_burst_boundary, 11, 11 ) \
> +  }
> +
> +/**
> + * @brief Driver configuration.
> + *
> + * Configuration data for the network driver.
> + * See @see DWMAC_CFG_INITIALIZER
> + * for an initializer.
> + */
> +typedef struct {
> +  /** @brief The clock to be used for the gmii interface in Hz. */
> +  const uint32_t GMII_CLK_RATE;
> +
> +  /** @brief Start address of the MAC group registers. */
> +  volatile void *addr_gmac_regs;
> +
> +  /** @brief Start address of the DMA group registers. */
> +  volatile void *addr_dma_regs;
> +
> +  /** @brief Address of the PHY on the mdio bus (5 bit). */
> +  const uint8_t MDIO_BUS_ADDR;
> +
> +  /** @brief Bytes per L1 cache line. */
> +  const uint8_t L1_CACHE_LINE_SIZE;
> +
> +  /** @brief Interrupt vector number for EMAC IRQs. */
> +  const rtems_vector_number IRQ_EMAC;
> +
> +  /** @brief Set to true if prefetching into cache via PLD is supported. */
> +  const bool ARCH_HAS_PREFETCH;
> +
> +  /** @brief Optional configuration for bus mode and axi bus mode. */
> +  const dwmac_dma_cfg *DMA_CFG;
> +
> +  /** @brief Methods which must get provided to the by the micro controller. */
> +  const dwmac_callback_cfg CALLBACK;
> +
> +  /** @brief Operations which are specific to the ethernet MAC. */
> +  const dwmac_ethernet_mac_ops *MAC_OPS;
> +
> +  /** @brief DMA descriptor operations. */
> +  const dwmac_descriptor_ops *DESC_OPS;
> +} dwmac_cfg;
> +
> +/**
> + * @brief Configuration initializer.
> + *
> + * Initializes the configuration data to be passed to
> + * the initialization method (@see dwmac_network_if_attach_detach()).
> + *
> + * @param[in] mdio_clk_rate           The clock to be used for the gmii
> + *                                    interface in Hz.
> + * @param[in] macgrp_regs_addr        Base address of the MAC group registers.
> + * @param[in] dmagrp_regs_addr        Base address of the DMA group registers.
> + * @param[in] mdio_bus_addr           Address of the network PHY on the
> + *                                    mdio bus.
> + * @param[in] l1_cache_line_size      Size of a cache line in the level 1 cache.
> + * @param[in] irq_emac                Number of the EMAC interrupt.
> + * @param[in] arch_has_prefetch       True if architecture supports.
> + *                                    prefetching, false if not.
> + * @param[in] dma_cfg_addr            Address of the optional DMA configuration.
> + *                                    Set to NULL for defaults.
> + *                                    (@see dwmac_dma_cfg)
> + * @param[in] nic_enable              Callback method for for enabling the
> + *                                    network interface controller.
> + *                                    (@see dwmac_if_nic_enable)
> + * @param[in] nic_disable             Callback method for disabling the
> + *                                    network interface controller.
> + *                                    (@see dwmac_if_nic_disable)
> + * @param[in] phy_enable              Callback method for enabling the
> + *                                    network PHY.
> + *                                    (@see dwmac_if_phy_enable)
> + * @param[in] phy_disable             Callback method for disabling the
> + *                                    network PHY.
> + *                                    (@see dwmac_if_phy_disable)
> + * @param[in] phy_event_enable        Callback method for enabling PHY status
> + *                                    changes for event generation.
> + *                                    (@see dwmac_if_phy_event_enable)
> + * @param[in] phy_event_clear         Callback method for
> + *                                    clearing/acknowledging PHY events.
> + *                                    (@see dwmac_if_phy_event_status_clear)
> + * @param[in] phy_events_get          Callback method for reading the status of
> + *                                    PHY events.
> + *                                    (@see dwmac_if_phy_events_status_get)
> + * @param[in] phy_start               Callback method for starting event
> + *                                    generation by the network PHY.
> + *                                    (@see dwcmac_if_phy_start)
> + * @param[in] phy_stop                Callback method for stoping event
> + *                                    generation by the network PHY.
> + *                                    (@see dwcmac_if_phy_stop)
> + * @param[in] mem_alloc_nocache       Callback method for allocating uncached
> + *                                    RAM.
> + *                                    (@see dwmac_if_mem_alloc_nocache)
> + * @param[in] mem_free_nocache        Callback method for releasing uncached
> + *                                    RAM.
> + *                                    (@see dwmac_if_mem_free_nocache)
> + * @param[in] bus_setup               Callback method for setting up the system
> + *                                    bus.
> + *                                    (@see dwcmac_if_bus_setup)
> + * @param[in] ethernet_mac_ops_addr   Address of a struct encapsulating
> + *                                    ethernet MAC operations for DWMAC 1000 or
> + *                                    DWMAC 10/100.
> + *                                    (@see DWMAC_1000_ETHERNET_MAC_OPS)
> + *                                    (@see DWMAC_100_ETHERNET_MAC_OPS)
> + * @param[in] descriptor_ops_addr     Address of a struct encasulating DMA
> + *                                    descriptor operations for either normal
> + *                                    descriptors or enhanced descriptors.
> + *                                    (@see DWMAC_DESCRIPTOR_OPS_NORMAL)
> + *                                    (@see DWMAC_DESCRIPTOR_OPS_ENHANCED)
> + * @retval An initialized struct of configuration parameters (@see dwmac_cfg).
> + */
> +#define DWMAC_CFG_INITIALIZER( \
> +    mdio_clk_rate, \
> +    macgrp_regs_addr, \
> +    dmagrp_regs_addr, \
> +    mdio_bus_addr, \
> +    l1_cache_line_size, \
> +    irq_emac, \
> +    arch_has_prefetch, \
> +    dma_cfg_addr, \
> +    nic_enable, \
> +    nic_disable, \
> +    phy_enable, \
> +    phy_disable, \
> +    phy_event_enable, \
> +    phy_event_clear, \
> +    phy_events_get, \
> +    phy_start, \
> +    phy_stop, \
> +    mem_alloc_nocache, \
> +    mem_free_nocache, \
> +    bus_setup, \
> +    ethernet_mac_ops_addr, \
> +    descriptor_ops_addr \
> +    ) \
> +  { \
> +    mdio_clk_rate, \
> +    macgrp_regs_addr, \
> +    dmagrp_regs_addr, \
> +    mdio_bus_addr, \
> +    l1_cache_line_size, \
> +    irq_emac, \
> +    arch_has_prefetch, \
> +    dma_cfg_addr, \
> +    DWMAC_CALLBACK_CFG_INITIALIZER( \
> +      nic_enable, \
> +      nic_disable, \
> +      phy_enable, \
> +      phy_disable, \
> +      phy_event_enable, \
> +      phy_event_clear, \
> +      phy_events_get, \
> +      phy_start, \
> +      phy_stop, \
> +      mem_alloc_nocache, \
> +      mem_free_nocache, \
> +      bus_setup \
> +      ), \
> +    ethernet_mac_ops_addr, \
> +    descriptor_ops_addr \
> +  }
> +
> +/**
> + * @brief Initialization method.
> + *
> + * Initialized the network driver and "links" it to the network stack.
> + *
> + * @param[in]  bsd_config     The BSD configuation passed to all
> + *                            network_if_attach_detach() methods.
> + * @param[in]  driver_config  Address of of a struct containing driver
> + *                            specific configuration data.
> + *                            @see dwmac_cfg
> + *                            @see DWMAC_CFG_INITIALIZER()
> + * @param[in]  arg            An optional argument which will get passed to all
> + *                            callback methods.
> + * @param[in]  attching       1 for attching and 0 for detaching.
> + * @retval  Address of the drivers context if successful or NULL if not
> + *          successful.
> + */
> +void *dwmac_network_if_attach_detach(
> +  struct rtems_bsdnet_ifconfig *bsd_config,
> +  const dwmac_cfg              *driver_config,
> +  void                         *arg,
> +  int                           attaching );
> +
> +/**
> + * @brief Read from PHY
> + *
> + * Read a value from a register of the network PHY.
> + *
> + * @param[in]   arg     Pointer returned from dwmac_network_if_attach_detach.
> + *                      @see dwmac_network_if_attach_detach()
> + * @param[in]   phy_reg The PHY register to be read from.
> + * @param[out]  val     Buffer address for the value to be read.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +int dwmac_if_read_from_phy(
> +  void          *arg,
> +  const unsigned phy_reg,
> +  uint16_t      *val );
> +
> +/**
> + * @brief Write to PHY.
> + *
> + * Write a value to a register of the network PHY.
> + *
> + * @param[in] arg     Pointer returned from dwmac_network_if_attach_detach.
> + *                    @see dwmac_network_if_attach_detach()
> + * @param[in] phy_reg The PHY register to be written to.
> + * @param[in] val     The value to be written.
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +int dwmac_if_write_to_phy(
> +  void          *arg,
> +  const unsigned phy_reg,
> +  const uint16_t val );
> +
> +/**
> + * @brief Handle PHY event.
> + *
> + * Handle an event from the network PHY.
> + *
> + * @param[in] arg   Pointer returned from dwmac_network_if_attach_detach.
> + *                  @see dwmac_network_if_attach_detach()
> + * @retval 0 on success, error code from errno.h on failure.
> + */
> +int dwmac_if_handle_phy_event( void *arg );
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* DWMAC_H_ */
> \ No newline at end of file
> diff --git a/c/src/libchip/preinstall.am b/c/src/libchip/preinstall.am
> index 8b9a0bb..452818f 100644
> --- a/c/src/libchip/preinstall.am
> +++ b/c/src/libchip/preinstall.am
> @@ -97,6 +97,10 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/smc91111.h
>  $(PROJECT_INCLUDE)/libchip/smc91111exp.h: network/smc91111exp.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/smc91111exp.h
>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/smc91111exp.h
> +
> +$(PROJECT_INCLUDE)/libchip/dwmac.h: network/dwmac.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/dwmac.h
> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/dwmac.h
>  endif
>  $(PROJECT_INCLUDE)/libchip/rtc.h: rtc/rtc.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/rtc.h
> --
> 1.7.10.4
>
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel




More information about the devel mailing list