]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_A2F200_SoftConsole / MicroSemi_Code / drivers / mss_ethernet_mac / mss_ethernet_mac.c
diff --git a/FreeRTOS/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c b/FreeRTOS/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
new file mode 100644 (file)
index 0000000..4e92171
--- /dev/null
@@ -0,0 +1,1575 @@
+/***************************************************************************//**\r
+ * @file\r
+ * SmartFusion MSS Ethernet MAC driver implementation.\r
+ *\r
+ * (c) Copyright 2007 Actel Corporation\r
+ *\r
+ * SVN $Revision: 2369 $\r
+ * SVN $Date: 2010-03-01 18:31:45 +0000 (Mon, 01 Mar 2010) $\r
+ *\r
+ ******************************************************************************/\r
+\r
+/*\r
+ *\r
+ *\r
+ * NOTE:  This driver has been modified specifically for use with the* uIP stack.\r
+ * It is no longer a generic driver.\r
+ *\r
+ *\r
+ */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+#include "crc32.h"\r
+\r
+#include "mss_ethernet_mac.h"\r
+#include "mss_ethernet_mac_regs.h"\r
+#include "mss_ethernet_mac_desc.h"\r
+#include "mss_ethernet_mac_conf.h"\r
+#include "../../CMSIS/mss_assert.h"\r
+\r
+#include "phy.h"\r
+\r
+/**************************** INTERNAL DEFINES ********************************/\r
+\r
+#define MAC_CHECK(CHECK,ERRNO) \\r
+       {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); configASSERT((CHECK));}}\r
+\r
+/*\r
+ * Flags\r
+ */\r
+#define FLAG_MAC_INIT_DONE             1u\r
+#define FLAG_PERFECT_FILTERING 2u\r
+#define FLAG_CRC_DISABLE               4u\r
+#define FLAG_EXCEED_LIMIT              8u\r
+\r
+/*\r
+ * Return types\r
+ */\r
+#define MAC_OK                    0\r
+#define MAC_FAIL                  (-1)\r
+#define MAC_WRONG_PARAMETER       (-2)\r
+#define MAC_TOO_BIG_PACKET        (-3)\r
+#define MAC_BUFFER_IS_FULL        (-4)\r
+#define MAC_NOT_ENOUGH_SPACE      (-5)\r
+#define MAC_TIME_OUT                     (-6)\r
+#define MAC_TOO_SMALL_PACKET      (-7)\r
+\r
+/* Allocating this many buffers will always ensure there is one free as, even\r
+though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point\r
+to the same buffer. */\r
+#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE\r
+#define macBUFFER_SIZE 1488\r
+\r
+/***************************************************************/\r
+MAC_instance_t g_mss_mac;\r
+\r
+/**************************** INTERNAL DATA ***********************************/\r
+#define ERROR_MESSAGE_COUNT            8\r
+#define MAX_ERROR_MESSAGE_WIDTH 40\r
+static const int8_t unknown_error[] = "Unknown error";\r
+static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {\r
+       "No error occured",\r
+       "Method failed",\r
+       "Wrong parameter pased to function",\r
+       "Frame is too long",\r
+       "Not enough space in buffer",\r
+       "Not enough space in buffer",\r
+       "Timed out",\r
+       "Frame is too small"\r
+};\r
+\r
+/*\r
+ * Null variables\r
+ */\r
+static uint8_t*                NULL_buffer;\r
+static MSS_MAC_callback_t      NULL_callback;\r
+\r
+/* Declare the uip_buf as a pointer, rather than the traditional array, as this\r
+is a zero copy driver.  uip_buf just gets set to whichever buffer is being\r
+processed. */\r
+unsigned char *uip_buf = NULL;\r
+\r
+/**************************** INTERNAL FUNCTIONS ******************************/\r
+\r
+static int32_t MAC_dismiss_bad_frames( void );\r
+static int32_t MAC_send_setup_frame( void );\r
+\r
+static int32_t MAC_stop_transmission( void );\r
+static void            MAC_start_transmission( void );\r
+static int32_t MAC_stop_receiving( void );\r
+static void            MAC_start_receiving( void );\r
+\r
+static void            MAC_set_time_out( uint32_t time_out );\r
+static uint32_t        MAC_get_time_out( void );\r
+\r
+static void     MAC_memset(uint8_t *s, uint8_t c, uint32_t n);\r
+static void     MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);\r
+static void     MAC_memset_All(MAC_instance_t *s, uint32_t c);\r
+\r
+static unsigned char *MAC_obtain_buffer( void );\r
+static void MAC_release_buffer( unsigned char *pcBufferToRelease );\r
+\r
+#if( TX_RING_SIZE != 2 )\r
+       #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2\r
+#endif\r
+\r
+/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.\r
+The union is used for alignment only. */\r
+static union xMAC_BUFFERS\r
+{\r
+       unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */\r
+       unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];\r
+} xMACBuffers;\r
+\r
+/* Each array position indicates whether or not the buffer of the same index\r
+is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */\r
+static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };\r
+\r
+/***************************************************************************//**\r
+ * Initializes the Ethernet Controller.\r
+ * This function will prepare the Ethernet Controller for first time use in a\r
+ * given hardware/software configuration. This function should be called before\r
+ * any other Ethernet API functions are called.\r
+ *\r
+ * Initialization of registers - config registers, enable Tx/Rx interrupts,\r
+ * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address\r
+ * filter table (unicats/multicast)/hash init\r
+ */\r
+void\r
+MSS_MAC_init\r
+(\r
+       uint8_t phy_address\r
+)\r
+{\r
+    const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };\r
+    int32_t a;\r
+\r
+       /* To start with all buffers are free. */\r
+       for( a = 0; a < macNUM_BUFFERS; a++ )\r
+       {\r
+               ucMACBufferInUse[ a ] = pdFALSE;\r
+       }\r
+       \r
+    /* Try to reset chip */\r
+    MAC_BITBAND->CSR0_SWR = 1u;\r
+\r
+    do\r
+    {\r
+       vTaskDelay( 10 );\r
+    } while ( 1u == MAC_BITBAND->CSR0_SWR );\r
+\r
+    /* Check reset values of some registers to constrol\r
+     * base address validity */\r
+    configASSERT( MAC->CSR0 == 0xFE000000uL );\r
+    configASSERT( MAC->CSR5 == 0xF0000000uL );\r
+    configASSERT( MAC->CSR6 == 0x32000040uL );\r
+\r
+    /* Instance setup */\r
+    MAC_memset_All( &g_mss_mac, 0u );\r
+\r
+    g_mss_mac.base_address = MAC_BASE;\r
+    g_mss_mac.phy_address = phy_address;\r
+\r
+    for( a=0; a<RX_RING_SIZE; a++ )\r
+    {\r
+        /* Give the ownership to the MAC */\r
+        g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;\r
+        g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);\r
+               \r
+               /* Allocate a buffer to the descriptor, then mark the buffer as in use\r
+               (not free). */\r
+        g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );\r
+               ucMACBufferInUse[ a ] = pdTRUE;\r
+    }\r
+    g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;\r
+\r
+    for( a = 0; a < TX_RING_SIZE; a++ )\r
+    {\r
+               /* Buffers only get allocated to the Tx buffers when something is\r
+               actually tranmitted. */\r
+        g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL;\r
+    }\r
+    g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;\r
+\r
+    /* Configurable settings */\r
+    MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;\r
+    MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);\r
+    MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;\r
+    MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;\r
+\r
+    /* Fixed settings */\r
+    /* No space between descriptors */\r
+    MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;\r
+    /* General-purpose timer works in continuous mode */\r
+    MAC_BITBAND->CSR11_CON = 1u;\r
+    /* Start general-purpose */\r
+    MAC->CSR11 =  (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);\r
+\r
+       /* Ensure promiscous mode is off (it should be by default anyway). */\r
+       MAC_BITBAND->CSR6_PR = 0;\r
+       \r
+       /* Perfect filter. */\r
+       MAC_BITBAND->CSR6_HP = 1;\r
+       \r
+       /* Pass multcast. */\r
+       MAC_BITBAND->CSR6_PM = 1;\r
+       \r
+    /* Set descriptors */\r
+    MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);\r
+    MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);\r
+\r
+       /* enable normal interrupts */\r
+    MAC_BITBAND->CSR7_NIE = 1u;\r
+\r
+    /* Set default MAC address and reset mac filters */\r
+       MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );\r
+       MSS_MAC_set_mac_address((uint8_t *)mac_address);\r
+       \r
+    /* Detect PHY */\r
+    if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )\r
+    {\r
+       PHY_probe();\r
+       configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );\r
+    }\r
+\r
+    /* Reset PHY */\r
+    PHY_reset();\r
+\r
+       /* Configure chip according to PHY status */\r
+    MSS_MAC_auto_setup_link();\r
+       \r
+       /* Ensure uip_buf starts by pointing somewhere. */\r
+       uip_buf = MAC_obtain_buffer();  \r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Sets the configuration of the Ethernet Controller.\r
+ * After the EthernetInit function has been called, this API function can be\r
+ * used to configure the various features of the Ethernet Controller.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @param config        The logical OR of the following values:\r
+ *    - #MSS_MAC_CFG_RECEIVE_ALL\r
+ *    - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE\r
+ *    - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD\r
+ *    - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]\r
+ *    - #MSS_MAC_CFG_FULL_DUPLEX_MODE\r
+ *    - #MSS_MAC_CFG_PASS_ALL_MULTICAST\r
+ *    - #MSS_MAC_CFG_PROMISCUOUS_MODE\r
+ *    - #MSS_MAC_CFG_PASS_BAD_FRAMES\r
+ * @see   MAC_get_configuration()\r
+ */\r
+void\r
+MSS_MAC_configure\r
+(\r
+    uint32_t configuration\r
+)\r
+{\r
+    int32_t ret;\r
+\r
+    ret = MAC_stop_transmission();\r
+    configASSERT( ret == MAC_OK );\r
+\r
+    ret = MAC_stop_receiving();\r
+    configASSERT( ret == MAC_OK );\r
+\r
+    MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );\r
+    MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );\r
+    MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );\r
+\r
+    switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {\r
+    case MSS_MAC_CFG_THRESHOLD_CONTROL_00:\r
+        MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;\r
+        break;\r
+    case MSS_MAC_CFG_THRESHOLD_CONTROL_01:\r
+        MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );\r
+        break;\r
+    case MSS_MAC_CFG_THRESHOLD_CONTROL_10:\r
+        MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );\r
+        break;\r
+    case MSS_MAC_CFG_THRESHOLD_CONTROL_11:\r
+        MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );\r
+        break;\r
+    default:\r
+        break;\r
+    }\r
+    MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );\r
+    MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );\r
+    MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );\r
+    MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );\r
+    PHY_set_link_type( (uint8_t)\r
+        ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |\r
+        (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );\r
+\r
+    MSS_MAC_auto_setup_link();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Returns the configuration of the Ethernet Controller.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @return              The logical OR of the following values:\r
+ *    - #MSS_MAC_CFG_RECEIVE_ALL\r
+ *    - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE\r
+ *    - #MSS_MAC_CFG_STORE_AND_FORWARD\r
+ *    - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]\r
+ *    - #MSS_MAC_CFG_FULL_DUPLEX_MODE\r
+ *    - #MSS_MAC_CFG_PASS_ALL_MULTICAST\r
+ *    - #MSS_MAC_CFG_PROMISCUOUS_MODE\r
+ *    - #MSS_MAC_CFG_INVERSE_FILTERING\r
+ *    - #MSS_MAC_CFG_PASS_BAD_FRAMES\r
+ *    - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE\r
+ *    - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE\r
+ * @see   MAC_configure()\r
+ */\r
+int32_t\r
+MSS_MAC_get_configuration( void )\r
+{\r
+    uint32_t configuration;\r
+\r
+    configuration = 0u;\r
+    if( MAC_BITBAND->CSR6_RA != 0u ) {\r
+        configuration |= MSS_MAC_CFG_RECEIVE_ALL;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_TTM != 0u ) {\r
+        configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_SF != 0u ) {\r
+        configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;\r
+    }\r
+\r
+    switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {\r
+    case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;\r
+    case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;\r
+    case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;\r
+    default: break;\r
+    }\r
+    if( MAC_BITBAND->CSR6_FD != 0u ) {\r
+        configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_PM != 0u ) {\r
+        configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_PR != 0u ) {\r
+        configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_IF != 0u ) {\r
+        configuration |= MSS_MAC_CFG_INVERSE_FILTERING;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_PB != 0u ) {\r
+        configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_HO != 0u ) {\r
+        configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;\r
+    }\r
+\r
+    if( MAC_BITBAND->CSR6_HP != 0u ) {\r
+        configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;\r
+    }\r
+\r
+    return (int32_t)configuration;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+  Sends a packet from the uIP stack to the Ethernet Controller.\r
+  The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet\r
+  MAC. This function writes uip_len bytes of the packet contained in uip_buf into\r
+  the transmit FIFO and then activates the transmitter for this packet. If space\r
+  is available in the FIFO, the function will return once pac_len bytes of the\r
+  packet have been placed into the FIFO and the transmitter has been started.\r
+  This function will not wait for the transmission to complete.\r
+\r
+  @return\r
+    The function returns zero if a timeout occurs otherwise it returns size of the packet.\r
+\r
+  @see   MAC_rx_packet()\r
+ */\r
+\r
+int32_t\r
+MSS_MAC_tx_packet\r
+(\r
+    unsigned short usLength\r
+)\r
+{\r
+       uint32_t desc;\r
+       unsigned long ulDescriptor;\r
+    int32_t error = MAC_OK;\r
+\r
+    configASSERT( uip_buf != NULL_buffer );\r
+\r
+       configASSERT( usLength >= 12 );\r
+\r
+    if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )\r
+    {\r
+               configASSERT( usLength <= MSS_MAX_PACKET_SIZE );\r
+       }\r
+\r
+       taskENTER_CRITICAL();\r
+       {\r
+               /* Check both Tx descriptors are free, meaning the double send has completed. */\r
+               if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )\r
+               {\r
+                       error = MAC_BUFFER_IS_FULL;\r
+               }\r
+       }\r
+       taskEXIT_CRITICAL();\r
+\r
+       configASSERT( ( g_mss_mac.tx_desc_index == 0 ) );\r
+       \r
+       if( error == MAC_OK )\r
+       {\r
+               /* Ensure nothing is going to get sent until both descriptors are ready.\r
+               This is done to prevent a Tx end occurring prior to the second descriptor\r
+               being ready. */\r
+               MAC_BITBAND->CSR6_ST = 0u;\r
+\r
+               /* Assumed TX_RING_SIZE == 2.  A #error directive checks this is the\r
+               case. */\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
+                       {\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
+       \r
+                               if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
+                                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;\r
+                               }\r
+       \r
+                               /* Every buffer can hold a full frame so they are always first and last\r
+                                  descriptor */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;\r
+       \r
+                               /* set data size */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;\r
+       \r
+                               /* reset end of ring */\r
+                               g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
+       \r
+                               if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
+                               {\r
+                                       usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
+                               }\r
+       \r
+                               /* The data buffer is assigned to the Tx descriptor. */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;\r
+       \r
+                               /* update counters */\r
+                               desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;\r
+                               if( (desc & TDES0_LO) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_loss_of_carrier++;\r
+                               }\r
+                               if( (desc & TDES0_NC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_no_carrier++;\r
+                               }\r
+                               if( (desc & TDES0_LC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_late_collision++;\r
+                               }\r
+                               if( (desc & TDES0_EC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_excessive_collision++;\r
+                               }\r
+                               if( (desc & TDES0_UF) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_underflow_error++;\r
+                               }\r
+                               g_mss_mac.statistics.tx_collision_count +=\r
+                                       (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
+       \r
+                               /* Give ownership of descriptor to the MAC */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = TDES0_OWN;\r
+                               \r
+                               g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
+                       }               \r
+               }\r
+               taskEXIT_CRITICAL();\r
+    }\r
+       \r
+    if (error == MAC_OK)\r
+    {\r
+        error = (int32_t)usLength;\r
+               \r
+               /* Start sending now both descriptors are set up.  This is done to\r
+               prevent a Tx end occurring prior to the second descriptor being\r
+               ready. */\r
+               MAC_BITBAND->CSR6_ST = 1u;\r
+               MAC->CSR1 = 1u;\r
+               \r
+               /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.\r
+               Find anothere free buffer for uip_buf. */\r
+               uip_buf = MAC_obtain_buffer();\r
+    }\r
+    else\r
+    {\r
+        error = 0;\r
+    }\r
+    return ( error );\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Returns available packet size.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @return              size of packet, bigger than 0, if a packet is available.\r
+ *                      If not, returns 0.\r
+ * @see   MAC_rx_packet()\r
+ */\r
+int32_t\r
+MSS_MAC_rx_pckt_size\r
+(\r
+    void\r
+)\r
+{\r
+    int32_t retval;\r
+    MAC_dismiss_bad_frames();\r
+\r
+    if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &    RDES0_OWN) != 0u )\r
+    {\r
+       /* Current descriptor is empty */\r
+       retval = 0;\r
+    }\r
+    else\r
+    {\r
+        uint32_t frame_length;\r
+        frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;\r
+        retval = (int32_t)( frame_length );\r
+    }\r
+    return retval;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Receives a packet from the Ethernet Controller into the uIP stack.\r
+ * This function reads a packet from the receive FIFO of the controller and\r
+ * places it into uip_buf.\r
+\r
+ * @return              Size of packet if packet fits in uip_buf.\r
+ *                                         0 if there is no received packet.\r
+ * @see   MAC_rx_pckt_size()\r
+ * @see   MAC_tx_packet()\r
+ */\r
+int32_t\r
+MSS_MAC_rx_packet\r
+(\r
+       void\r
+)\r
+{\r
+       uint16_t frame_length=0u;\r
+\r
+    MAC_dismiss_bad_frames();\r
+\r
+    if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )\r
+    {\r
+        frame_length = ( (\r
+           g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
+           RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
+\r
+        /* strip crc */\r
+        frame_length -= 4u;\r
+\r
+        if( frame_length > macBUFFER_SIZE ) {\r
+               return MAC_NOT_ENOUGH_SPACE;\r
+        }\r
+\r
+               /* uip_buf is about to point to the buffer that contains the received\r
+               data, mark the buffer that uip_buf is currently pointing to as free\r
+               again. */\r
+               MAC_release_buffer( uip_buf );\r
+        uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;\r
+               \r
+               /* The buffer the Rx descriptor was pointing to is now in use by the\r
+               uIP stack - allocate a new buffer to the Rx descriptor. */\r
+               g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();\r
+\r
+        MSS_MAC_prepare_rx_descriptor();\r
+    }\r
+    return ((int32_t)frame_length);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Receives a packet from the Ethernet Controller.\r
+ * This function reads a packet from the receive FIFO of the controller and\r
+ * sets the address of pacData to the received data.\r
+ * If time_out parameter is zero the function will return\r
+ * immediately (after the copy operation if data is available. Otherwise the function\r
+ * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING\r
+ * value is given as time_out, function will wait for the reception to complete.\r
+ *\r
+  * @param pacData       The pointer to the packet data.\r
+ * @param time_out      Time out value in milli seconds for receiving.\r
+ *                                         if value is #MSS_MAC_BLOCKING, there will be no time out.\r
+ *                                         if value is #MSS_MAC_NONBLOCKING, function will return immediately\r
+ *                                         if there is no packet waiting.\r
+ *                                         Otherwise value must be greater than 0 and smaller than\r
+ *                                         0x01000000.\r
+ * @return              Size of packet if packet fits in pacData.\r
+ *                                         0 if there is no received packet.\r
+ * @see   MAC_rx_pckt_size()\r
+ * @see   MAC_tx_packet()\r
+ */\r
+int32_t\r
+MSS_MAC_rx_packet_ptrset\r
+(\r
+    uint8_t **pacData,\r
+    uint32_t time_out\r
+)\r
+{\r
+       uint16_t frame_length = 0u;\r
+    int8_t exit = 0;\r
+\r
+    configASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
+                       (time_out == MSS_MAC_NONBLOCKING) ||\r
+                       ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
+\r
+    MAC_dismiss_bad_frames();\r
+\r
+    /* wait for a packet */\r
+       if( time_out != MSS_MAC_BLOCKING ) {\r
+               if( time_out == MSS_MAC_NONBLOCKING ) {\r
+               MAC_set_time_out( 0u );\r
+               } else {\r
+               MAC_set_time_out( time_out );\r
+               }\r
+       }\r
+\r
+    while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
+       RDES0_OWN) != 0u) && (exit == 0) )\r
+    {\r
+       if( time_out != MSS_MAC_BLOCKING )\r
+       {\r
+               if( MAC_get_time_out() == 0u ) {\r
+                       exit = 1;\r
+               }\r
+       }\r
+    }\r
+\r
+    if(exit == 0)\r
+    {\r
+        frame_length = ( (\r
+           g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
+           RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
+\r
+        /* strip crc */\r
+        frame_length -= 4u;\r
+\r
+       /* Here we are setting the buffer 'pacData' address to the address\r
+          RX descriptor address. After this is called, the following function\r
+          must be called 'MAC_prepare_rx_descriptor'\r
+          to prepare the current rx descriptor for receiving the next packet.\r
+       */\r
+       *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;\r
+\r
+    }\r
+    return ((int32_t)frame_length);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Returns the status of connection.\r
+ *\r
+ * @return              the logical OR of the following values:\r
+ *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
+ *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
+ *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
+ * @see   MAC_auto_setup_link()\r
+ */\r
+int32_t\r
+MSS_MAC_link_status\r
+(\r
+    void\r
+)\r
+{\r
+       uint32_t link;\r
+\r
+    link = PHY_link_status();\r
+    if( link == MSS_MAC_LINK_STATUS_LINK ) {\r
+       link |= PHY_link_type();\r
+    }\r
+\r
+    return ((int32_t)link);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Setups the link between PHY and MAC and returns the status of connection.\r
+ *\r
+ * @return              the logical OR of the following values:\r
+ *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
+ *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
+ *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
+ * @see   MAC_link_status()\r
+ */\r
+int32_t\r
+MSS_MAC_auto_setup_link\r
+(\r
+    void\r
+)\r
+{\r
+       int32_t link;\r
+\r
+    PHY_auto_negotiate();\r
+\r
+    link = MSS_MAC_link_status();\r
+\r
+    if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {\r
+       int32_t ret;\r
+           ret = MAC_stop_transmission();\r
+           MAC_CHECK( ret == MAC_OK, ret );\r
+\r
+           ret = MAC_stop_receiving();\r
+           MAC_CHECK( ret == MAC_OK, ret );\r
+        MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );\r
+        MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );\r
+           MAC_start_transmission();\r
+           MAC_start_receiving();\r
+    }\r
+\r
+    return link;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Sets mac address. New address must be unicast.\r
+ *\r
+ * @param new_address   Pointer to a MAC_instance_t structure\r
+ * @see   MAC_get_mac_address()\r
+ */\r
+void\r
+MSS_MAC_set_mac_address\r
+(\r
+    const uint8_t *new_address\r
+)\r
+{\r
+    /* Check if the new address is unicast */\r
+    configASSERT( (new_address[0]&1) == 0 );\r
+\r
+       MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );\r
+\r
+       if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
+               int32_t a;\r
+               /* set unused filters to the new mac address */\r
+               for( a=14*6; a>=0; a-=6 ) {\r
+                       if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {\r
+                               /* Filters with multicast addresses are used */\r
+                               a = -1;\r
+                       } else {\r
+                               MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),\r
+                                       g_mss_mac.mac_address, 6u );\r
+                       }\r
+               }\r
+       }\r
+\r
+       MAC_send_setup_frame();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Returns mac address.\r
+ *\r
+ * @param address       Pointer to receive the MAC address\r
+ * @see   MAC_set_mac_address()\r
+ */\r
+void\r
+MSS_MAC_get_mac_address\r
+(\r
+    uint8_t *address\r
+)\r
+{\r
+       MAC_memcpy( address, g_mss_mac.mac_address, 6u );\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Sets mac address filters. Addresses must be multicast.\r
+ *\r
+ * @param filter_count  number of addresses\r
+ * @param filters       Pointer to addresses to be filtered\r
+ */\r
+void\r
+MSS_MAC_set_mac_filters\r
+(\r
+       uint16_t filter_count,\r
+       const uint8_t *filters\r
+)\r
+{\r
+    configASSERT( (filter_count==0) || (filters != NULL_buffer) );\r
+    /* Check if the mac addresses is multicast */\r
+    {\r
+       int32_t a;\r
+       for( a = 0u; a < filter_count; a++ ) {\r
+               configASSERT( (filters[a*6]&1) == 1 );\r
+       }\r
+    }\r
+\r
+    if( filter_count <= 15 ){\r
+       int32_t a;\r
+       g_mss_mac.flags |= FLAG_PERFECT_FILTERING;\r
+\r
+       /* copy new filters */\r
+       MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));\r
+\r
+       /* set unused filters to our mac address */\r
+       for( a=filter_count; a<15; a++ ) {\r
+                       MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),\r
+                               g_mss_mac.mac_address, 6 );\r
+       }\r
+    } else {\r
+       int32_t a,b;\r
+       uint32_t hash;\r
+\r
+       g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;\r
+\r
+       /* reset hash table */\r
+       MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );\r
+\r
+       for( a=0, b=0; a<filter_count; a++, b+=6 ) {\r
+               hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;\r
+               g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);\r
+       }\r
+    }\r
+\r
+    MAC_send_setup_frame();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * MAC interrupt service routine.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @see   MAC_set_callback()\r
+ */\r
+#if defined(__GNUC__)\r
+__attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )\r
+#else\r
+void EthernetMAC_IRQHandler( void )\r
+#endif\r
+{\r
+    uint32_t events;\r
+    uint32_t intr_status;\r
+\r
+    events = 0u;\r
+    intr_status = MAC->CSR5;\r
+\r
+    if( (intr_status & CSR5_NIS_MASK) != 0u ) {\r
+       if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */\r
+               g_mss_mac.statistics.tx_interrupts++;\r
+               events |= MSS_MAC_EVENT_PACKET_SEND;\r
+       }\r
+\r
+       if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */\r
+               g_mss_mac.statistics.rx_interrupts++;\r
+               events |= MSS_MAC_EVENT_PACKET_RECEIVED;\r
+       }\r
+    }\r
+\r
+    /* Clear interrupts */\r
+    MAC->CSR5 = CSR5_INT_BITS;\r
+\r
+    if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {\r
+        g_mss_mac.listener( events );\r
+    }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Sets MAC event listener.\r
+ * Sets the given event listener function to be triggered inside MAC_isr().\r
+ * Assigning NULL pointer as the listener function will disable it.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @param listener      function pointer to a MAC_callback_t function\r
+ * @return              #MAC_OK if everything is OK\r
+ *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
+ *                                             initialized.\r
+ * @see   MAC_isr()\r
+ */\r
+void\r
+MSS_MAC_set_callback\r
+(\r
+    MSS_MAC_callback_t listener\r
+)\r
+{\r
+       /* disable tx and rx interrupts */\r
+    MAC_BITBAND->CSR7_RIE = 0u;\r
+    MAC_BITBAND->CSR7_TIE = 0u;\r
+\r
+    g_mss_mac.listener = listener;\r
+\r
+       if( listener != NULL_callback ) {\r
+               /* enable tx and rx interrupts */\r
+        MAC_BITBAND->CSR7_RIE = 1u;\r
+        MAC_BITBAND->CSR7_TIE = 1u;\r
+       }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Returns description of last error.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @return              A string describing the error. This string must not be\r
+ *                                             modified by the application.\r
+ *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
+ *                      initialized.\r
+ */\r
+const int8_t*\r
+MSS_MAC_last_error\r
+(\r
+    void\r
+)\r
+{\r
+       int8_t error_msg_nb;\r
+    const int8_t* returnvalue;\r
+\r
+       error_msg_nb = -(g_mss_mac.last_error);\r
+       if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {\r
+               returnvalue = unknown_error;\r
+       } else {\r
+               returnvalue = ErrorMessages[error_msg_nb];\r
+       }\r
+       return returnvalue;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Returns statistics counter of stat_id identifier.\r
+ *\r
+ * @param instance      Pointer to a MAC_instance_t structure\r
+ * @param stat_id              Identifier of statistics counter.\r
+ * @return                             Statistics counter of stat_id identifier.\r
+ *                                             On error returns 0.\r
+ */\r
+uint32_t\r
+MSS_MAC_get_statistics\r
+(\r
+    mss_mac_statistics_id_t stat_id\r
+)\r
+{\r
+    uint32_t returnval = 0u;\r
+\r
+       switch( stat_id ) {\r
+       case MSS_MAC_RX_INTERRUPTS:\r
+               returnval = g_mss_mac.statistics.rx_interrupts;\r
+        break;\r
+       case MSS_MAC_RX_FILTERING_FAIL:\r
+               returnval = g_mss_mac.statistics.rx_filtering_fail;\r
+        break;\r
+       case MSS_MAC_RX_DESCRIPTOR_ERROR:\r
+               returnval = g_mss_mac.statistics.rx_descriptor_error;\r
+        break;\r
+       case MSS_MAC_RX_RUNT_FRAME:\r
+               returnval = g_mss_mac.statistics.rx_runt_frame;\r
+        break;\r
+       case MSS_MAC_RX_NOT_FIRST:\r
+               returnval = g_mss_mac.statistics.rx_not_first;\r
+        break;\r
+       case MSS_MAC_RX_NOT_LAST:\r
+               returnval = g_mss_mac.statistics.rx_not_last;\r
+        break;\r
+       case MSS_MAC_RX_FRAME_TOO_LONG:\r
+               returnval = g_mss_mac.statistics.rx_frame_too_long;\r
+        break;\r
+       case MSS_MAC_RX_COLLISION_SEEN:\r
+               returnval = g_mss_mac.statistics.rx_collision_seen;\r
+        break;\r
+       case MSS_MAC_RX_CRC_ERROR:\r
+               returnval = g_mss_mac.statistics.rx_crc_error;\r
+        break;\r
+       case MSS_MAC_RX_FIFO_OVERFLOW:\r
+               returnval = g_mss_mac.statistics.rx_fifo_overflow;\r
+        break;\r
+       case MSS_MAC_RX_MISSED_FRAME:\r
+               returnval = g_mss_mac.statistics.rx_missed_frame;\r
+        break;\r
+       case MSS_MAC_TX_INTERRUPTS:\r
+               returnval = g_mss_mac.statistics.tx_interrupts;\r
+        break;\r
+       case MSS_MAC_TX_LOSS_OF_CARRIER:\r
+               returnval = g_mss_mac.statistics.tx_loss_of_carrier;\r
+        break;\r
+       case MSS_MAC_TX_NO_CARRIER:\r
+               returnval = g_mss_mac.statistics.tx_no_carrier;\r
+        break;\r
+       case MSS_MAC_TX_LATE_COLLISION:\r
+               returnval = g_mss_mac.statistics.tx_late_collision;\r
+        break;\r
+       case MSS_MAC_TX_EXCESSIVE_COLLISION:\r
+               returnval = g_mss_mac.statistics.tx_excessive_collision;\r
+        break;\r
+       case MSS_MAC_TX_COLLISION_COUNT:\r
+               returnval = g_mss_mac.statistics.tx_collision_count;\r
+        break;\r
+       case MSS_MAC_TX_UNDERFLOW_ERROR:\r
+               returnval = g_mss_mac.statistics.tx_underflow_error;\r
+        break;\r
+    default:\r
+        break;\r
+       }\r
+\r
+       return returnval;\r
+}\r
+\r
+\r
+/**************************** INTERNAL FUNCTIONS ******************************/\r
+\r
+\r
+/***************************************************************************//**\r
+ * Prepares current rx descriptor for receiving.\r
+ */\r
+void\r
+MSS_MAC_prepare_rx_descriptor\r
+(\r
+    void\r
+)\r
+{\r
+       uint32_t desc;\r
+\r
+       /* update counters */\r
+       desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;\r
+       if( (desc & RDES0_FF) != 0u ) {\r
+               g_mss_mac.statistics.rx_filtering_fail++;\r
+       }\r
+       if( (desc & RDES0_DE) != 0u ) {\r
+               g_mss_mac.statistics.rx_descriptor_error++;\r
+       }\r
+       if( (desc & RDES0_RF) != 0u ) {\r
+               g_mss_mac.statistics.rx_runt_frame++;\r
+       }\r
+       if( (desc & RDES0_FS) == 0u ) {\r
+               g_mss_mac.statistics.rx_not_first++;\r
+       }\r
+       if( (desc & RDES0_LS) == 0u ) {\r
+               g_mss_mac.statistics.rx_not_last++;\r
+       }\r
+       if( (desc & RDES0_TL) != 0u ) {\r
+               g_mss_mac.statistics.rx_frame_too_long++;\r
+       }\r
+       if( (desc & RDES0_CS) != 0u ) {\r
+               g_mss_mac.statistics.rx_collision_seen++;\r
+       }\r
+       if( (desc & RDES0_CE) != 0u ) {\r
+               g_mss_mac.statistics.rx_crc_error++;\r
+       }\r
+\r
+       desc = MAC->CSR8;\r
+       g_mss_mac.statistics.rx_fifo_overflow +=\r
+               (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;\r
+       g_mss_mac.statistics.rx_missed_frame +=\r
+               (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));\r
+\r
+       /* Give ownership of descriptor to the MAC */\r
+       g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 = RDES0_OWN;\r
+       g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;\r
+\r
+       /* Start receive */\r
+    MAC_start_receiving();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Prepares a setup frame and sends it to MAC.\r
+ * This function is blocking.\r
+ * @return             #MAC_OK if everything is ok.\r
+ *                             #MAC_TIME_OUT if timed out before packet send.\r
+ */\r
+static int32_t\r
+MAC_send_setup_frame\r
+(\r
+    void\r
+)\r
+{\r
+       volatile MAC_descriptor_t descriptor;\r
+       uint8_t frame_data[192];\r
+       uint8_t *data;\r
+       int32_t a,b,c,d;\r
+       int32_t ret;\r
+\r
+    /* prepare descriptor */\r
+       descriptor.descriptor_0 = TDES0_OWN;\r
+       descriptor.descriptor_1 = TDES1_SET | TDES1_TER |\r
+               (sizeof(frame_data) << TDES1_TBS1_OFFSET);\r
+\r
+       if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {\r
+               descriptor.descriptor_1 |= TDES1_FT0;\r
+       }\r
+\r
+       descriptor.buffer_1 = (uint32_t)frame_data;\r
+       descriptor.buffer_2 = 0u;\r
+\r
+    /* prepare frame */\r
+    if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
+       b = 0;\r
+       d = 12;\r
+       c = 90;\r
+    } else {\r
+       b = 156;\r
+       d = 0;\r
+       c = 64;\r
+    }\r
+\r
+       data = g_mss_mac.mac_address;\r
+       frame_data[b] = data[0];\r
+       frame_data[b+1] = data[1];\r
+       frame_data[b+4] = data[2];\r
+       frame_data[b+5] = data[3];\r
+       frame_data[b+8] = data[4];\r
+       frame_data[b+9] = data[5];\r
+\r
+       data = g_mss_mac.mac_filter_data;\r
+    for( a = 0; a < c; ) {\r
+               frame_data[d] = data[a++];\r
+               frame_data[d+1] = data[a++];\r
+               frame_data[d+4] = data[a++];\r
+               frame_data[d+5] = data[a++];\r
+               frame_data[d+8] = data[a++];\r
+               frame_data[d+9] = data[a++];\r
+               d += 12;\r
+       }\r
+\r
+       /* Stop transmission */\r
+    ret = MAC_stop_transmission();\r
+    configASSERT( ret == MAC_OK );\r
+\r
+    ret = MAC_stop_receiving();\r
+    configASSERT( ret == MAC_OK );\r
+\r
+    /* Set descriptor */\r
+    MAC->CSR4 = (uint32_t)&descriptor;\r
+\r
+       /* Start transmission */\r
+    MAC_start_transmission();\r
+\r
+    /* Wait until transmission over */\r
+    ret = MAC_OK;\r
+    MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );\r
+\r
+    while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
+       CSR5_TS_SUSPENDED) && (MAC_OK == ret) )\r
+    {\r
+       /* transmit poll demand */\r
+       MAC->CSR1 = 1u;\r
+       if( MAC_get_time_out() == 0u ) {\r
+               ret = MAC_TIME_OUT;\r
+       }\r
+    }\r
+\r
+       MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );\r
+\r
+    /* Set tx descriptor */\r
+    MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;\r
+\r
+    /* Start receiving and transmission */\r
+    MAC_start_receiving();\r
+    MAC_start_transmission();\r
+\r
+    return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Stops transmission.\r
+ * Function will wait until transmit operation enters stop state.\r
+ *\r
+ * @return                     #MAC_OK if everything is ok.\r
+ *                                     #MAC_TIME_OUT if timed out.\r
+ */\r
+static int32_t\r
+MAC_stop_transmission\r
+(\r
+    void\r
+)\r
+{\r
+    int32_t retval = MAC_OK;\r
+    MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
+\r
+       while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
+               CSR5_TS_STOPPED) && (retval == MAC_OK) )\r
+       {\r
+       MAC_BITBAND->CSR6_ST = 0u;\r
+       if( MAC_get_time_out() == 0u ) {\r
+               retval = MAC_TIME_OUT;\r
+       }\r
+       }\r
+       return retval;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Starts transmission.\r
+ */\r
+static void\r
+MAC_start_transmission\r
+(\r
+    void\r
+)\r
+{\r
+    MAC_BITBAND->CSR6_ST = 1u;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Stops transmission.\r
+ * Function will wait until transmit operation enters stop state.\r
+ *\r
+ * @return                     #MAC_OK if everything is ok.\r
+ *                                     #MAC_TIME_OUT if timed out.\r
+ */\r
+static int32_t\r
+MAC_stop_receiving\r
+(\r
+    void\r
+)\r
+{\r
+    int32_t retval = MAC_OK;\r
+    MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
+\r
+       while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)\r
+            && (retval == MAC_OK) )\r
+       {\r
+       MAC_BITBAND->CSR6_SR = 0u;\r
+       if( MAC_get_time_out() == 0u ) {\r
+               retval = MAC_TIME_OUT;\r
+       }\r
+       }\r
+\r
+       return retval;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Starts transmission.\r
+ */\r
+static void\r
+MAC_start_receiving\r
+(\r
+    void\r
+)\r
+{\r
+    MAC_BITBAND->CSR6_SR = 1u;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * Dismisses bad frames.\r
+ *\r
+ * @return             dismissed frame count.\r
+ */\r
+static int32_t\r
+MAC_dismiss_bad_frames\r
+(\r
+    void\r
+)\r
+{\r
+       int32_t dc = 0;\r
+       int8_t cont = 1;\r
+\r
+       if( MAC_BITBAND->CSR6_PB != 0u ) {\r
+               /* User wants bad frames too, don't dismiss anything */\r
+               cont = 0;\r
+       }\r
+\r
+       while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
+            RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */\r
+    {\r
+       /* check error summary */\r
+       if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
+               (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )\r
+       {\r
+               MSS_MAC_prepare_rx_descriptor();\r
+               dc++;\r
+       }\r
+        else\r
+        {\r
+               cont = 0;\r
+       }\r
+    }\r
+\r
+       return dc;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Sets time out value.\r
+ * #MAC_get_time_out must be called frequently to make time out value updated.\r
+ * Because of user may not be using ISR, we can not update time out in ISR.\r
+ *\r
+ * @time_out   time out value in milli seconds.\r
+ *                             Must be smaller than 0x01000000.\r
+ */\r
+static void\r
+MAC_set_time_out\r
+(\r
+    uint32_t time_out\r
+)\r
+{\r
+       g_mss_mac.time_out_value = (time_out * 122u) / 10u;\r
+\r
+       g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Returns time out value.\r
+ *\r
+ * @return             timer out value in milli seconds.\r
+ */\r
+static uint32_t\r
+MAC_get_time_out\r
+(\r
+    void\r
+)\r
+{\r
+       uint32_t timer;\r
+       uint32_t time = 0u;\r
+\r
+       timer = ( MAC->CSR11 & CSR11_TIM_MASK );\r
+\r
+       if( timer > g_mss_mac.last_timer_value ) {\r
+               time = 0x0000ffffUL;\r
+       }\r
+       time += g_mss_mac.last_timer_value - timer;\r
+\r
+       if( MAC_BITBAND->CSR6_TTM == 0u ) {\r
+               time *= 10u;\r
+       }\r
+       if( g_mss_mac.time_out_value <= time ){\r
+               g_mss_mac.time_out_value = 0u;\r
+       } else {\r
+               g_mss_mac.time_out_value -= time;\r
+       }\r
+\r
+       g_mss_mac.last_timer_value = (uint16_t)timer;\r
+\r
+       return ((g_mss_mac.time_out_value * 10u) / 122u);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Fills the first n bytes of the memory area pointed to by s with the constant\r
+ * byte c.\r
+ */\r
+static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)\r
+{\r
+    uint8_t *sb = s;\r
+\r
+    while( n > 0u ) {\r
+       n--;\r
+        sb[n] = c;\r
+    }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Fills all fields of MAC_instance_t with c.\r
+ *\r
+ * @return          a pointer to the given MAC_instance_t s.\r
+ */\r
+static void MAC_memset_All(MAC_instance_t *s, uint32_t c)\r
+{\r
+    int32_t count;\r
+    s->base_address = (addr_t)c;\r
+    s->flags = (uint8_t)c;\r
+    s->last_error = (int8_t)c;\r
+    s->last_timer_value = (uint16_t)c;\r
+    s->listener = NULL_callback;\r
+       MAC_memset( s->mac_address, (uint8_t)c, 6u );\r
+       MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );\r
+    s->phy_address = (uint8_t)c;\r
+    s->rx_desc_index =c;\r
+    for(count = 0; count<RX_RING_SIZE ;count++)\r
+    {\r
+        s->rx_descriptors[count].buffer_1 = c;\r
+        s->rx_descriptors[count].buffer_2 = c;\r
+        s->rx_descriptors[count].descriptor_0 = c;\r
+        s->rx_descriptors[count].descriptor_1 = c;\r
+    }\r
+    s->statistics.rx_collision_seen =c;\r
+    s->statistics.rx_crc_error = c;\r
+    s->statistics.rx_descriptor_error = c;\r
+    s->statistics.rx_fifo_overflow = c;\r
+    s->statistics.rx_filtering_fail = c;\r
+    s->statistics.rx_frame_too_long = c;\r
+    s->statistics.rx_interrupts = c;\r
+    s->statistics.rx_missed_frame = c;\r
+    s->statistics.rx_not_first = c;\r
+    s->statistics.rx_not_last = c;\r
+    s->statistics.rx_runt_frame = c;\r
+    s->statistics.tx_collision_count = c;\r
+    s->statistics.tx_excessive_collision = c;\r
+    s->statistics.tx_interrupts = c;\r
+    s->statistics.tx_late_collision = c;\r
+    s->statistics.tx_loss_of_carrier = c;\r
+    s->statistics.tx_no_carrier = c;\r
+    s->statistics.tx_underflow_error = c;\r
+    s->time_out_value = c;\r
+    s->tx_desc_index = c;\r
+    for(count = 0; count < TX_RING_SIZE ;count++)\r
+    {\r
+        s->tx_descriptors[count].buffer_1 = c;\r
+        s->tx_descriptors[count].buffer_2 = c;\r
+        s->tx_descriptors[count].descriptor_0 = c;\r
+        s->tx_descriptors[count].descriptor_1 = c;\r
+    }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Copies n bytes from memory area src to memory area dest.\r
+ * The memory areas should not overlap.\r
+ *\r
+ * @return          a pointer to the memory area dest.\r
+ */\r
+static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)\r
+{\r
+    uint8_t *d = dest;\r
+\r
+    while( n > 0u ) {\r
+       n--;\r
+        d[n] = src[n];\r
+    }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Tx has completed, mark the buffers that were assigned to the Tx descriptors\r
+ * as free again.\r
+ *\r
+ */\r
+void MSS_MAC_FreeTxBuffers( void )\r
+{\r
+       /* Check the buffers have not already been freed in the first of the\r
+       two Tx interrupts - which could potentially happen if the second Tx completed\r
+       during the interrupt for the first Tx. */\r
+       if( g_mss_mac.tx_descriptors[ 0 ].buffer_1 != ( uint32_t ) NULL )\r
+       {\r
+               if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )\r
+               {\r
+                       configASSERT( g_mss_mac.tx_descriptors[ 0 ].buffer_1 == g_mss_mac.tx_descriptors[ 1 ].buffer_1 );\r
+                       MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );\r
+                       \r
+                       /* Just to mark the fact that the buffer has already been released. */\r
+                       g_mss_mac.tx_descriptors[ 0 ].buffer_1 = ( uint32_t ) NULL;\r
+               }\r
+       }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Look through the array of buffers until one is found that is free for use -\r
+ * that is, not currently assigned to an Rx or a Tx descriptor.  Mark the buffer\r
+ * as in use, then return its address.\r
+ *\r
+ * @return          a pointer to a free buffer.\r
+ */\r
+unsigned char *MAC_obtain_buffer( void )\r
+{\r
+long lIndex, lAttempt = 0, lDescriptor, lBufferIsInUse;\r
+unsigned char *pcReturn = NULL;\r
+unsigned char *pcBufferAddress;\r
+\r
+       /* Find and return the address of a buffer that is not being used.  Mark\r
+       the buffer as now in use. */\r
+       while( ( lAttempt <= 1 ) && ( pcReturn == NULL ) )\r
+       {\r
+               for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+               {\r
+                       if( ucMACBufferInUse[ lIndex ] == pdFALSE )\r
+                       {\r
+                               pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
+                               ucMACBufferInUse[ lIndex ] = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+               \r
+               if( pcReturn == NULL )\r
+               {\r
+                       /* Did not find a buffer.  That should not really happen, but could if\r
+                       an interrupt was missed.  See if any buffers are marked as in use, but\r
+                       are not actually in use. */\r
+                       for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+                       {\r
+                               pcBufferAddress = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
+                               lBufferIsInUse = pdFALSE;\r
+                               \r
+                               /* Is the buffer used by an Rx descriptor? */\r
+                               for( lDescriptor = 0; lDescriptor < RX_RING_SIZE; lDescriptor++ )\r
+                               {\r
+                                       if( g_mss_mac.rx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )\r
+                                       {\r
+                                               /* The buffer is in use by an Rx descriptor. */\r
+                                               lBufferIsInUse = pdTRUE;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               \r
+                               if( lBufferIsInUse != pdTRUE )\r
+                               {\r
+                                       /* Is the buffer used by an Tx descriptor? */\r
+                                       for( lDescriptor = 0; lDescriptor < TX_RING_SIZE; lDescriptor++ )\r
+                                       {\r
+                                               if( g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )\r
+                                               {\r
+                                                       /* The buffer is in use by an Tx descriptor. */\r
+                                                       lBufferIsInUse = pdTRUE;\r
+                                                       break;\r
+                                               }\r
+                                       }                       \r
+                               }\r
+                               \r
+                               /* If the buffer was not found to be in use by either a Tx or an\r
+                               Rx descriptor, but the buffer is marked as in use, then mark the\r
+                               buffer to be in it's correct state of "not in use". */\r
+                               if( ( lBufferIsInUse == pdFALSE ) && ( ucMACBufferInUse[ lIndex ] == pdTRUE ) )\r
+                               {\r
+                                       ucMACBufferInUse[ lIndex ] = pdFALSE;\r
+                               }\r
+                       }\r
+               }\r
+                                                                                                                                       \r
+               /* If any buffer states were changed it might be that a buffer can now\r
+               be obtained.  Try again, but only one more time. */\r
+               lAttempt++;\r
+       }\r
+       \r
+       configASSERT( pcReturn );\r
+       return pcReturn;\r
+}\r
+\r
+/***************************************************************************//**\r
+ * Return a buffer to the list of free buffers, it was in use, but is not now.\r
+ *\r
+ */\r
+void MAC_release_buffer( unsigned char *pucBufferToRelease )\r
+{\r
+long lIndex;\r
+\r
+       /* uip_buf is going to point to a different buffer - first ensure the buffer\r
+       it is currently pointing to is marked as being free again. */\r
+       for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+       {\r
+               if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )\r
+               {\r
+                       /* This is the buffer in use, mark it as being free. */\r
+                       ucMACBufferInUse[ lIndex ] = pdFALSE;\r
+                       break;\r
+               }\r
+       }\r
+       \r
+       configASSERT( lIndex < macNUM_BUFFERS );\r
+}\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+/******************************** END OF FILE *********************************/\r
+\r