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 + 1
\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 /* Check if second descriptor is free, if it is then the first must
\r
425 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
427 error = MAC_BUFFER_IS_FULL;
\r
431 if( error == MAC_OK )
\r
433 /* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
\r
435 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
\r
437 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
\r
439 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
440 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
\r
443 /* Every buffer can hold a full frame so they are always first and last
\r
445 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
\r
447 /* set data size */
\r
448 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
\r
450 /* reset end of ring */
\r
451 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
453 if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
455 usLength = (uint16_t)MSS_TX_BUFF_SIZE;
\r
458 /* The data buffer is assigned to the Tx descriptor. */
\r
459 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;
\r
461 /* update counters */
\r
462 desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
\r
463 if( (desc & TDES0_LO) != 0u ) {
\r
464 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
466 if( (desc & TDES0_NC) != 0u ) {
\r
467 g_mss_mac.statistics.tx_no_carrier++;
\r
469 if( (desc & TDES0_LC) != 0u ) {
\r
470 g_mss_mac.statistics.tx_late_collision++;
\r
472 if( (desc & TDES0_EC) != 0u ) {
\r
473 g_mss_mac.statistics.tx_excessive_collision++;
\r
475 if( (desc & TDES0_UF) != 0u ) {
\r
476 g_mss_mac.statistics.tx_underflow_error++;
\r
478 g_mss_mac.statistics.tx_collision_count +=
\r
479 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
481 /* Give ownership of descriptor to the MAC */
\r
482 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;
\r
484 g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
\r
486 MAC_start_transmission();
\r
491 if (error == MAC_OK)
\r
493 error = (int32_t)usLength;
\r
495 /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
\r
496 Find anothere free buffer for uip_buf. */
\r
497 uip_buf = MAC_obtain_buffer();
\r
507 /***************************************************************************//**
\r
508 * Returns available packet size.
\r
510 * @param instance Pointer to a MAC_instance_t structure
\r
511 * @return size of packet, bigger than 0, if a packet is available.
\r
512 * If not, returns 0.
\r
513 * @see MAC_rx_packet()
\r
516 MSS_MAC_rx_pckt_size
\r
522 MAC_dismiss_bad_frames();
\r
524 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
\r
526 /* Current descriptor is empty */
\r
531 uint32_t frame_length;
\r
532 frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;
\r
533 retval = (int32_t)( frame_length );
\r
539 /***************************************************************************//**
\r
540 * Receives a packet from the Ethernet Controller into the uIP stack.
\r
541 * This function reads a packet from the receive FIFO of the controller and
\r
542 * places it into uip_buf.
\r
544 * @return Size of packet if packet fits in uip_buf.
\r
545 * 0 if there is no received packet.
\r
546 * @see MAC_rx_pckt_size()
\r
547 * @see MAC_tx_packet()
\r
555 uint16_t frame_length=0u;
\r
557 MAC_dismiss_bad_frames();
\r
559 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
\r
562 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
563 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
566 frame_length -= 4u;
\r
568 if( frame_length > macBUFFER_SIZE ) {
\r
569 return MAC_NOT_ENOUGH_SPACE;
\r
572 /* uip_buf is about to point to the buffer that contains the received
\r
573 data, mark the buffer that uip_buf is currently pointing to as free
\r
575 MAC_release_buffer( uip_buf );
\r
576 uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
578 /* The buffer the Rx descriptor was pointing to is now in use by the
\r
579 uIP stack - allocate a new buffer to the Rx descriptor. */
\r
580 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();
\r
582 MSS_MAC_prepare_rx_descriptor();
\r
584 return ((int32_t)frame_length);
\r
588 /***************************************************************************//**
\r
589 * Receives a packet from the Ethernet Controller.
\r
590 * This function reads a packet from the receive FIFO of the controller and
\r
591 * sets the address of pacData to the received data.
\r
592 * If time_out parameter is zero the function will return
\r
593 * immediately (after the copy operation if data is available. Otherwise the function
\r
594 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
595 * value is given as time_out, function will wait for the reception to complete.
\r
597 * @param instance Pointer to a MAC_instance_t structure
\r
598 * @param pacData The pointer to the packet data.
\r
599 * @param time_out Time out value in milli seconds for receiving.
\r
600 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
601 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
602 * if there is no packet waiting.
\r
603 * Otherwise value must be greater than 0 and smaller than
\r
605 * @return Size of packet if packet fits in pacData.
\r
606 * 0 if there is no received packet.
\r
607 * @see MAC_rx_pckt_size()
\r
608 * @see MAC_tx_packet()
\r
611 MSS_MAC_rx_packet_ptrset
\r
617 uint16_t frame_length = 0u;
\r
620 configASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
621 (time_out == MSS_MAC_NONBLOCKING) ||
\r
622 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
624 MAC_dismiss_bad_frames();
\r
626 /* wait for a packet */
\r
627 if( time_out != MSS_MAC_BLOCKING ) {
\r
628 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
629 MAC_set_time_out( 0u );
\r
631 MAC_set_time_out( time_out );
\r
635 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
636 RDES0_OWN) != 0u) && (exit == 0) )
\r
638 if( time_out != MSS_MAC_BLOCKING )
\r
640 if( MAC_get_time_out() == 0u ) {
\r
649 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
650 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
653 frame_length -= 4u;
\r
655 /* Here we are setting the buffer 'pacData' address to the address
\r
656 RX descriptor address. After this is called, the following function
\r
657 must be called 'MAC_prepare_rx_descriptor'
\r
658 to prepare the current rx descriptor for receiving the next packet.
\r
660 *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
\r
663 return ((int32_t)frame_length);
\r
666 /***************************************************************************//**
\r
667 * Returns the status of connection.
\r
669 * @return the logical OR of the following values:
\r
670 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
671 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
672 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
673 * @see MAC_auto_setup_link()
\r
676 MSS_MAC_link_status
\r
683 link = PHY_link_status();
\r
684 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
685 link |= PHY_link_type();
\r
688 return ((int32_t)link);
\r
692 /***************************************************************************//**
\r
693 * Setups the link between PHY and MAC and returns the status of connection.
\r
695 * @return the logical OR of the following values:
\r
696 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
697 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
698 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
699 * @see MAC_link_status()
\r
702 MSS_MAC_auto_setup_link
\r
709 PHY_auto_negotiate();
\r
711 link = MSS_MAC_link_status();
\r
713 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
715 ret = MAC_stop_transmission();
\r
716 MAC_CHECK( ret == MAC_OK, ret );
\r
718 ret = MAC_stop_receiving();
\r
719 MAC_CHECK( ret == MAC_OK, ret );
\r
720 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
721 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
722 MAC_start_transmission();
\r
723 MAC_start_receiving();
\r
730 /***************************************************************************//**
\r
731 * Sets mac address. New address must be unicast.
\r
733 * @param new_address Pointer to a MAC_instance_t structure
\r
734 * @see MAC_get_mac_address()
\r
737 MSS_MAC_set_mac_address
\r
739 const uint8_t *new_address
\r
742 /* Check if the new address is unicast */
\r
743 configASSERT( (new_address[0]&1) == 0 );
\r
745 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
747 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
749 /* set unused filters to the new mac address */
\r
750 for( a=14*6; a>=0; a-=6 ) {
\r
751 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
752 /* Filters with multicast addresses are used */
\r
755 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
756 g_mss_mac.mac_address, 6u );
\r
761 MAC_send_setup_frame();
\r
765 /***************************************************************************//**
\r
766 * Returns mac address.
\r
768 * @param address Pointer to receive the MAC address
\r
769 * @see MAC_set_mac_address()
\r
772 MSS_MAC_get_mac_address
\r
777 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
781 /***************************************************************************//**
\r
782 * Sets mac address filters. Addresses must be multicast.
\r
784 * @param filter_count number of addresses
\r
785 * @param filters Pointer to addresses to be filtered
\r
788 MSS_MAC_set_mac_filters
\r
790 uint16_t filter_count,
\r
791 const uint8_t *filters
\r
794 configASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
795 /* Check if the mac addresses is multicast */
\r
798 for( a = 0u; a < filter_count; a++ ) {
\r
799 configASSERT( (filters[a*6]&1) == 1 );
\r
803 if( filter_count <= 15 ){
\r
805 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
807 /* copy new filters */
\r
808 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
810 /* set unused filters to our mac address */
\r
811 for( a=filter_count; a<15; a++ ) {
\r
812 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
813 g_mss_mac.mac_address, 6 );
\r
819 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
821 /* reset hash table */
\r
822 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
824 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
825 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
826 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
830 MAC_send_setup_frame();
\r
834 /***************************************************************************//**
\r
835 * MAC interrupt service routine.
\r
837 * @param instance Pointer to a MAC_instance_t structure
\r
838 * @see MAC_set_callback()
\r
840 #if defined(__GNUC__)
\r
841 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
843 void EthernetMAC_IRQHandler( void )
\r
847 uint32_t intr_status;
\r
850 intr_status = MAC->CSR5;
\r
852 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
853 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
854 g_mss_mac.statistics.tx_interrupts++;
\r
855 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
858 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
859 g_mss_mac.statistics.rx_interrupts++;
\r
860 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
864 /* Clear interrupts */
\r
865 MAC->CSR5 = CSR5_INT_BITS;
\r
867 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
868 g_mss_mac.listener( events );
\r
873 /***************************************************************************//**
\r
874 * Sets MAC event listener.
\r
875 * Sets the given event listener function to be triggered inside MAC_isr().
\r
876 * Assigning NULL pointer as the listener function will disable it.
\r
878 * @param instance Pointer to a MAC_instance_t structure
\r
879 * @param listener function pointer to a MAC_callback_t function
\r
880 * @return #MAC_OK if everything is OK
\r
881 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
886 MSS_MAC_set_callback
\r
888 MSS_MAC_callback_t listener
\r
891 /* disable tx and rx interrupts */
\r
892 MAC_BITBAND->CSR7_RIE = 0u;
\r
893 MAC_BITBAND->CSR7_TIE = 0u;
\r
895 g_mss_mac.listener = listener;
\r
897 if( listener != NULL_callback ) {
\r
898 /* enable tx and rx interrupts */
\r
899 MAC_BITBAND->CSR7_RIE = 1u;
\r
900 MAC_BITBAND->CSR7_TIE = 1u;
\r
905 /***************************************************************************//**
\r
906 * Returns description of last error.
\r
908 * @param instance Pointer to a MAC_instance_t structure
\r
909 * @return A string describing the error. This string must not be
\r
910 * modified by the application.
\r
911 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
920 int8_t error_msg_nb;
\r
921 const int8_t* returnvalue;
\r
923 error_msg_nb = -(g_mss_mac.last_error);
\r
924 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
925 returnvalue = unknown_error;
\r
927 returnvalue = ErrorMessages[error_msg_nb];
\r
929 return returnvalue;
\r
933 /***************************************************************************//**
\r
934 * Returns statistics counter of stat_id identifier.
\r
936 * @param instance Pointer to a MAC_instance_t structure
\r
937 * @param stat_id Identifier of statistics counter.
\r
938 * @return Statistics counter of stat_id identifier.
\r
939 * On error returns 0.
\r
942 MSS_MAC_get_statistics
\r
944 mss_mac_statistics_id_t stat_id
\r
947 uint32_t returnval = 0u;
\r
949 switch( stat_id ) {
\r
950 case MSS_MAC_RX_INTERRUPTS:
\r
951 returnval = g_mss_mac.statistics.rx_interrupts;
\r
953 case MSS_MAC_RX_FILTERING_FAIL:
\r
954 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
956 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
957 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
959 case MSS_MAC_RX_RUNT_FRAME:
\r
960 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
962 case MSS_MAC_RX_NOT_FIRST:
\r
963 returnval = g_mss_mac.statistics.rx_not_first;
\r
965 case MSS_MAC_RX_NOT_LAST:
\r
966 returnval = g_mss_mac.statistics.rx_not_last;
\r
968 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
969 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
971 case MSS_MAC_RX_COLLISION_SEEN:
\r
972 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
974 case MSS_MAC_RX_CRC_ERROR:
\r
975 returnval = g_mss_mac.statistics.rx_crc_error;
\r
977 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
978 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
980 case MSS_MAC_RX_MISSED_FRAME:
\r
981 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
983 case MSS_MAC_TX_INTERRUPTS:
\r
984 returnval = g_mss_mac.statistics.tx_interrupts;
\r
986 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
987 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
989 case MSS_MAC_TX_NO_CARRIER:
\r
990 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
992 case MSS_MAC_TX_LATE_COLLISION:
\r
993 returnval = g_mss_mac.statistics.tx_late_collision;
\r
995 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
996 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
998 case MSS_MAC_TX_COLLISION_COUNT:
\r
999 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1001 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1002 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1012 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1015 /***************************************************************************//**
\r
1016 * Prepares current rx descriptor for receiving.
\r
1019 MSS_MAC_prepare_rx_descriptor
\r
1026 /* update counters */
\r
1027 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1028 if( (desc & RDES0_FF) != 0u ) {
\r
1029 g_mss_mac.statistics.rx_filtering_fail++;
\r
1031 if( (desc & RDES0_DE) != 0u ) {
\r
1032 g_mss_mac.statistics.rx_descriptor_error++;
\r
1034 if( (desc & RDES0_RF) != 0u ) {
\r
1035 g_mss_mac.statistics.rx_runt_frame++;
\r
1037 if( (desc & RDES0_FS) == 0u ) {
\r
1038 g_mss_mac.statistics.rx_not_first++;
\r
1040 if( (desc & RDES0_LS) == 0u ) {
\r
1041 g_mss_mac.statistics.rx_not_last++;
\r
1043 if( (desc & RDES0_TL) != 0u ) {
\r
1044 g_mss_mac.statistics.rx_frame_too_long++;
\r
1046 if( (desc & RDES0_CS) != 0u ) {
\r
1047 g_mss_mac.statistics.rx_collision_seen++;
\r
1049 if( (desc & RDES0_CE) != 0u ) {
\r
1050 g_mss_mac.statistics.rx_crc_error++;
\r
1054 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1055 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1056 g_mss_mac.statistics.rx_missed_frame +=
\r
1057 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1059 /* Give ownership of descriptor to the MAC */
\r
1060 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =
\r
1062 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1064 /* Start receive */
\r
1065 MAC_start_receiving();
\r
1069 /***************************************************************************//**
\r
1070 * Prepares a setup frame and sends it to MAC.
\r
1071 * This function is blocking.
\r
1072 * @return #MAC_OK if everything is ok.
\r
1073 * #MAC_TIME_OUT if timed out before packet send.
\r
1076 MAC_send_setup_frame
\r
1081 volatile MAC_descriptor_t descriptor;
\r
1082 uint8_t frame_data[192];
\r
1087 /* prepare descriptor */
\r
1088 descriptor.descriptor_0 = TDES0_OWN;
\r
1089 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1090 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1092 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1093 descriptor.descriptor_1 |= TDES1_FT0;
\r
1096 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1097 descriptor.buffer_2 = 0u;
\r
1099 /* prepare frame */
\r
1100 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1110 data = g_mss_mac.mac_address;
\r
1111 frame_data[b] = data[0];
\r
1112 frame_data[b+1] = data[1];
\r
1113 frame_data[b+4] = data[2];
\r
1114 frame_data[b+5] = data[3];
\r
1115 frame_data[b+8] = data[4];
\r
1116 frame_data[b+9] = data[5];
\r
1118 data = g_mss_mac.mac_filter_data;
\r
1119 for( a = 0; a < c; ) {
\r
1120 frame_data[d] = data[a++];
\r
1121 frame_data[d+1] = data[a++];
\r
1122 frame_data[d+4] = data[a++];
\r
1123 frame_data[d+5] = data[a++];
\r
1124 frame_data[d+8] = data[a++];
\r
1125 frame_data[d+9] = data[a++];
\r
1129 /* Stop transmission */
\r
1130 ret = MAC_stop_transmission();
\r
1131 configASSERT( ret == MAC_OK );
\r
1133 ret = MAC_stop_receiving();
\r
1134 configASSERT( ret == MAC_OK );
\r
1136 /* Set descriptor */
\r
1137 MAC->CSR4 = (uint32_t)&descriptor;
\r
1139 /* Start transmission */
\r
1140 MAC_start_transmission();
\r
1142 /* Wait until transmission over */
\r
1144 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1146 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1147 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1149 /* transmit poll demand */
\r
1151 if( MAC_get_time_out() == 0u ) {
\r
1152 ret = MAC_TIME_OUT;
\r
1156 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1158 /* Set tx descriptor */
\r
1159 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1161 /* Start receiving and transmission */
\r
1162 MAC_start_receiving();
\r
1163 MAC_start_transmission();
\r
1169 /***************************************************************************//**
\r
1170 * Stops transmission.
\r
1171 * Function will wait until transmit operation enters stop state.
\r
1173 * @return #MAC_OK if everything is ok.
\r
1174 * #MAC_TIME_OUT if timed out.
\r
1177 MAC_stop_transmission
\r
1182 int32_t retval = MAC_OK;
\r
1183 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1185 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1186 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1188 MAC_BITBAND->CSR6_ST = 0u;
\r
1189 if( MAC_get_time_out() == 0u ) {
\r
1190 retval = MAC_TIME_OUT;
\r
1197 /***************************************************************************//**
\r
1198 * Starts transmission.
\r
1201 MAC_start_transmission
\r
1206 MAC_BITBAND->CSR6_ST = 1u;
\r
1210 /***************************************************************************//**
\r
1211 * Stops transmission.
\r
1212 * Function will wait until transmit operation enters stop state.
\r
1214 * @return #MAC_OK if everything is ok.
\r
1215 * #MAC_TIME_OUT if timed out.
\r
1218 MAC_stop_receiving
\r
1223 int32_t retval = MAC_OK;
\r
1224 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1226 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1227 && (retval == MAC_OK) )
\r
1229 MAC_BITBAND->CSR6_SR = 0u;
\r
1230 if( MAC_get_time_out() == 0u ) {
\r
1231 retval = MAC_TIME_OUT;
\r
1239 /***************************************************************************//**
\r
1240 * Starts transmission.
\r
1243 MAC_start_receiving
\r
1248 MAC_BITBAND->CSR6_SR = 1u;
\r
1252 /***************************************************************************//**
\r
1253 * Dismisses bad frames.
\r
1255 * @return dismissed frame count.
\r
1258 MAC_dismiss_bad_frames
\r
1266 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1267 /* User wants bad frames too, don't dismiss anything */
\r
1271 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1272 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1274 /* check error summary */
\r
1275 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1276 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1278 MSS_MAC_prepare_rx_descriptor();
\r
1290 /***************************************************************************//**
\r
1291 * Sets time out value.
\r
1292 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1293 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1295 * @time_out time out value in milli seconds.
\r
1296 * Must be smaller than 0x01000000.
\r
1304 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1306 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1309 /***************************************************************************//**
\r
1310 * Returns time out value.
\r
1312 * @return timer out value in milli seconds.
\r
1321 uint32_t time = 0u;
\r
1323 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1325 if( timer > g_mss_mac.last_timer_value ) {
\r
1326 time = 0x0000ffffUL;
\r
1328 time += g_mss_mac.last_timer_value - timer;
\r
1330 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1333 if( g_mss_mac.time_out_value <= time ){
\r
1334 g_mss_mac.time_out_value = 0u;
\r
1336 g_mss_mac.time_out_value -= time;
\r
1339 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1341 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1344 /***************************************************************************//**
\r
1345 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1348 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1358 /***************************************************************************//**
\r
1359 * Fills all fields of MAC_instance_t with c.
\r
1361 * @return a pointer to the given MAC_instance_t s.
\r
1363 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1366 s->base_address = (addr_t)c;
\r
1367 s->flags = (uint8_t)c;
\r
1368 s->last_error = (int8_t)c;
\r
1369 s->last_timer_value = (uint16_t)c;
\r
1370 s->listener = NULL_callback;
\r
1371 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1372 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1373 s->phy_address = (uint8_t)c;
\r
1374 s->rx_desc_index =c;
\r
1375 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1377 s->rx_descriptors[count].buffer_1 = c;
\r
1378 s->rx_descriptors[count].buffer_2 = c;
\r
1379 s->rx_descriptors[count].descriptor_0 = c;
\r
1380 s->rx_descriptors[count].descriptor_1 = c;
\r
1382 s->statistics.rx_collision_seen =c;
\r
1383 s->statistics.rx_crc_error = c;
\r
1384 s->statistics.rx_descriptor_error = c;
\r
1385 s->statistics.rx_fifo_overflow = c;
\r
1386 s->statistics.rx_filtering_fail = c;
\r
1387 s->statistics.rx_frame_too_long = c;
\r
1388 s->statistics.rx_interrupts = c;
\r
1389 s->statistics.rx_missed_frame = c;
\r
1390 s->statistics.rx_not_first = c;
\r
1391 s->statistics.rx_not_last = c;
\r
1392 s->statistics.rx_runt_frame = c;
\r
1393 s->statistics.tx_collision_count = c;
\r
1394 s->statistics.tx_excessive_collision = c;
\r
1395 s->statistics.tx_interrupts = c;
\r
1396 s->statistics.tx_late_collision = c;
\r
1397 s->statistics.tx_loss_of_carrier = c;
\r
1398 s->statistics.tx_no_carrier = c;
\r
1399 s->statistics.tx_underflow_error = c;
\r
1400 s->time_out_value = c;
\r
1401 s->tx_desc_index = c;
\r
1402 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1404 s->tx_descriptors[count].buffer_1 = c;
\r
1405 s->tx_descriptors[count].buffer_2 = c;
\r
1406 s->tx_descriptors[count].descriptor_0 = c;
\r
1407 s->tx_descriptors[count].descriptor_1 = c;
\r
1411 /***************************************************************************//**
\r
1412 * Copies n bytes from memory area src to memory area dest.
\r
1413 * The memory areas should not overlap.
\r
1415 * @return a pointer to the memory area dest.
\r
1417 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1419 uint8_t *d = dest;
\r
1427 /***************************************************************************//**
\r
1428 * Tx has completed, mark the buffers that were assigned to the Tx descriptors
\r
1432 void MSS_MAC_FreeTxBuffers( void )
\r
1434 if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )
\r
1436 MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );
\r
1437 MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1 );
\r
1441 /***************************************************************************//**
\r
1442 * Look through the array of buffers until one is found that is free for use -
\r
1443 * that is, not currently assigned to an Rx or a Tx descriptor. Mark the buffer
\r
1444 * as in use, then return its address.
\r
1446 * @return a pointer to a free buffer.
\r
1448 unsigned char *MAC_obtain_buffer( void )
\r
1451 unsigned char *pcReturn = NULL;
\r
1453 /* Find and return the address of a buffer that is not being used. Mark
\r
1454 the buffer as now in use. */
\r
1455 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1457 if( ucMACBufferInUse[ lIndex ] == pdFALSE )
\r
1459 pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
\r
1460 ucMACBufferInUse[ lIndex ] = pdTRUE;
\r
1465 configASSERT( pcReturn );
\r
1469 /***************************************************************************//**
\r
1470 * Return a buffer to the list of free buffers, it was in use, but is not now.
\r
1473 void MAC_release_buffer( unsigned char *pucBufferToRelease )
\r
1477 /* uip_buf is going to point to a different buffer - first ensure the buffer
\r
1478 it is currently pointing to is marked as being free again. */
\r
1479 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1481 if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
\r
1483 /* This is the buffer in use, mark it as being free. */
\r
1484 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1489 configASSERT( lIndex < macNUM_BUFFERS );
\r
1494 #ifdef __cplusplus
\r
1498 /******************************** END OF FILE *********************************/
\r