1 /***************************************************************************//**
\r
3 * SmartFusion MSS Ethernet MAC driver implementation.
\r
5 * (c) Copyright 2007 Actel Corporation
\r
7 * SVN $Revision: 2369 $
\r
8 * SVN $Date: 2010-03-01 18:31:45 +0000 (Mon, 01 Mar 2010) $
\r
10 ******************************************************************************/
\r
15 * NOTE: This driver has been modified specifically for use with the* uIP stack.
\r
16 * It is no longer a generic driver.
\r
25 #include "FreeRTOS.h"
\r
30 #include "mss_ethernet_mac.h"
\r
31 #include "mss_ethernet_mac_regs.h"
\r
32 #include "mss_ethernet_mac_desc.h"
\r
33 #include "mss_ethernet_mac_conf.h"
\r
34 #include "../../CMSIS/mss_assert.h"
\r
38 /**************************** INTERNAL DEFINES ********************************/
\r
40 #define MAC_CHECK(CHECK,ERRNO) \
\r
41 {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); configASSERT((CHECK));}}
\r
46 #define FLAG_MAC_INIT_DONE 1u
\r
47 #define FLAG_PERFECT_FILTERING 2u
\r
48 #define FLAG_CRC_DISABLE 4u
\r
49 #define FLAG_EXCEED_LIMIT 8u
\r
55 #define MAC_FAIL (-1)
\r
56 #define MAC_WRONG_PARAMETER (-2)
\r
57 #define MAC_TOO_BIG_PACKET (-3)
\r
58 #define MAC_BUFFER_IS_FULL (-4)
\r
59 #define MAC_NOT_ENOUGH_SPACE (-5)
\r
60 #define MAC_TIME_OUT (-6)
\r
61 #define MAC_TOO_SMALL_PACKET (-7)
\r
63 /* Allocating this many buffers will always ensure there is one free as, even
\r
64 though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
\r
65 to the same buffer. */
\r
66 #define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE
\r
67 #define macBUFFER_SIZE 1488
\r
69 /***************************************************************/
\r
70 MAC_instance_t g_mss_mac;
\r
72 /**************************** INTERNAL DATA ***********************************/
\r
73 #define ERROR_MESSAGE_COUNT 8
\r
74 #define MAX_ERROR_MESSAGE_WIDTH 40
\r
75 static const int8_t unknown_error[] = "Unknown error";
\r
76 static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
\r
79 "Wrong parameter pased to function",
\r
80 "Frame is too long",
\r
81 "Not enough space in buffer",
\r
82 "Not enough space in buffer",
\r
84 "Frame is too small"
\r
90 static uint8_t* NULL_buffer;
\r
91 static MSS_MAC_callback_t NULL_callback;
\r
93 /* Declare the uip_buf as a pointer, rather than the traditional array, as this
\r
94 is a zero copy driver. uip_buf just gets set to whichever buffer is being
\r
96 unsigned char *uip_buf = NULL;
\r
98 /**************************** INTERNAL FUNCTIONS ******************************/
\r
100 static int32_t MAC_dismiss_bad_frames( void );
\r
101 static int32_t MAC_send_setup_frame( void );
\r
103 static int32_t MAC_stop_transmission( void );
\r
104 static void MAC_start_transmission( void );
\r
105 static int32_t MAC_stop_receiving( void );
\r
106 static void MAC_start_receiving( void );
\r
108 static void MAC_set_time_out( uint32_t time_out );
\r
109 static uint32_t MAC_get_time_out( void );
\r
111 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n);
\r
112 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);
\r
113 static void MAC_memset_All(MAC_instance_t *s, uint32_t c);
\r
115 static unsigned char *MAC_obtain_buffer( void );
\r
116 static void MAC_release_buffer( unsigned char *pcBufferToRelease );
\r
118 #if( TX_RING_SIZE != 2 )
\r
119 #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2
\r
122 /* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.
\r
123 The union is used for alignment only. */
\r
124 static union xMAC_BUFFERS
\r
126 unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */
\r
127 unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
\r
130 /* Each array position indicates whether or not the buffer of the same index
\r
131 is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */
\r
132 static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
\r
134 /***************************************************************************//**
\r
135 * Initializes the Ethernet Controller.
\r
136 * This function will prepare the Ethernet Controller for first time use in a
\r
137 * given hardware/software configuration. This function should be called before
\r
138 * any other Ethernet API functions are called.
\r
140 * Initialization of registers - config registers, enable Tx/Rx interrupts,
\r
141 * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address
\r
142 * filter table (unicats/multicast)/hash init
\r
147 uint8_t phy_address
\r
150 const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };
\r
153 /* To start with all buffers are free. */
\r
154 for( a = 0; a < macNUM_BUFFERS; a++ )
\r
156 ucMACBufferInUse[ a ] = pdFALSE;
\r
159 /* Try to reset chip */
\r
160 MAC_BITBAND->CSR0_SWR = 1u;
\r
165 } while ( 1u == MAC_BITBAND->CSR0_SWR );
\r
167 /* Check reset values of some registers to constrol
\r
168 * base address validity */
\r
169 configASSERT( MAC->CSR0 == 0xFE000000uL );
\r
170 configASSERT( MAC->CSR5 == 0xF0000000uL );
\r
171 configASSERT( MAC->CSR6 == 0x32000040uL );
\r
173 /* Instance setup */
\r
174 MAC_memset_All( &g_mss_mac, 0u );
\r
176 g_mss_mac.base_address = MAC_BASE;
\r
177 g_mss_mac.phy_address = phy_address;
\r
179 for( a=0; a<RX_RING_SIZE; a++ )
\r
181 /* Give the ownership to the MAC */
\r
182 g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;
\r
183 g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);
\r
185 /* Allocate a buffer to the descriptor, then mark the buffer as in use
\r
187 g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );
\r
188 ucMACBufferInUse[ a ] = pdTRUE;
\r
190 g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
\r
192 for( a = 0; a < TX_RING_SIZE; a++ )
\r
194 /* Buffers only get allocated to the Tx buffers when something is
\r
195 actually tranmitted. */
\r
196 g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL;
\r
198 g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;
\r
200 /* Configurable settings */
\r
201 MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;
\r
202 MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);
\r
203 MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;
\r
204 MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
\r
206 /* Fixed settings */
\r
207 /* No space between descriptors */
\r
208 MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
\r
209 /* General-purpose timer works in continuous mode */
\r
210 MAC_BITBAND->CSR11_CON = 1u;
\r
211 /* Start general-purpose */
\r
212 MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
\r
214 /* Ensure promiscous mode is off (it should be by default anyway). */
\r
215 MAC_BITBAND->CSR6_PR = 0;
\r
217 /* Perfect filter. */
\r
218 MAC_BITBAND->CSR6_HP = 1;
\r
220 /* Pass multcast. */
\r
221 MAC_BITBAND->CSR6_PM = 1;
\r
223 /* Set descriptors */
\r
224 MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
\r
225 MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);
\r
227 /* enable normal interrupts */
\r
228 MAC_BITBAND->CSR7_NIE = 1u;
\r
230 /* Set default MAC address and reset mac filters */
\r
231 MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
\r
232 MSS_MAC_set_mac_address((uint8_t *)mac_address);
\r
235 if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
\r
238 configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
\r
244 /* Configure chip according to PHY status */
\r
245 MSS_MAC_auto_setup_link();
\r
247 /* Ensure uip_buf starts by pointing somewhere. */
\r
248 uip_buf = MAC_obtain_buffer();
\r
252 /***************************************************************************//**
\r
253 * Sets the configuration of the Ethernet Controller.
\r
254 * After the EthernetInit function has been called, this API function can be
\r
255 * used to configure the various features of the Ethernet Controller.
\r
257 * @param instance Pointer to a MAC_instance_t structure
\r
258 * @param config The logical OR of the following values:
\r
259 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
260 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
261 * - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD
\r
262 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
263 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
264 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
265 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
266 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
267 * @see MAC_get_configuration()
\r
272 uint32_t configuration
\r
277 ret = MAC_stop_transmission();
\r
278 configASSERT( ret == MAC_OK );
\r
280 ret = MAC_stop_receiving();
\r
281 configASSERT( ret == MAC_OK );
\r
283 MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
\r
284 MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
\r
285 MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
\r
287 switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
\r
288 case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
\r
289 MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
\r
291 case MSS_MAC_CFG_THRESHOLD_CONTROL_01:
\r
292 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );
\r
294 case MSS_MAC_CFG_THRESHOLD_CONTROL_10:
\r
295 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );
\r
297 case MSS_MAC_CFG_THRESHOLD_CONTROL_11:
\r
298 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );
\r
303 MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );
\r
304 MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );
\r
305 MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );
\r
306 MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );
\r
307 PHY_set_link_type( (uint8_t)
\r
308 ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |
\r
309 (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );
\r
311 MSS_MAC_auto_setup_link();
\r
315 /***************************************************************************//**
\r
316 * Returns the configuration of the Ethernet Controller.
\r
318 * @param instance Pointer to a MAC_instance_t structure
\r
319 * @return The logical OR of the following values:
\r
320 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
321 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
322 * - #MSS_MAC_CFG_STORE_AND_FORWARD
\r
323 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
324 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
325 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
326 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
327 * - #MSS_MAC_CFG_INVERSE_FILTERING
\r
328 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
329 * - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE
\r
330 * - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE
\r
331 * @see MAC_configure()
\r
334 MSS_MAC_get_configuration( void )
\r
336 uint32_t configuration;
\r
338 configuration = 0u;
\r
339 if( MAC_BITBAND->CSR6_RA != 0u ) {
\r
340 configuration |= MSS_MAC_CFG_RECEIVE_ALL;
\r
343 if( MAC_BITBAND->CSR6_TTM != 0u ) {
\r
344 configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;
\r
347 if( MAC_BITBAND->CSR6_SF != 0u ) {
\r
348 configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;
\r
351 switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {
\r
352 case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;
\r
353 case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;
\r
354 case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;
\r
357 if( MAC_BITBAND->CSR6_FD != 0u ) {
\r
358 configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;
\r
361 if( MAC_BITBAND->CSR6_PM != 0u ) {
\r
362 configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;
\r
365 if( MAC_BITBAND->CSR6_PR != 0u ) {
\r
366 configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;
\r
369 if( MAC_BITBAND->CSR6_IF != 0u ) {
\r
370 configuration |= MSS_MAC_CFG_INVERSE_FILTERING;
\r
373 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
374 configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;
\r
377 if( MAC_BITBAND->CSR6_HO != 0u ) {
\r
378 configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;
\r
381 if( MAC_BITBAND->CSR6_HP != 0u ) {
\r
382 configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
\r
385 return (int32_t)configuration;
\r
389 /***************************************************************************//**
\r
390 Sends a packet from the uIP stack to the Ethernet Controller.
\r
391 The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
\r
392 MAC. This function writes uip_len bytes of the packet contained in uip_buf into
\r
393 the transmit FIFO and then activates the transmitter for this packet. If space
\r
394 is available in the FIFO, the function will return once pac_len bytes of the
\r
395 packet have been placed into the FIFO and the transmitter has been started.
\r
396 This function will not wait for the transmission to complete.
\r
399 The function returns zero if a timeout occurs otherwise it returns size of the packet.
\r
401 @see MAC_rx_packet()
\r
407 unsigned short usLength
\r
411 unsigned long ulDescriptor;
\r
412 int32_t error = MAC_OK;
\r
414 configASSERT( uip_buf != NULL_buffer );
\r
416 configASSERT( usLength >= 12 );
\r
418 if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
\r
420 configASSERT( usLength <= MSS_MAX_PACKET_SIZE );
\r
423 taskENTER_CRITICAL();
\r
425 /* Check both Tx descriptors are free, meaning the double send has completed. */
\r
426 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
428 error = MAC_BUFFER_IS_FULL;
\r
431 taskEXIT_CRITICAL();
\r
433 configASSERT( ( g_mss_mac.tx_desc_index == 0 ) );
\r
435 if( error == MAC_OK )
\r
437 /* Ensure nothing is going to get sent until both descriptors are ready.
\r
438 This is done to prevent a Tx end occurring prior to the second descriptor
\r
440 MAC_BITBAND->CSR6_ST = 0u;
\r
442 /* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
\r
444 taskENTER_CRITICAL();
\r
446 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
\r
448 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
\r
450 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
451 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
\r
454 /* Every buffer can hold a full frame so they are always first and last
\r
456 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;
\r
458 /* set data size */
\r
459 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
\r
461 /* reset end of ring */
\r
462 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
464 if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
466 usLength = (uint16_t)MSS_TX_BUFF_SIZE;
\r
469 /* The data buffer is assigned to the Tx descriptor. */
\r
470 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;
\r
472 /* update counters */
\r
473 desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
\r
474 if( (desc & TDES0_LO) != 0u ) {
\r
475 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
477 if( (desc & TDES0_NC) != 0u ) {
\r
478 g_mss_mac.statistics.tx_no_carrier++;
\r
480 if( (desc & TDES0_LC) != 0u ) {
\r
481 g_mss_mac.statistics.tx_late_collision++;
\r
483 if( (desc & TDES0_EC) != 0u ) {
\r
484 g_mss_mac.statistics.tx_excessive_collision++;
\r
486 if( (desc & TDES0_UF) != 0u ) {
\r
487 g_mss_mac.statistics.tx_underflow_error++;
\r
489 g_mss_mac.statistics.tx_collision_count +=
\r
490 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
492 /* Give ownership of descriptor to the MAC */
\r
493 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = TDES0_OWN;
\r
495 g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
\r
498 taskEXIT_CRITICAL();
\r
501 if (error == MAC_OK)
\r
503 error = (int32_t)usLength;
\r
505 /* Start sending now both descriptors are set up. This is done to
\r
506 prevent a Tx end occurring prior to the second descriptor being
\r
508 MAC_BITBAND->CSR6_ST = 1u;
\r
511 /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
\r
512 Find anothere free buffer for uip_buf. */
\r
513 uip_buf = MAC_obtain_buffer();
\r
523 /***************************************************************************//**
\r
524 * Returns available packet size.
\r
526 * @param instance Pointer to a MAC_instance_t structure
\r
527 * @return size of packet, bigger than 0, if a packet is available.
\r
528 * If not, returns 0.
\r
529 * @see MAC_rx_packet()
\r
532 MSS_MAC_rx_pckt_size
\r
538 MAC_dismiss_bad_frames();
\r
540 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
\r
542 /* Current descriptor is empty */
\r
547 uint32_t frame_length;
\r
548 frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;
\r
549 retval = (int32_t)( frame_length );
\r
555 /***************************************************************************//**
\r
556 * Receives a packet from the Ethernet Controller into the uIP stack.
\r
557 * This function reads a packet from the receive FIFO of the controller and
\r
558 * places it into uip_buf.
\r
560 * @return Size of packet if packet fits in uip_buf.
\r
561 * 0 if there is no received packet.
\r
562 * @see MAC_rx_pckt_size()
\r
563 * @see MAC_tx_packet()
\r
571 uint16_t frame_length=0u;
\r
573 MAC_dismiss_bad_frames();
\r
575 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
\r
578 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
579 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
582 frame_length -= 4u;
\r
584 if( frame_length > macBUFFER_SIZE ) {
\r
585 return MAC_NOT_ENOUGH_SPACE;
\r
588 /* uip_buf is about to point to the buffer that contains the received
\r
589 data, mark the buffer that uip_buf is currently pointing to as free
\r
591 MAC_release_buffer( uip_buf );
\r
592 uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
594 /* The buffer the Rx descriptor was pointing to is now in use by the
\r
595 uIP stack - allocate a new buffer to the Rx descriptor. */
\r
596 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();
\r
598 MSS_MAC_prepare_rx_descriptor();
\r
600 return ((int32_t)frame_length);
\r
604 /***************************************************************************//**
\r
605 * Receives a packet from the Ethernet Controller.
\r
606 * This function reads a packet from the receive FIFO of the controller and
\r
607 * sets the address of pacData to the received data.
\r
608 * If time_out parameter is zero the function will return
\r
609 * immediately (after the copy operation if data is available. Otherwise the function
\r
610 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
611 * value is given as time_out, function will wait for the reception to complete.
\r
613 * @param pacData The pointer to the packet data.
\r
614 * @param time_out Time out value in milli seconds for receiving.
\r
615 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
616 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
617 * if there is no packet waiting.
\r
618 * Otherwise value must be greater than 0 and smaller than
\r
620 * @return Size of packet if packet fits in pacData.
\r
621 * 0 if there is no received packet.
\r
622 * @see MAC_rx_pckt_size()
\r
623 * @see MAC_tx_packet()
\r
626 MSS_MAC_rx_packet_ptrset
\r
632 uint16_t frame_length = 0u;
\r
635 configASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
636 (time_out == MSS_MAC_NONBLOCKING) ||
\r
637 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
639 MAC_dismiss_bad_frames();
\r
641 /* wait for a packet */
\r
642 if( time_out != MSS_MAC_BLOCKING ) {
\r
643 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
644 MAC_set_time_out( 0u );
\r
646 MAC_set_time_out( time_out );
\r
650 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
651 RDES0_OWN) != 0u) && (exit == 0) )
\r
653 if( time_out != MSS_MAC_BLOCKING )
\r
655 if( MAC_get_time_out() == 0u ) {
\r
664 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
665 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
668 frame_length -= 4u;
\r
670 /* Here we are setting the buffer 'pacData' address to the address
\r
671 RX descriptor address. After this is called, the following function
\r
672 must be called 'MAC_prepare_rx_descriptor'
\r
673 to prepare the current rx descriptor for receiving the next packet.
\r
675 *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
\r
678 return ((int32_t)frame_length);
\r
681 /***************************************************************************//**
\r
682 * Returns the status of connection.
\r
684 * @return the logical OR of the following values:
\r
685 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
686 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
687 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
688 * @see MAC_auto_setup_link()
\r
691 MSS_MAC_link_status
\r
698 link = PHY_link_status();
\r
699 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
700 link |= PHY_link_type();
\r
703 return ((int32_t)link);
\r
707 /***************************************************************************//**
\r
708 * Setups the link between PHY and MAC and returns the status of connection.
\r
710 * @return the logical OR of the following values:
\r
711 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
712 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
713 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
714 * @see MAC_link_status()
\r
717 MSS_MAC_auto_setup_link
\r
724 PHY_auto_negotiate();
\r
726 link = MSS_MAC_link_status();
\r
728 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
730 ret = MAC_stop_transmission();
\r
731 MAC_CHECK( ret == MAC_OK, ret );
\r
733 ret = MAC_stop_receiving();
\r
734 MAC_CHECK( ret == MAC_OK, ret );
\r
735 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
736 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
737 MAC_start_transmission();
\r
738 MAC_start_receiving();
\r
745 /***************************************************************************//**
\r
746 * Sets mac address. New address must be unicast.
\r
748 * @param new_address Pointer to a MAC_instance_t structure
\r
749 * @see MAC_get_mac_address()
\r
752 MSS_MAC_set_mac_address
\r
754 const uint8_t *new_address
\r
757 /* Check if the new address is unicast */
\r
758 configASSERT( (new_address[0]&1) == 0 );
\r
760 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
762 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
764 /* set unused filters to the new mac address */
\r
765 for( a=14*6; a>=0; a-=6 ) {
\r
766 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
767 /* Filters with multicast addresses are used */
\r
770 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
771 g_mss_mac.mac_address, 6u );
\r
776 MAC_send_setup_frame();
\r
780 /***************************************************************************//**
\r
781 * Returns mac address.
\r
783 * @param address Pointer to receive the MAC address
\r
784 * @see MAC_set_mac_address()
\r
787 MSS_MAC_get_mac_address
\r
792 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
796 /***************************************************************************//**
\r
797 * Sets mac address filters. Addresses must be multicast.
\r
799 * @param filter_count number of addresses
\r
800 * @param filters Pointer to addresses to be filtered
\r
803 MSS_MAC_set_mac_filters
\r
805 uint16_t filter_count,
\r
806 const uint8_t *filters
\r
809 configASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
810 /* Check if the mac addresses is multicast */
\r
813 for( a = 0u; a < filter_count; a++ ) {
\r
814 configASSERT( (filters[a*6]&1) == 1 );
\r
818 if( filter_count <= 15 ){
\r
820 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
822 /* copy new filters */
\r
823 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
825 /* set unused filters to our mac address */
\r
826 for( a=filter_count; a<15; a++ ) {
\r
827 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
828 g_mss_mac.mac_address, 6 );
\r
834 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
836 /* reset hash table */
\r
837 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
839 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
840 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
841 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
845 MAC_send_setup_frame();
\r
849 /***************************************************************************//**
\r
850 * MAC interrupt service routine.
\r
852 * @param instance Pointer to a MAC_instance_t structure
\r
853 * @see MAC_set_callback()
\r
855 #if defined(__GNUC__)
\r
856 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
858 void EthernetMAC_IRQHandler( void )
\r
862 uint32_t intr_status;
\r
865 intr_status = MAC->CSR5;
\r
867 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
868 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
869 g_mss_mac.statistics.tx_interrupts++;
\r
870 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
873 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
874 g_mss_mac.statistics.rx_interrupts++;
\r
875 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
879 /* Clear interrupts */
\r
880 MAC->CSR5 = CSR5_INT_BITS;
\r
882 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
883 g_mss_mac.listener( events );
\r
888 /***************************************************************************//**
\r
889 * Sets MAC event listener.
\r
890 * Sets the given event listener function to be triggered inside MAC_isr().
\r
891 * Assigning NULL pointer as the listener function will disable it.
\r
893 * @param instance Pointer to a MAC_instance_t structure
\r
894 * @param listener function pointer to a MAC_callback_t function
\r
895 * @return #MAC_OK if everything is OK
\r
896 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
901 MSS_MAC_set_callback
\r
903 MSS_MAC_callback_t listener
\r
906 /* disable tx and rx interrupts */
\r
907 MAC_BITBAND->CSR7_RIE = 0u;
\r
908 MAC_BITBAND->CSR7_TIE = 0u;
\r
910 g_mss_mac.listener = listener;
\r
912 if( listener != NULL_callback ) {
\r
913 /* enable tx and rx interrupts */
\r
914 MAC_BITBAND->CSR7_RIE = 1u;
\r
915 MAC_BITBAND->CSR7_TIE = 1u;
\r
920 /***************************************************************************//**
\r
921 * Returns description of last error.
\r
923 * @param instance Pointer to a MAC_instance_t structure
\r
924 * @return A string describing the error. This string must not be
\r
925 * modified by the application.
\r
926 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
935 int8_t error_msg_nb;
\r
936 const int8_t* returnvalue;
\r
938 error_msg_nb = -(g_mss_mac.last_error);
\r
939 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
940 returnvalue = unknown_error;
\r
942 returnvalue = ErrorMessages[error_msg_nb];
\r
944 return returnvalue;
\r
948 /***************************************************************************//**
\r
949 * Returns statistics counter of stat_id identifier.
\r
951 * @param instance Pointer to a MAC_instance_t structure
\r
952 * @param stat_id Identifier of statistics counter.
\r
953 * @return Statistics counter of stat_id identifier.
\r
954 * On error returns 0.
\r
957 MSS_MAC_get_statistics
\r
959 mss_mac_statistics_id_t stat_id
\r
962 uint32_t returnval = 0u;
\r
964 switch( stat_id ) {
\r
965 case MSS_MAC_RX_INTERRUPTS:
\r
966 returnval = g_mss_mac.statistics.rx_interrupts;
\r
968 case MSS_MAC_RX_FILTERING_FAIL:
\r
969 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
971 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
972 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
974 case MSS_MAC_RX_RUNT_FRAME:
\r
975 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
977 case MSS_MAC_RX_NOT_FIRST:
\r
978 returnval = g_mss_mac.statistics.rx_not_first;
\r
980 case MSS_MAC_RX_NOT_LAST:
\r
981 returnval = g_mss_mac.statistics.rx_not_last;
\r
983 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
984 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
986 case MSS_MAC_RX_COLLISION_SEEN:
\r
987 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
989 case MSS_MAC_RX_CRC_ERROR:
\r
990 returnval = g_mss_mac.statistics.rx_crc_error;
\r
992 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
993 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
995 case MSS_MAC_RX_MISSED_FRAME:
\r
996 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
998 case MSS_MAC_TX_INTERRUPTS:
\r
999 returnval = g_mss_mac.statistics.tx_interrupts;
\r
1001 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
1002 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
1004 case MSS_MAC_TX_NO_CARRIER:
\r
1005 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
1007 case MSS_MAC_TX_LATE_COLLISION:
\r
1008 returnval = g_mss_mac.statistics.tx_late_collision;
\r
1010 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
1011 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
1013 case MSS_MAC_TX_COLLISION_COUNT:
\r
1014 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1016 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1017 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1027 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1030 /***************************************************************************//**
\r
1031 * Prepares current rx descriptor for receiving.
\r
1034 MSS_MAC_prepare_rx_descriptor
\r
1041 /* update counters */
\r
1042 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1043 if( (desc & RDES0_FF) != 0u ) {
\r
1044 g_mss_mac.statistics.rx_filtering_fail++;
\r
1046 if( (desc & RDES0_DE) != 0u ) {
\r
1047 g_mss_mac.statistics.rx_descriptor_error++;
\r
1049 if( (desc & RDES0_RF) != 0u ) {
\r
1050 g_mss_mac.statistics.rx_runt_frame++;
\r
1052 if( (desc & RDES0_FS) == 0u ) {
\r
1053 g_mss_mac.statistics.rx_not_first++;
\r
1055 if( (desc & RDES0_LS) == 0u ) {
\r
1056 g_mss_mac.statistics.rx_not_last++;
\r
1058 if( (desc & RDES0_TL) != 0u ) {
\r
1059 g_mss_mac.statistics.rx_frame_too_long++;
\r
1061 if( (desc & RDES0_CS) != 0u ) {
\r
1062 g_mss_mac.statistics.rx_collision_seen++;
\r
1064 if( (desc & RDES0_CE) != 0u ) {
\r
1065 g_mss_mac.statistics.rx_crc_error++;
\r
1069 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1070 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1071 g_mss_mac.statistics.rx_missed_frame +=
\r
1072 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1074 /* Give ownership of descriptor to the MAC */
\r
1075 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 = RDES0_OWN;
\r
1076 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1078 /* Start receive */
\r
1079 MAC_start_receiving();
\r
1083 /***************************************************************************//**
\r
1084 * Prepares a setup frame and sends it to MAC.
\r
1085 * This function is blocking.
\r
1086 * @return #MAC_OK if everything is ok.
\r
1087 * #MAC_TIME_OUT if timed out before packet send.
\r
1090 MAC_send_setup_frame
\r
1095 volatile MAC_descriptor_t descriptor;
\r
1096 uint8_t frame_data[192];
\r
1101 /* prepare descriptor */
\r
1102 descriptor.descriptor_0 = TDES0_OWN;
\r
1103 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1104 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1106 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1107 descriptor.descriptor_1 |= TDES1_FT0;
\r
1110 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1111 descriptor.buffer_2 = 0u;
\r
1113 /* prepare frame */
\r
1114 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1124 data = g_mss_mac.mac_address;
\r
1125 frame_data[b] = data[0];
\r
1126 frame_data[b+1] = data[1];
\r
1127 frame_data[b+4] = data[2];
\r
1128 frame_data[b+5] = data[3];
\r
1129 frame_data[b+8] = data[4];
\r
1130 frame_data[b+9] = data[5];
\r
1132 data = g_mss_mac.mac_filter_data;
\r
1133 for( a = 0; a < c; ) {
\r
1134 frame_data[d] = data[a++];
\r
1135 frame_data[d+1] = data[a++];
\r
1136 frame_data[d+4] = data[a++];
\r
1137 frame_data[d+5] = data[a++];
\r
1138 frame_data[d+8] = data[a++];
\r
1139 frame_data[d+9] = data[a++];
\r
1143 /* Stop transmission */
\r
1144 ret = MAC_stop_transmission();
\r
1145 configASSERT( ret == MAC_OK );
\r
1147 ret = MAC_stop_receiving();
\r
1148 configASSERT( ret == MAC_OK );
\r
1150 /* Set descriptor */
\r
1151 MAC->CSR4 = (uint32_t)&descriptor;
\r
1153 /* Start transmission */
\r
1154 MAC_start_transmission();
\r
1156 /* Wait until transmission over */
\r
1158 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1160 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1161 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1163 /* transmit poll demand */
\r
1165 if( MAC_get_time_out() == 0u ) {
\r
1166 ret = MAC_TIME_OUT;
\r
1170 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1172 /* Set tx descriptor */
\r
1173 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1175 /* Start receiving and transmission */
\r
1176 MAC_start_receiving();
\r
1177 MAC_start_transmission();
\r
1183 /***************************************************************************//**
\r
1184 * Stops transmission.
\r
1185 * Function will wait until transmit operation enters stop state.
\r
1187 * @return #MAC_OK if everything is ok.
\r
1188 * #MAC_TIME_OUT if timed out.
\r
1191 MAC_stop_transmission
\r
1196 int32_t retval = MAC_OK;
\r
1197 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1199 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1200 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1202 MAC_BITBAND->CSR6_ST = 0u;
\r
1203 if( MAC_get_time_out() == 0u ) {
\r
1204 retval = MAC_TIME_OUT;
\r
1211 /***************************************************************************//**
\r
1212 * Starts transmission.
\r
1215 MAC_start_transmission
\r
1220 MAC_BITBAND->CSR6_ST = 1u;
\r
1224 /***************************************************************************//**
\r
1225 * Stops transmission.
\r
1226 * Function will wait until transmit operation enters stop state.
\r
1228 * @return #MAC_OK if everything is ok.
\r
1229 * #MAC_TIME_OUT if timed out.
\r
1232 MAC_stop_receiving
\r
1237 int32_t retval = MAC_OK;
\r
1238 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1240 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1241 && (retval == MAC_OK) )
\r
1243 MAC_BITBAND->CSR6_SR = 0u;
\r
1244 if( MAC_get_time_out() == 0u ) {
\r
1245 retval = MAC_TIME_OUT;
\r
1253 /***************************************************************************//**
\r
1254 * Starts transmission.
\r
1257 MAC_start_receiving
\r
1262 MAC_BITBAND->CSR6_SR = 1u;
\r
1266 /***************************************************************************//**
\r
1267 * Dismisses bad frames.
\r
1269 * @return dismissed frame count.
\r
1272 MAC_dismiss_bad_frames
\r
1280 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1281 /* User wants bad frames too, don't dismiss anything */
\r
1285 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1286 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1288 /* check error summary */
\r
1289 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1290 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1292 MSS_MAC_prepare_rx_descriptor();
\r
1304 /***************************************************************************//**
\r
1305 * Sets time out value.
\r
1306 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1307 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1309 * @time_out time out value in milli seconds.
\r
1310 * Must be smaller than 0x01000000.
\r
1318 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1320 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1323 /***************************************************************************//**
\r
1324 * Returns time out value.
\r
1326 * @return timer out value in milli seconds.
\r
1335 uint32_t time = 0u;
\r
1337 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1339 if( timer > g_mss_mac.last_timer_value ) {
\r
1340 time = 0x0000ffffUL;
\r
1342 time += g_mss_mac.last_timer_value - timer;
\r
1344 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1347 if( g_mss_mac.time_out_value <= time ){
\r
1348 g_mss_mac.time_out_value = 0u;
\r
1350 g_mss_mac.time_out_value -= time;
\r
1353 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1355 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1358 /***************************************************************************//**
\r
1359 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1362 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1372 /***************************************************************************//**
\r
1373 * Fills all fields of MAC_instance_t with c.
\r
1375 * @return a pointer to the given MAC_instance_t s.
\r
1377 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1380 s->base_address = (addr_t)c;
\r
1381 s->flags = (uint8_t)c;
\r
1382 s->last_error = (int8_t)c;
\r
1383 s->last_timer_value = (uint16_t)c;
\r
1384 s->listener = NULL_callback;
\r
1385 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1386 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1387 s->phy_address = (uint8_t)c;
\r
1388 s->rx_desc_index =c;
\r
1389 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1391 s->rx_descriptors[count].buffer_1 = c;
\r
1392 s->rx_descriptors[count].buffer_2 = c;
\r
1393 s->rx_descriptors[count].descriptor_0 = c;
\r
1394 s->rx_descriptors[count].descriptor_1 = c;
\r
1396 s->statistics.rx_collision_seen =c;
\r
1397 s->statistics.rx_crc_error = c;
\r
1398 s->statistics.rx_descriptor_error = c;
\r
1399 s->statistics.rx_fifo_overflow = c;
\r
1400 s->statistics.rx_filtering_fail = c;
\r
1401 s->statistics.rx_frame_too_long = c;
\r
1402 s->statistics.rx_interrupts = c;
\r
1403 s->statistics.rx_missed_frame = c;
\r
1404 s->statistics.rx_not_first = c;
\r
1405 s->statistics.rx_not_last = c;
\r
1406 s->statistics.rx_runt_frame = c;
\r
1407 s->statistics.tx_collision_count = c;
\r
1408 s->statistics.tx_excessive_collision = c;
\r
1409 s->statistics.tx_interrupts = c;
\r
1410 s->statistics.tx_late_collision = c;
\r
1411 s->statistics.tx_loss_of_carrier = c;
\r
1412 s->statistics.tx_no_carrier = c;
\r
1413 s->statistics.tx_underflow_error = c;
\r
1414 s->time_out_value = c;
\r
1415 s->tx_desc_index = c;
\r
1416 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1418 s->tx_descriptors[count].buffer_1 = c;
\r
1419 s->tx_descriptors[count].buffer_2 = c;
\r
1420 s->tx_descriptors[count].descriptor_0 = c;
\r
1421 s->tx_descriptors[count].descriptor_1 = c;
\r
1425 /***************************************************************************//**
\r
1426 * Copies n bytes from memory area src to memory area dest.
\r
1427 * The memory areas should not overlap.
\r
1429 * @return a pointer to the memory area dest.
\r
1431 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1433 uint8_t *d = dest;
\r
1441 /***************************************************************************//**
\r
1442 * Tx has completed, mark the buffers that were assigned to the Tx descriptors
\r
1446 void MSS_MAC_FreeTxBuffers( void )
\r
1448 /* Check the buffers have not already been freed in the first of the
\r
1449 two Tx interrupts - which could potentially happen if the second Tx completed
\r
1450 during the interrupt for the first Tx. */
\r
1451 if( g_mss_mac.tx_descriptors[ 0 ].buffer_1 != ( uint32_t ) NULL )
\r
1453 if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )
\r
1455 configASSERT( g_mss_mac.tx_descriptors[ 0 ].buffer_1 == g_mss_mac.tx_descriptors[ 1 ].buffer_1 );
\r
1456 MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );
\r
1458 /* Just to mark the fact that the buffer has already been released. */
\r
1459 g_mss_mac.tx_descriptors[ 0 ].buffer_1 = ( uint32_t ) NULL;
\r
1464 /***************************************************************************//**
\r
1465 * Look through the array of buffers until one is found that is free for use -
\r
1466 * that is, not currently assigned to an Rx or a Tx descriptor. Mark the buffer
\r
1467 * as in use, then return its address.
\r
1469 * @return a pointer to a free buffer.
\r
1471 unsigned char *MAC_obtain_buffer( void )
\r
1473 long lIndex, lAttempt = 0, lDescriptor, lBufferIsInUse;
\r
1474 unsigned char *pcReturn = NULL;
\r
1475 unsigned char *pcBufferAddress;
\r
1477 /* Find and return the address of a buffer that is not being used. Mark
\r
1478 the buffer as now in use. */
\r
1479 while( ( lAttempt <= 1 ) && ( pcReturn == NULL ) )
\r
1481 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1483 if( ucMACBufferInUse[ lIndex ] == pdFALSE )
\r
1485 pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
\r
1486 ucMACBufferInUse[ lIndex ] = pdTRUE;
\r
1491 if( pcReturn == NULL )
\r
1493 /* Did not find a buffer. That should not really happen, but could if
\r
1494 an interrupt was missed. See if any buffers are marked as in use, but
\r
1495 are not actually in use. */
\r
1496 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1498 pcBufferAddress = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
\r
1499 lBufferIsInUse = pdFALSE;
\r
1501 /* Is the buffer used by an Rx descriptor? */
\r
1502 for( lDescriptor = 0; lDescriptor < RX_RING_SIZE; lDescriptor++ )
\r
1504 if( g_mss_mac.rx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )
\r
1506 /* The buffer is in use by an Rx descriptor. */
\r
1507 lBufferIsInUse = pdTRUE;
\r
1512 if( lBufferIsInUse != pdTRUE )
\r
1514 /* Is the buffer used by an Tx descriptor? */
\r
1515 for( lDescriptor = 0; lDescriptor < TX_RING_SIZE; lDescriptor++ )
\r
1517 if( g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )
\r
1519 /* The buffer is in use by an Tx descriptor. */
\r
1520 lBufferIsInUse = pdTRUE;
\r
1526 /* If the buffer was not found to be in use by either a Tx or an
\r
1527 Rx descriptor, but the buffer is marked as in use, then mark the
\r
1528 buffer to be in it's correct state of "not in use". */
\r
1529 if( ( lBufferIsInUse == pdFALSE ) && ( ucMACBufferInUse[ lIndex ] == pdTRUE ) )
\r
1531 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1536 /* If any buffer states were changed it might be that a buffer can now
\r
1537 be obtained. Try again, but only one more time. */
\r
1541 configASSERT( pcReturn );
\r
1545 /***************************************************************************//**
\r
1546 * Return a buffer to the list of free buffers, it was in use, but is not now.
\r
1549 void MAC_release_buffer( unsigned char *pucBufferToRelease )
\r
1553 /* uip_buf is going to point to a different buffer - first ensure the buffer
\r
1554 it is currently pointing to is marked as being free again. */
\r
1555 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1557 if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
\r
1559 /* This is the buffer in use, mark it as being free. */
\r
1560 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1565 configASSERT( lIndex < macNUM_BUFFERS );
\r
1570 #ifdef __cplusplus
\r
1574 /******************************** END OF FILE *********************************/
\r