summaryrefslogtreecommitdiffstats
path: root/c/src/libchip/network/dwmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/libchip/network/dwmac.c')
-rw-r--r--c/src/libchip/network/dwmac.c2374
1 files changed, 0 insertions, 2374 deletions
diff --git a/c/src/libchip/network/dwmac.c b/c/src/libchip/network/dwmac.c
deleted file mode 100644
index ddcf36530c..0000000000
--- a/c/src/libchip/network/dwmac.c
+++ /dev/null
@@ -1,2374 +0,0 @@
-/**
- * @file
- *
- * @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-2014 embedded brains GmbH. All rights reserved.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@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 <bsp.h>
-#include <bsp/fatal.h>
-#include <rtems/endian.h>
-#include "dwmac-common.h"
-#include "dwmac-core.h"
-
-#ifdef BSP_FEATURE_IRQ_EXTENSION
-#include <bsp/irq.h>
-#endif
-
-/* 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 64
-#define DWMAC_CONFIG_RX_UNIT_COUNT_MAX INT_MAX
-#define DWMAC_CONFIG_TX_UNIT_COUNT_DEFAULT 64
-#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
-
-#define DWMAC_GLOBAL_MBUF_CNT (rtems_bsdnet_config.mbuf_bytecount / sizeof(struct mbuf))
-#define DWMAG_GLOBAL_MCLUST_CNT (rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES)
-
-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->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->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_default( dwmac_common_context *self )
-{
- dwmac_core_enable_dma_irq_tx_default( self );
-}
-
-static inline void dwmac_enable_irq_tx_transmitted( dwmac_common_context *self )
-{
- dwmac_core_enable_dma_irq_tx_transmitted( self );
-}
-
-static inline void dwmac_disable_irq_rx( dwmac_common_context *self )
-{
- dwmac_core_disable_dma_irq_rx( self );
-}
-
-static inline void dwmac_disable_irq_tx_all( dwmac_common_context *self )
-{
- dwmac_core_disable_dma_irq_tx_all( self );
-}
-
-static inline void dwmac_disable_irq_tx_transmitted ( dwmac_common_context *self )
-{
- dwmac_core_disable_dma_irq_tx_transmitted( 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 );
- 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->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->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->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->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 " packet buffers regained from 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 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];
- 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;
-
- DWMAC_COMMON_DSB();
-
- 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;
- self->dmagrp->status = DMAGRP_STATUS_RU;
- }
-
- 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->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 );
-
- while( events != 0 ) {
- /* Handle a status change of the ethernet PHY */
- if ( ( events & DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE ) != 0 ) {
- events &= ~DWMAC_COMMON_EVENT_TX_PHY_STATUS_CHANGE;
- 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_disable_irq_tx_all( 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 */
- events = 0;
- continue;
- }
-
- /* Ininitialize / Re-initialize transmission handling */
- if ( ( events & DWMAC_COMMON_EVENT_TASK_INIT ) != 0 ) {
- events &= ~DWMAC_COMMON_EVENT_TASK_INIT;
- (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_enable_irq_tx_default( 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 ) {
- events &= ~DWMAC_COMMON_EVENT_TX_BUMP_UP_DMA_THRESHOLD;
- 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 ) {
- events &= ~DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED;
- dwmac_common_tx_frame_counts *counts = &self->stats.frame_counts_tx;
- dwmac_disable_irq_tx_transmitted( self );
-
- /* Next index to be transmitted */
- unsigned int idx_transmitted_next = dwmac_increment(
- idx_transmitted, INDEX_MAX );
-
- /* Free consumed fragments */
- if( idx_release != idx_transmitted_next
- && ( DESC_OPS->am_i_tx_owner )( self, idx_release ) ) {
- 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 );
- }
- 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;
- }
- } else {
- /* Clear transmit interrupt status */
- self->dmagrp->status = DMAGRP_STATUS_TI;
- /* Get re-activated by the next interrupt */
- dwmac_enable_irq_tx_transmitted( self );
- }
- }
-
- /* There are one or more frames to be transmitted. */
- if ( ( events & DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME ) != 0 ) {
- events &= ~DWMAC_COMMON_EVENT_TX_TRANSMIT_FRAME;
- 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" );
- events |= DWMAC_COMMON_EVENT_TX_FRAME_TRANSMITTED;
- }
-
- /* TODO: Add handling */
- }
-
- DWMAC_PRINT_DBG( "tx: enable transmit interrupts\n" );
- }
- }
-}
-
-/* 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 );
-
-#ifdef BSP_FEATURE_IRQ_EXTENSION
- /* Install interrupt handler */
- sc = rtems_interrupt_handler_install(
- self->CFG->IRQ_EMAC,
- "Ethernet",
- RTEMS_INTERRUPT_UNIQUE,
- dwmac_core_dma_interrupt,
- self
- );
-#else
- sc = RTEMS_NOT_IMPLEMENTED;
-#endif
- eno = rtems_status_code_to_errno( sc );
- }
-
- if ( eno == 0 ) {
- /* Start the ball rolling ... */
- eno = dwmac_control_request(
- self, self->task_id_tx, DWMAC_COMMON_EVENT_TASK_INIT );
- }
-
- if ( eno == 0 ) {
- eno = dwmac_control_request(
- self, self->task_id_rx, DWMAC_COMMON_EVENT_TASK_INIT );
- }
-
- 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 );
-#ifdef BSP_FEATURE_IRQ_EXTENSION
- (void) rtems_interrupt_handler_remove(
- self->CFG->IRQ_EMAC,
- dwmac_core_dma_interrupt,
- self
- );
-#endif
- (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 ) {
- eno = dwmac_control_request(
- self, self->task_id_tx, DWMAC_COMMON_EVENT_TASK_STOP );
- }
-
- if ( eno == 0 ) {
- eno = dwmac_control_request(
- self, self->task_id_rx, DWMAC_COMMON_EVENT_TASK_STOP );
- }
-
- if ( eno == 0 ) {
-#ifdef BSP_FEATURE_IRQ_EXTENSION
- sc = rtems_interrupt_handler_remove(
- self->CFG->IRQ_EMAC,
- dwmac_core_dma_interrupt,
- self
- );
-#else
- sc = RTEMS_NOT_IMPLEMENTED;
-#endif
- 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 {
- assert( gmii_clk_rate < DWCGNAC3504_CSR_F_300M );
- 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;
- const dwmac_ifconfig_drv_ctrl *drv_ctrl =
- (const dwmac_ifconfig_drv_ctrl *) bsd_config->drv_ctrl;
-
- 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;
-
- assert( driver_config->addr_gmac_regs != NULL );
- if ( driver_config->addr_gmac_regs != NULL ) {
- self->macgrp = driver_config->addr_gmac_regs;
-
- assert( driver_config->addr_dma_regs != NULL );
- 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 ) {
- if ( drv_ctrl == NULL ) {
- self->MDIO_BUS_ADDR = driver_config->MDIO_BUS_ADDR;
- } else {
- self->MDIO_BUS_ADDR = drv_ctrl->phy_addr;
- }
-
- assert( 32 >= self->MDIO_BUS_ADDR );
-
- if ( 32 < self->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
- );
-
- if (
- DWMAC_GLOBAL_MBUF_CNT / 4 < bsd_config->rbuf_count
- || DWMAG_GLOBAL_MCLUST_CNT / 4 < bsd_config->rbuf_count
- ) {
- bsp_fatal( DWMAC_FATAL_TOO_MANY_RBUFS_CONFIGURED );
- }
-
- /* 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->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->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;
-}