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
16 #include "FreeRTOS.h"
\r
21 #include "mss_ethernet_mac.h"
\r
22 #include "mss_ethernet_mac_regs.h"
\r
23 #include "mss_ethernet_mac_desc.h"
\r
24 #include "mss_ethernet_mac_conf.h"
\r
25 #include "../../CMSIS/mss_assert.h"
\r
29 /**************************** INTERNAL DEFINES ********************************/
\r
31 #define MAC_CHECK(CHECK,ERRNO) \
\r
32 {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); ASSERT((CHECK));}}
\r
37 #define FLAG_MAC_INIT_DONE 1u
\r
38 #define FLAG_PERFECT_FILTERING 2u
\r
39 #define FLAG_CRC_DISABLE 4u
\r
40 #define FLAG_EXCEED_LIMIT 8u
\r
46 #define MAC_FAIL (-1)
\r
47 #define MAC_WRONG_PARAMETER (-2)
\r
48 #define MAC_TOO_BIG_PACKET (-3)
\r
49 #define MAC_BUFFER_IS_FULL (-4)
\r
50 #define MAC_NOT_ENOUGH_SPACE (-5)
\r
51 #define MAC_TIME_OUT (-6)
\r
52 #define MAC_TOO_SMALL_PACKET (-7)
\r
54 /* Allocating this many buffers will always ensure there is one free as, even
\r
55 though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
\r
56 to the same buffer. */
\r
57 #define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE
\r
58 #define macBUFFER_SIZE 1500
\r
60 /***************************************************************/
\r
61 MAC_instance_t g_mss_mac;
\r
63 /**************************** INTERNAL DATA ***********************************/
\r
64 #define ERROR_MESSAGE_COUNT 8
\r
65 #define MAX_ERROR_MESSAGE_WIDTH 40
\r
66 static const int8_t unknown_error[] = "Unknown error";
\r
67 static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
\r
70 "Wrong parameter pased to function",
\r
71 "Frame is too long",
\r
72 "Not enough space in buffer",
\r
73 "Not enough space in buffer",
\r
75 "Frame is too small"
\r
81 static MAC_instance_t* NULL_instance;
\r
82 static uint8_t* NULL_buffer;
\r
83 static MSS_MAC_callback_t NULL_callback;
\r
84 unsigned char *uip_buf = NULL;
\r
86 /**************************** INTERNAL FUNCTIONS ******************************/
\r
88 static int32_t MAC_test_instance( void );
\r
90 static int32_t MAC_dismiss_bad_frames( void );
\r
91 static int32_t MAC_send_setup_frame( void );
\r
93 static int32_t MAC_stop_transmission( void );
\r
94 static void MAC_start_transmission( void );
\r
95 static int32_t MAC_stop_receiving( void );
\r
96 static void MAC_start_receiving( void );
\r
98 static void MAC_set_time_out( uint32_t time_out );
\r
99 static uint32_t MAC_get_time_out( void );
\r
101 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n);
\r
102 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);
\r
103 static void MAC_memset_All(MAC_instance_t *s, uint32_t c);
\r
105 static unsigned char *MAC_obtain_buffer( void );
\r
106 static void MAC_release_buffer( unsigned char *pcBufferToRelease );
\r
108 #if( TX_RING_SIZE != 2 )
\r
109 #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2
\r
112 /* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */
\r
113 static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
\r
115 /* Each array position indicated whether or not the buffer of the same index
\r
116 is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */
\r
117 static unsigned char ucMACBufferFree[ macNUM_BUFFERS ];
\r
119 /***************************************************************************//**
\r
120 * Initializes the Ethernet Controller.
\r
121 * This function will prepare the Ethernet Controller for first time use in a
\r
122 * given hardware/software configuration. This function should be called before
\r
123 * any other Ethernet API functions are called.
\r
125 * Initialization of registers - config registers, enable Tx/Rx interrupts,
\r
126 * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address
\r
127 * filter table (unicats/multicast)/hash init
\r
132 uint8_t phy_address
\r
135 const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };
\r
138 /* To start with all buffers are free. */
\r
139 for( a = 0; a < macNUM_BUFFERS; a++ )
\r
141 ucMACBufferFree[ a ] = pdTRUE;
\r
144 /* Try to reset chip */
\r
145 MAC_BITBAND->CSR0_SWR = 1u;
\r
150 } while ( 1u == MAC_BITBAND->CSR0_SWR );
\r
152 /* Check reset values of some registers to constrol
\r
153 * base address validity */
\r
154 ASSERT( MAC->CSR0 == 0xFE000000uL );
\r
155 ASSERT( MAC->CSR5 == 0xF0000000uL );
\r
156 ASSERT( MAC->CSR6 == 0x32000040uL );
\r
158 /* Instance setup */
\r
159 MAC_memset_All( &g_mss_mac, 0u );
\r
161 g_mss_mac.base_address = MAC_BASE;
\r
162 g_mss_mac.phy_address = phy_address;
\r
164 for( a=0; a<RX_RING_SIZE; a++ )
\r
166 /* Give the ownership to the MAC */
\r
167 g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;
\r
168 g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);
\r
170 /* Allocate a buffer to the descriptor, then mark the buffer as in use
\r
172 g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] );
\r
173 ucMACBufferFree[ a ] = pdFALSE;
\r
175 g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
\r
177 for( a = 0; a < TX_RING_SIZE; a++ )
\r
179 /* Buffers only get allocated to the Tx buffers when something is
\r
180 actually tranmitted. */
\r
181 g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL;
\r
183 g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;
\r
185 /* Configurable settings */
\r
186 MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;
\r
187 MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);
\r
188 MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;
\r
189 MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
\r
191 /* Fixed settings */
\r
192 /* No automatic polling */
\r
193 MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;
\r
194 /* No space between descriptors */
\r
195 MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
\r
196 /* General-purpose timer works in continuous mode */
\r
197 MAC_BITBAND->CSR11_CON = 1u;
\r
198 /* Start general-purpose */
\r
199 MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
\r
201 /* Disable promiscuous mode */
\r
202 MAC_BITBAND->CSR6_PR = 0u;
\r
204 /* Enable store and forward */
\r
205 MAC_BITBAND->CSR6_SF = 1u;
\r
207 /* Set descriptors */
\r
208 MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
\r
209 MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);
\r
211 /* enable normal interrupts */
\r
212 MAC_BITBAND->CSR7_NIE = 1u;
\r
215 if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
\r
218 ASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
\r
225 g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;
\r
227 /* Configure chip according to PHY status */
\r
228 MSS_MAC_auto_setup_link();
\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_filters( 0u, NULL_buffer );
\r
233 MAC_BITBAND->CSR6_RA = 1; /* Receive all. */
\r
237 /***************************************************************************//**
\r
238 * Sets the configuration of the Ethernet Controller.
\r
239 * After the EthernetInit function has been called, this API function can be
\r
240 * used to configure the various features of the Ethernet Controller.
\r
242 * @param instance Pointer to a MAC_instance_t structure
\r
243 * @param config The logical OR of the following values:
\r
244 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
245 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
246 * - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD
\r
247 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
248 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
249 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
250 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
251 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
252 * @see MAC_get_configuration()
\r
257 uint32_t configuration
\r
262 ASSERT( MAC_test_instance() == MAC_OK );
\r
264 ret = MAC_stop_transmission();
\r
265 ASSERT( ret == MAC_OK );
\r
267 ret = MAC_stop_receiving();
\r
268 ASSERT( ret == MAC_OK );
\r
270 MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
\r
271 MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
\r
272 MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
\r
274 switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
\r
275 case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
\r
276 MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
\r
278 case MSS_MAC_CFG_THRESHOLD_CONTROL_01:
\r
279 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );
\r
281 case MSS_MAC_CFG_THRESHOLD_CONTROL_10:
\r
282 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );
\r
284 case MSS_MAC_CFG_THRESHOLD_CONTROL_11:
\r
285 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );
\r
290 MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );
\r
291 MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );
\r
292 MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );
\r
293 MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );
\r
294 PHY_set_link_type( (uint8_t)
\r
295 ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |
\r
296 (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );
\r
298 MSS_MAC_auto_setup_link();
\r
302 /***************************************************************************//**
\r
303 * Returns the configuration of the Ethernet Controller.
\r
305 * @param instance Pointer to a MAC_instance_t structure
\r
306 * @return The logical OR of the following values:
\r
307 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
308 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
309 * - #MSS_MAC_CFG_STORE_AND_FORWARD
\r
310 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
311 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
312 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
313 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
314 * - #MSS_MAC_CFG_INVERSE_FILTERING
\r
315 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
316 * - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE
\r
317 * - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE
\r
318 * @see MAC_configure()
\r
321 MSS_MAC_get_configuration( void )
\r
323 uint32_t configuration;
\r
325 ASSERT( MAC_test_instance() == MAC_OK );
\r
327 configuration = 0u;
\r
328 if( MAC_BITBAND->CSR6_RA != 0u ) {
\r
329 configuration |= MSS_MAC_CFG_RECEIVE_ALL;
\r
332 if( MAC_BITBAND->CSR6_TTM != 0u ) {
\r
333 configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;
\r
336 if( MAC_BITBAND->CSR6_SF != 0u ) {
\r
337 configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;
\r
340 switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {
\r
341 case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;
\r
342 case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;
\r
343 case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;
\r
346 if( MAC_BITBAND->CSR6_FD != 0u ) {
\r
347 configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;
\r
350 if( MAC_BITBAND->CSR6_PM != 0u ) {
\r
351 configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;
\r
354 if( MAC_BITBAND->CSR6_PR != 0u ) {
\r
355 configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;
\r
358 if( MAC_BITBAND->CSR6_IF != 0u ) {
\r
359 configuration |= MSS_MAC_CFG_INVERSE_FILTERING;
\r
362 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
363 configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;
\r
366 if( MAC_BITBAND->CSR6_HO != 0u ) {
\r
367 configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;
\r
370 if( MAC_BITBAND->CSR6_HP != 0u ) {
\r
371 configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
\r
374 return (int32_t)configuration;
\r
378 /***************************************************************************//**
\r
379 Sends a packet from the uIP stack to the Ethernet Controller.
\r
380 The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
\r
381 MAC. This function writes uip_len bytes of the packet contained in uip_buf into
\r
382 the transmit FIFO and then activates the transmitter for this packet. If space
\r
383 is available in the FIFO, the function will return once pac_len bytes of the
\r
384 packet have been placed into the FIFO and the transmitter has been started.
\r
385 This function will not wait for the transmission to complete.
\r
388 The function returns zero if a timeout occurs otherwise it returns size of the packet.
\r
390 @see MAC_rx_packet()
\r
396 unsigned short usLength
\r
400 unsigned long ulDescriptor;
\r
401 int32_t error = MAC_OK;
\r
402 extern unsigned char *uip_buf;
\r
404 ASSERT( MAC_test_instance() == MAC_OK );
\r
406 ASSERT( uip_buf != NULL_buffer );
\r
408 ASSERT( usLength >= 12 );
\r
410 if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
\r
412 ASSERT( usLength <= MSS_MAX_PACKET_SIZE );
\r
415 /* Check if second descriptor is free, if it is then the first must
\r
417 if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
\r
419 error = MAC_BUFFER_IS_FULL;
\r
422 if( error == MAC_OK ) {
\r
423 /* Assumed TX_RING_SIZE == 2. */
\r
424 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
\r
426 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u;
\r
428 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
429 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC;
\r
432 /* Every buffer can hold a full frame so they are always first and last
\r
434 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS;
\r
436 /* set data size */
\r
437 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength;
\r
439 /* reset end of ring */
\r
440 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
442 if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
444 usLength = (uint16_t)MSS_TX_BUFF_SIZE;
\r
447 /* The data buffer is assigned to the Tx descriptor. */
\r
448 g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf;
\r
450 /* update counters */
\r
451 desc = g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0;
\r
452 if( (desc & TDES0_LO) != 0u ) {
\r
453 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
455 if( (desc & TDES0_NC) != 0u ) {
\r
456 g_mss_mac.statistics.tx_no_carrier++;
\r
458 if( (desc & TDES0_LC) != 0u ) {
\r
459 g_mss_mac.statistics.tx_late_collision++;
\r
461 if( (desc & TDES0_EC) != 0u ) {
\r
462 g_mss_mac.statistics.tx_excessive_collision++;
\r
464 if( (desc & TDES0_UF) != 0u ) {
\r
465 g_mss_mac.statistics.tx_underflow_error++;
\r
467 g_mss_mac.statistics.tx_collision_count +=
\r
468 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
470 /* Give ownership of descriptor to the MAC */
\r
471 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = TDES0_OWN;
\r
473 g_mss_mac.tx_desc_index = 0;
\r
477 /* Start transmission */
\r
478 MAC_start_transmission();
\r
480 /* transmit poll demand */
\r
485 if (error == MAC_OK)
\r
487 /* The buffer uip_buf was pointing to is now under the control of the
\r
488 MAC (it is being transmitted). Set uip_buf to point to a free buffer. */
\r
489 uip_buf = MAC_obtain_buffer();
\r
490 error = (int32_t)usLength;
\r
500 /***************************************************************************//**
\r
501 * Returns available packet size.
\r
503 * @param instance Pointer to a MAC_instance_t structure
\r
504 * @return size of packet, bigger than 0, if a packet is available.
\r
505 * If not, returns 0.
\r
506 * @see MAC_rx_packet()
\r
509 MSS_MAC_rx_pckt_size
\r
515 ASSERT( MAC_test_instance() == MAC_OK );
\r
517 MAC_dismiss_bad_frames();
\r
519 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
\r
521 /* Current descriptor is empty */
\r
526 uint32_t frame_length;
\r
527 frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;
\r
528 retval = (int32_t)( frame_length );
\r
534 /***************************************************************************//**
\r
535 * Receives a packet from the Ethernet Controller into the uIP stack.
\r
536 * This function reads a packet from the receive FIFO of the controller and
\r
537 * places it into uip_buf.
\r
539 * @return Size of packet if packet fits in uip_buf.
\r
540 * 0 if there is no received packet.
\r
541 * @see MAC_rx_pckt_size()
\r
542 * @see MAC_tx_packet()
\r
550 uint16_t frame_length=0u;
\r
552 ASSERT( MAC_test_instance() == MAC_OK );
\r
554 MAC_dismiss_bad_frames();
\r
556 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
\r
559 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
560 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
563 frame_length -= 4u;
\r
565 if( frame_length > macBUFFER_SIZE ) {
\r
566 return MAC_NOT_ENOUGH_SPACE;
\r
569 /* uip_buf is about to point to the buffer that contains the received
\r
570 data, mark the buffer that uip_buf is currently pointing to as free
\r
572 MAC_release_buffer( uip_buf );
\r
573 uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
575 /* The buffer the Rx descriptor was pointing to is now in use by the
\r
576 uIP stack - allocate a new buffer to the Rx descriptor. */
\r
577 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();
\r
579 MSS_MAC_prepare_rx_descriptor();
\r
581 return ((int32_t)frame_length);
\r
585 /***************************************************************************//**
\r
586 * Receives a packet from the Ethernet Controller.
\r
587 * This function reads a packet from the receive FIFO of the controller and
\r
588 * sets the address of pacData to the received data.
\r
589 * If time_out parameter is zero the function will return
\r
590 * immediately (after the copy operation if data is available. Otherwise the function
\r
591 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
592 * value is given as time_out, function will wait for the reception to complete.
\r
594 * @param instance Pointer to a MAC_instance_t structure
\r
595 * @param pacData The pointer to the packet data.
\r
596 * @param time_out Time out value in milli seconds for receiving.
\r
597 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
598 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
599 * if there is no packet waiting.
\r
600 * Otherwise value must be greater than 0 and smaller than
\r
602 * @return Size of packet if packet fits in pacData.
\r
603 * 0 if there is no received packet.
\r
604 * @see MAC_rx_pckt_size()
\r
605 * @see MAC_tx_packet()
\r
608 MSS_MAC_rx_packet_ptrset
\r
614 uint16_t frame_length = 0u;
\r
617 ASSERT( MAC_test_instance() == MAC_OK );
\r
619 ASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
620 (time_out == MSS_MAC_NONBLOCKING) ||
\r
621 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
623 MAC_dismiss_bad_frames();
\r
625 /* wait for a packet */
\r
626 if( time_out != MSS_MAC_BLOCKING ) {
\r
627 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
628 MAC_set_time_out( 0u );
\r
630 MAC_set_time_out( time_out );
\r
634 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
635 RDES0_OWN) != 0u) && (exit == 0) )
\r
637 if( time_out != MSS_MAC_BLOCKING )
\r
639 if( MAC_get_time_out() == 0u ) {
\r
648 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
649 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
652 frame_length -= 4u;
\r
654 /* Here we are setting the buffer 'pacData' address to the address
\r
655 RX descriptor address. After this is called, the following function
\r
656 must be called 'MAC_prepare_rx_descriptor'
\r
657 to prepare the current rx descriptor for receiving the next packet.
\r
659 *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
\r
662 return ((int32_t)frame_length);
\r
665 /***************************************************************************//**
\r
666 * Returns the status of connection.
\r
668 * @return the logical OR of the following values:
\r
669 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
670 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
671 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
672 * @see MAC_auto_setup_link()
\r
675 MSS_MAC_link_status
\r
682 ASSERT( MAC_test_instance() == MAC_OK );
\r
684 link = PHY_link_status();
\r
685 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
686 link |= PHY_link_type();
\r
689 return ((int32_t)link);
\r
693 /***************************************************************************//**
\r
694 * Setups the link between PHY and MAC and returns the status of connection.
\r
696 * @return the logical OR of the following values:
\r
697 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
698 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
699 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
700 * @see MAC_link_status()
\r
703 MSS_MAC_auto_setup_link
\r
709 ASSERT( MAC_test_instance() == MAC_OK );
\r
711 PHY_auto_negotiate();
\r
713 link = MSS_MAC_link_status();
\r
715 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
717 ret = MAC_stop_transmission();
\r
718 MAC_CHECK( ret == MAC_OK, ret );
\r
720 ret = MAC_stop_receiving();
\r
721 MAC_CHECK( ret == MAC_OK, ret );
\r
722 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
723 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
724 MAC_start_transmission();
\r
725 MAC_start_receiving();
\r
732 /***************************************************************************//**
\r
733 * Sets mac address. New address must be unicast.
\r
735 * @param new_address Pointer to a MAC_instance_t structure
\r
736 * @see MAC_get_mac_address()
\r
739 MSS_MAC_set_mac_address
\r
741 const uint8_t *new_address
\r
744 ASSERT( MAC_test_instance() == MAC_OK );
\r
745 /* Check if the new address is unicast */
\r
746 ASSERT( (new_address[0]&1) == 0 );
\r
748 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
750 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
752 /* set unused filters to the new mac address */
\r
753 for( a=14*6; a>=0; a-=6 ) {
\r
754 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
755 /* Filters with multicast addresses are used */
\r
758 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
759 g_mss_mac.mac_address, 6u );
\r
764 MAC_send_setup_frame();
\r
768 /***************************************************************************//**
\r
769 * Returns mac address.
\r
771 * @param address Pointer to receive the MAC address
\r
772 * @see MAC_set_mac_address()
\r
775 MSS_MAC_get_mac_address
\r
780 ASSERT( MAC_test_instance() == MAC_OK );
\r
782 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
786 /***************************************************************************//**
\r
787 * Sets mac address filters. Addresses must be multicast.
\r
789 * @param filter_count number of addresses
\r
790 * @param filters Pointer to addresses to be filtered
\r
793 MSS_MAC_set_mac_filters
\r
795 uint16_t filter_count,
\r
796 const uint8_t *filters
\r
799 ASSERT( MAC_test_instance() == MAC_OK );
\r
800 ASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
801 /* Check if the mac addresses is multicast */
\r
804 for( a = 0u; a < filter_count; a++ ) {
\r
805 ASSERT( (filters[a*6]&1) == 1 );
\r
809 if( filter_count <= 15 ){
\r
811 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
813 /* copy new filters */
\r
814 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
816 /* set unused filters to our mac address */
\r
817 for( a=filter_count; a<15; a++ ) {
\r
818 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
819 g_mss_mac.mac_address, 6 );
\r
825 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
827 /* reset hash table */
\r
828 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
830 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
831 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
832 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
836 MAC_send_setup_frame();
\r
840 /***************************************************************************//**
\r
841 * MAC interrupt service routine.
\r
843 * @param instance Pointer to a MAC_instance_t structure
\r
844 * @see MAC_set_callback()
\r
846 #if defined(__GNUC__)
\r
847 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
849 void EthernetMAC_IRQHandler( void )
\r
853 uint32_t intr_status;
\r
855 ASSERT( MAC_test_instance() == MAC_OK );
\r
858 intr_status = MAC->CSR5;
\r
860 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
861 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
862 g_mss_mac.statistics.tx_interrupts++;
\r
863 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
866 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
867 g_mss_mac.statistics.rx_interrupts++;
\r
868 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
872 /* Clear interrupts */
\r
873 MAC->CSR5 = CSR5_INT_BITS;
\r
875 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
876 g_mss_mac.listener( events );
\r
881 /***************************************************************************//**
\r
882 * Sets MAC event listener.
\r
883 * Sets the given event listener function to be triggered inside MAC_isr().
\r
884 * Assigning NULL pointer as the listener function will disable it.
\r
886 * @param instance Pointer to a MAC_instance_t structure
\r
887 * @param listener function pointer to a MAC_callback_t function
\r
888 * @return #MAC_OK if everything is OK
\r
889 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
894 MSS_MAC_set_callback
\r
896 MSS_MAC_callback_t listener
\r
899 ASSERT( MAC_test_instance() == MAC_OK );
\r
901 /* disable tx and rx interrupts */
\r
902 MAC_BITBAND->CSR7_RIE = 0u;
\r
903 MAC_BITBAND->CSR7_TIE = 0u;
\r
905 g_mss_mac.listener = listener;
\r
907 if( listener != NULL_callback ) {
\r
908 /* enable tx and rx interrupts */
\r
909 MAC_BITBAND->CSR7_RIE = 1u;
\r
910 MAC_BITBAND->CSR7_TIE = 1u;
\r
915 /***************************************************************************//**
\r
916 * Returns description of last error.
\r
918 * @param instance Pointer to a MAC_instance_t structure
\r
919 * @return A string describing the error. This string must not be
\r
920 * modified by the application.
\r
921 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
930 int8_t error_msg_nb;
\r
931 const int8_t* returnvalue;
\r
933 ASSERT( MAC_test_instance() == MAC_OK );
\r
935 error_msg_nb = -(g_mss_mac.last_error);
\r
936 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
937 returnvalue = unknown_error;
\r
939 returnvalue = ErrorMessages[error_msg_nb];
\r
941 return returnvalue;
\r
945 /***************************************************************************//**
\r
946 * Returns statistics counter of stat_id identifier.
\r
948 * @param instance Pointer to a MAC_instance_t structure
\r
949 * @param stat_id Identifier of statistics counter.
\r
950 * @return Statistics counter of stat_id identifier.
\r
951 * On error returns 0.
\r
954 MSS_MAC_get_statistics
\r
956 mss_mac_statistics_id_t stat_id
\r
959 uint32_t returnval = 0u;
\r
960 ASSERT( MAC_test_instance() == MAC_OK );
\r
962 switch( stat_id ) {
\r
963 case MSS_MAC_RX_INTERRUPTS:
\r
964 returnval = g_mss_mac.statistics.rx_interrupts;
\r
966 case MSS_MAC_RX_FILTERING_FAIL:
\r
967 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
969 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
970 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
972 case MSS_MAC_RX_RUNT_FRAME:
\r
973 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
975 case MSS_MAC_RX_NOT_FIRST:
\r
976 returnval = g_mss_mac.statistics.rx_not_first;
\r
978 case MSS_MAC_RX_NOT_LAST:
\r
979 returnval = g_mss_mac.statistics.rx_not_last;
\r
981 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
982 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
984 case MSS_MAC_RX_COLLISION_SEEN:
\r
985 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
987 case MSS_MAC_RX_CRC_ERROR:
\r
988 returnval = g_mss_mac.statistics.rx_crc_error;
\r
990 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
991 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
993 case MSS_MAC_RX_MISSED_FRAME:
\r
994 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
996 case MSS_MAC_TX_INTERRUPTS:
\r
997 returnval = g_mss_mac.statistics.tx_interrupts;
\r
999 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
1000 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
1002 case MSS_MAC_TX_NO_CARRIER:
\r
1003 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
1005 case MSS_MAC_TX_LATE_COLLISION:
\r
1006 returnval = g_mss_mac.statistics.tx_late_collision;
\r
1008 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
1009 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
1011 case MSS_MAC_TX_COLLISION_COUNT:
\r
1012 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1014 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1015 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1025 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1027 /***************************************************************************//**
\r
1028 * Checks if instace is valid.
\r
1038 int32_t retval = MAC_WRONG_PARAMETER;
\r
1043 if( (&g_mss_mac != NULL_instance) &&
\r
1044 ((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&
\r
1045 ( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&
\r
1046 (val2 == (uint32_t)g_mss_mac.tx_descriptors ) )
\r
1053 /***************************************************************************//**
\r
1054 * Prepares current rx descriptor for receiving.
\r
1057 MSS_MAC_prepare_rx_descriptor
\r
1064 /* update counters */
\r
1065 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1066 if( (desc & RDES0_FF) != 0u ) {
\r
1067 g_mss_mac.statistics.rx_filtering_fail++;
\r
1069 if( (desc & RDES0_DE) != 0u ) {
\r
1070 g_mss_mac.statistics.rx_descriptor_error++;
\r
1072 if( (desc & RDES0_RF) != 0u ) {
\r
1073 g_mss_mac.statistics.rx_runt_frame++;
\r
1075 if( (desc & RDES0_FS) == 0u ) {
\r
1076 g_mss_mac.statistics.rx_not_first++;
\r
1078 if( (desc & RDES0_LS) == 0u ) {
\r
1079 g_mss_mac.statistics.rx_not_last++;
\r
1081 if( (desc & RDES0_TL) != 0u ) {
\r
1082 g_mss_mac.statistics.rx_frame_too_long++;
\r
1084 if( (desc & RDES0_CS) != 0u ) {
\r
1085 g_mss_mac.statistics.rx_collision_seen++;
\r
1087 if( (desc & RDES0_CE) != 0u ) {
\r
1088 g_mss_mac.statistics.rx_crc_error++;
\r
1092 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1093 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1094 g_mss_mac.statistics.rx_missed_frame +=
\r
1095 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1097 /* Give ownership of descriptor to the MAC */
\r
1098 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =
\r
1100 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1102 /* Start receive */
\r
1103 MAC_start_receiving();
\r
1107 /***************************************************************************//**
\r
1108 * Prepares a setup frame and sends it to MAC.
\r
1109 * This function is blocking.
\r
1110 * @return #MAC_OK if everything is ok.
\r
1111 * #MAC_TIME_OUT if timed out before packet send.
\r
1114 MAC_send_setup_frame
\r
1119 volatile MAC_descriptor_t descriptor;
\r
1120 uint8_t frame_data[192];
\r
1125 /* prepare descriptor */
\r
1126 descriptor.descriptor_0 = TDES0_OWN;
\r
1127 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1128 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1130 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1131 descriptor.descriptor_1 |= TDES1_FT0;
\r
1134 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1135 descriptor.buffer_2 = 0u;
\r
1137 /* prepare frame */
\r
1138 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1148 data = g_mss_mac.mac_address;
\r
1149 frame_data[b] = data[0];
\r
1150 frame_data[b+1] = data[1];
\r
1151 frame_data[b+4] = data[2];
\r
1152 frame_data[b+5] = data[3];
\r
1153 frame_data[b+8] = data[4];
\r
1154 frame_data[b+9] = data[5];
\r
1156 data = g_mss_mac.mac_filter_data;
\r
1157 for( a = 0; a < c; ) {
\r
1158 frame_data[d] = data[a++];
\r
1159 frame_data[d+1] = data[a++];
\r
1160 frame_data[d+4] = data[a++];
\r
1161 frame_data[d+5] = data[a++];
\r
1162 frame_data[d+8] = data[a++];
\r
1163 frame_data[d+9] = data[a++];
\r
1167 /* Stop transmission */
\r
1168 ret = MAC_stop_transmission();
\r
1169 ASSERT( ret == MAC_OK );
\r
1171 ret = MAC_stop_receiving();
\r
1172 ASSERT( ret == MAC_OK );
\r
1174 /* Set descriptor */
\r
1175 MAC->CSR4 = (uint32_t)&descriptor;
\r
1177 /* Start transmission */
\r
1178 MAC_start_transmission();
\r
1180 /* Wait until transmission over */
\r
1182 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1184 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1185 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1187 /* transmit poll demand */
\r
1189 if( MAC_get_time_out() == 0u ) {
\r
1190 ret = MAC_TIME_OUT;
\r
1194 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1196 /* Set tx descriptor */
\r
1197 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1199 /* Start receiving and transmission */
\r
1200 MAC_start_receiving();
\r
1201 MAC_start_transmission();
\r
1207 /***************************************************************************//**
\r
1208 * Stops transmission.
\r
1209 * Function will wait until transmit operation enters stop state.
\r
1211 * @return #MAC_OK if everything is ok.
\r
1212 * #MAC_TIME_OUT if timed out.
\r
1215 MAC_stop_transmission
\r
1220 int32_t retval = MAC_OK;
\r
1221 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1223 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1224 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1226 MAC_BITBAND->CSR6_ST = 0u;
\r
1227 if( MAC_get_time_out() == 0u ) {
\r
1228 retval = MAC_TIME_OUT;
\r
1235 /***************************************************************************//**
\r
1236 * Starts transmission.
\r
1239 MAC_start_transmission
\r
1244 MAC_BITBAND->CSR6_ST = 1u;
\r
1248 /***************************************************************************//**
\r
1249 * Stops transmission.
\r
1250 * Function will wait until transmit operation enters stop state.
\r
1252 * @return #MAC_OK if everything is ok.
\r
1253 * #MAC_TIME_OUT if timed out.
\r
1256 MAC_stop_receiving
\r
1261 int32_t retval = MAC_OK;
\r
1262 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1264 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1265 && (retval == MAC_OK) )
\r
1267 MAC_BITBAND->CSR6_SR = 0u;
\r
1268 if( MAC_get_time_out() == 0u ) {
\r
1269 retval = MAC_TIME_OUT;
\r
1277 /***************************************************************************//**
\r
1278 * Starts transmission.
\r
1281 MAC_start_receiving
\r
1286 MAC_BITBAND->CSR6_SR = 1u;
\r
1290 /***************************************************************************//**
\r
1291 * Dismisses bad frames.
\r
1293 * @return dismissed frame count.
\r
1296 MAC_dismiss_bad_frames
\r
1304 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1305 /* User wants bad frames too, don't dismiss anything */
\r
1309 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1310 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1312 /* check error summary */
\r
1313 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1314 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1316 MSS_MAC_prepare_rx_descriptor();
\r
1328 /***************************************************************************//**
\r
1329 * Sets time out value.
\r
1330 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1331 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1333 * @time_out time out value in milli seconds.
\r
1334 * Must be smaller than 0x01000000.
\r
1342 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1344 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1347 /***************************************************************************//**
\r
1348 * Returns time out value.
\r
1350 * @return timer out value in milli seconds.
\r
1359 uint32_t time = 0u;
\r
1361 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1363 if( timer > g_mss_mac.last_timer_value ) {
\r
1364 time = 0x0000ffffUL;
\r
1366 time += g_mss_mac.last_timer_value - timer;
\r
1368 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1371 if( g_mss_mac.time_out_value <= time ){
\r
1372 g_mss_mac.time_out_value = 0u;
\r
1374 g_mss_mac.time_out_value -= time;
\r
1377 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1379 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1382 /***************************************************************************//**
\r
1383 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1386 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1396 /***************************************************************************//**
\r
1397 * Fills all fields of MAC_instance_t with c.
\r
1399 * @return a pointer to the given MAC_instance_t s.
\r
1401 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1404 s->base_address = (addr_t)c;
\r
1405 s->flags = (uint8_t)c;
\r
1406 s->last_error = (int8_t)c;
\r
1407 s->last_timer_value = (uint16_t)c;
\r
1408 s->listener = NULL_callback;
\r
1409 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1410 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1411 s->phy_address = (uint8_t)c;
\r
1412 // for(count = 0; count<RX_RING_SIZE ;count++)
\r
1414 // MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
\r
1416 s->rx_desc_index =c;
\r
1417 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1419 s->rx_descriptors[count].buffer_1 = c;
\r
1420 s->rx_descriptors[count].buffer_2 = c;
\r
1421 s->rx_descriptors[count].descriptor_0 = c;
\r
1422 s->rx_descriptors[count].descriptor_1 = c;
\r
1424 s->statistics.rx_collision_seen =c;
\r
1425 s->statistics.rx_crc_error = c;
\r
1426 s->statistics.rx_descriptor_error = c;
\r
1427 s->statistics.rx_fifo_overflow = c;
\r
1428 s->statistics.rx_filtering_fail = c;
\r
1429 s->statistics.rx_frame_too_long = c;
\r
1430 s->statistics.rx_interrupts = c;
\r
1431 s->statistics.rx_missed_frame = c;
\r
1432 s->statistics.rx_not_first = c;
\r
1433 s->statistics.rx_not_last = c;
\r
1434 s->statistics.rx_runt_frame = c;
\r
1435 s->statistics.tx_collision_count = c;
\r
1436 s->statistics.tx_excessive_collision = c;
\r
1437 s->statistics.tx_interrupts = c;
\r
1438 s->statistics.tx_late_collision = c;
\r
1439 s->statistics.tx_loss_of_carrier = c;
\r
1440 s->statistics.tx_no_carrier = c;
\r
1441 s->statistics.tx_underflow_error = c;
\r
1442 s->time_out_value = c;
\r
1443 // for(count = 0; count < TX_RING_SIZE ;count++)
\r
1445 // MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
\r
1447 s->tx_desc_index = c;
\r
1448 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1450 s->tx_descriptors[count].buffer_1 = c;
\r
1451 s->tx_descriptors[count].buffer_2 = c;
\r
1452 s->tx_descriptors[count].descriptor_0 = c;
\r
1453 s->tx_descriptors[count].descriptor_1 = c;
\r
1457 /***************************************************************************//**
\r
1458 * Copies n bytes from memory area src to memory area dest.
\r
1459 * The memory areas should not overlap.
\r
1461 * @return a pointer to the memory area dest.
\r
1463 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1465 uint8_t *d = dest;
\r
1473 void MSS_MAC_TxBufferCompleted( void )
\r
1475 unsigned char *pxTransmittedBuffer;
\r
1477 /* Was it the second transmission that has completed? */
\r
1478 if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )
\r
1480 pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1;
\r
1482 /* The buffer has been transmitted and is no longer in use. */
\r
1483 MAC_release_buffer( pxTransmittedBuffer );
\r
1487 static unsigned char *MAC_obtain_buffer( void )
\r
1490 unsigned char *pcReturn = NULL;
\r
1492 /* Find and return the address of a buffer that is not being used. Mark
\r
1493 the buffer as now in use. */
\r
1494 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1496 if( ucMACBufferFree[ lIndex ] == pdTRUE )
\r
1498 pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] );
\r
1503 configASSERT( pcReturn );
\r
1507 void MAC_release_buffer( unsigned char *pucBufferToRelease )
\r
1511 /* uip_buf is going to point to a different buffer - first ensure the buffer
\r
1512 it is currently pointing to is marked as being free again. */
\r
1513 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1515 if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) )
\r
1517 /* This is the buffer in use, mark it as being free. */
\r
1518 ucMACBufferFree[ lIndex ] = pdTRUE;
\r
1526 #ifdef __cplusplus
\r
1530 /******************************** END OF FILE *********************************/
\r