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
20 #include "mss_ethernet_mac.h"
\r
21 #include "mss_ethernet_mac_regs.h"
\r
22 #include "mss_ethernet_mac_desc.h"
\r
23 #include "mss_ethernet_mac_conf.h"
\r
24 #include "../../CMSIS/mss_assert.h"
\r
28 /**************************** INTERNAL DEFINES ********************************/
\r
30 #define MAC_CHECK(CHECK,ERRNO) \
\r
31 {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); ASSERT((CHECK));}}
\r
36 #define FLAG_MAC_INIT_DONE 1u
\r
37 #define FLAG_PERFECT_FILTERING 2u
\r
38 #define FLAG_CRC_DISABLE 4u
\r
39 #define FLAG_EXCEED_LIMIT 8u
\r
45 #define MAC_FAIL (-1)
\r
46 #define MAC_WRONG_PARAMETER (-2)
\r
47 #define MAC_TOO_BIG_PACKET (-3)
\r
48 #define MAC_BUFFER_IS_FULL (-4)
\r
49 #define MAC_NOT_ENOUGH_SPACE (-5)
\r
50 #define MAC_TIME_OUT (-6)
\r
51 #define MAC_TOO_SMALL_PACKET (-7)
\r
53 /***************************************************************/
\r
54 MAC_instance_t g_mss_mac;
\r
56 /**************************** INTERNAL DATA ***********************************/
\r
57 #define ERROR_MESSAGE_COUNT 8
\r
58 #define MAX_ERROR_MESSAGE_WIDTH 40
\r
59 static const int8_t unknown_error[] = "Unknown error";
\r
60 static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
\r
63 "Wrong parameter pased to function",
\r
64 "Frame is too long",
\r
65 "Not enough space in buffer",
\r
66 "Not enough space in buffer",
\r
68 "Frame is too small"
\r
74 static MAC_instance_t* NULL_instance;
\r
75 static uint8_t* NULL_buffer;
\r
76 static MSS_MAC_callback_t NULL_callback;
\r
78 /**************************** INTERNAL FUNCTIONS ******************************/
\r
80 static int32_t MAC_test_instance( void );
\r
82 static int32_t MAC_dismiss_bad_frames( void );
\r
83 static int32_t MAC_send_setup_frame( void );
\r
85 static int32_t MAC_stop_transmission( void );
\r
86 static void MAC_start_transmission( void );
\r
87 static int32_t MAC_stop_receiving( void );
\r
88 static void MAC_start_receiving( void );
\r
90 static void MAC_set_time_out( uint32_t time_out );
\r
91 static uint32_t MAC_get_time_out( void );
\r
93 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n);
\r
94 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);
\r
95 static void MAC_memset_All(MAC_instance_t *s, uint32_t c);
\r
97 /***************************************************************************//**
\r
98 * Initializes the Ethernet Controller.
\r
99 * This function will prepare the Ethernet Controller for first time use in a
\r
100 * given hardware/software configuration. This function should be called before
\r
101 * any other Ethernet API functions are called.
\r
103 * Initialization of registers - config registers, enable Tx/Rx interrupts,
\r
104 * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address
\r
105 * filter table (unicats/multicast)/hash init
\r
110 uint8_t phy_address
\r
113 const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };
\r
117 /* Try to reset chip */
\r
118 MAC_BITBAND->CSR0_SWR = 1u;
\r
120 while ( 1u == MAC_BITBAND->CSR0_SWR )
\r
125 /* Check reset values of some registers to constrol
\r
126 * base address validity */
\r
127 ASSERT( MAC->CSR0 == 0xFE000000uL );
\r
128 ASSERT( MAC->CSR5 == 0xF0000000uL );
\r
129 ASSERT( MAC->CSR6 == 0x32000040uL );
\r
131 /* Instance setup */
\r
132 MAC_memset_All( &g_mss_mac, 0u );
\r
134 g_mss_mac.base_address = MAC_BASE;
\r
135 g_mss_mac.phy_address = phy_address;
\r
137 for( a=0; a<RX_RING_SIZE; a++ )
\r
139 /* Give the ownership to the MAC */
\r
140 g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;
\r
141 g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);
\r
142 g_mss_mac.rx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.rx_buffers[a];
\r
144 g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
\r
146 for( a = 0; a < TX_RING_SIZE; a++ )
\r
148 g_mss_mac.tx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.tx_buffers[a];
\r
150 g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;
\r
152 /* Configurable settings */
\r
153 MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;
\r
154 MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);
\r
155 MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;
\r
156 MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
\r
158 /* Fixed settings */
\r
159 /* No automatic polling */
\r
160 MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;
\r
161 /* No space between descriptors */
\r
162 MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
\r
163 /* General-purpose timer works in continuous mode */
\r
164 MAC_BITBAND->CSR11_CON = 1u;
\r
165 /* Start general-purpose */
\r
166 MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
\r
168 /* Disable promiscuous mode */
\r
169 MAC_BITBAND->CSR6_PR = 0u;
\r
171 /* Enable store and forward */
\r
172 MAC_BITBAND->CSR6_SF = 1u;
\r
174 /* Set descriptors */
\r
175 MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
\r
176 MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);
\r
178 /* enable normal interrupts */
\r
179 MAC_BITBAND->CSR7_NIE = 1u;
\r
182 if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
\r
185 ASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
\r
192 g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;
\r
194 /* Configure chip according to PHY status */
\r
195 MSS_MAC_auto_setup_link();
\r
197 /* Set default MAC address and reset mac filters */
\r
198 MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
\r
199 MSS_MAC_set_mac_filters( 0u, NULL_buffer );
\r
202 /* Start receiving and transmission */
\r
203 MAC_start_receiving();
\r
204 MAC_start_transmission();
\r
208 /***************************************************************************//**
\r
209 * Sets the configuration of the Ethernet Controller.
\r
210 * After the EthernetInit function has been called, this API function can be
\r
211 * used to configure the various features of the Ethernet Controller.
\r
213 * @param instance Pointer to a MAC_instance_t structure
\r
214 * @param config The logical OR of the following values:
\r
215 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
216 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
217 * - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD
\r
218 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
219 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
220 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
221 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
222 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
223 * @see MAC_get_configuration()
\r
228 uint32_t configuration
\r
233 ASSERT( MAC_test_instance() == MAC_OK );
\r
235 ret = MAC_stop_transmission();
\r
236 ASSERT( ret == MAC_OK );
\r
238 ret = MAC_stop_receiving();
\r
239 ASSERT( ret == MAC_OK );
\r
241 MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
\r
242 MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
\r
243 MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
\r
245 switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
\r
246 case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
\r
247 MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
\r
249 case MSS_MAC_CFG_THRESHOLD_CONTROL_01:
\r
250 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );
\r
252 case MSS_MAC_CFG_THRESHOLD_CONTROL_10:
\r
253 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );
\r
255 case MSS_MAC_CFG_THRESHOLD_CONTROL_11:
\r
256 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );
\r
261 MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );
\r
262 MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );
\r
263 MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );
\r
264 MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );
\r
265 PHY_set_link_type( (uint8_t)
\r
266 ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |
\r
267 (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );
\r
269 MAC_start_transmission();
\r
270 MAC_start_receiving();
\r
272 MSS_MAC_auto_setup_link();
\r
276 /***************************************************************************//**
\r
277 * Returns the configuration of the Ethernet Controller.
\r
279 * @param instance Pointer to a MAC_instance_t structure
\r
280 * @return The logical OR of the following values:
\r
281 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
282 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
283 * - #MSS_MAC_CFG_STORE_AND_FORWARD
\r
284 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
285 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
286 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
287 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
288 * - #MSS_MAC_CFG_INVERSE_FILTERING
\r
289 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
290 * - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE
\r
291 * - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE
\r
292 * @see MAC_configure()
\r
295 MSS_MAC_get_configuration( void )
\r
297 uint32_t configuration;
\r
299 ASSERT( MAC_test_instance() == MAC_OK );
\r
301 configuration = 0u;
\r
302 if( MAC_BITBAND->CSR6_RA != 0u ) {
\r
303 configuration |= MSS_MAC_CFG_RECEIVE_ALL;
\r
306 if( MAC_BITBAND->CSR6_TTM != 0u ) {
\r
307 configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;
\r
310 if( MAC_BITBAND->CSR6_SF != 0u ) {
\r
311 configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;
\r
314 switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {
\r
315 case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;
\r
316 case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;
\r
317 case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;
\r
320 if( MAC_BITBAND->CSR6_FD != 0u ) {
\r
321 configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;
\r
324 if( MAC_BITBAND->CSR6_PM != 0u ) {
\r
325 configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;
\r
328 if( MAC_BITBAND->CSR6_PR != 0u ) {
\r
329 configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;
\r
332 if( MAC_BITBAND->CSR6_IF != 0u ) {
\r
333 configuration |= MSS_MAC_CFG_INVERSE_FILTERING;
\r
336 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
337 configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;
\r
340 if( MAC_BITBAND->CSR6_HO != 0u ) {
\r
341 configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;
\r
344 if( MAC_BITBAND->CSR6_HP != 0u ) {
\r
345 configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
\r
348 return (int32_t)configuration;
\r
352 /***************************************************************************//**
\r
353 Sends a packet to the Ethernet Controller.
\r
354 The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
\r
355 MAC. This function writes pacLen bytes of the packet contained in pacData into
\r
356 the transmit FIFO and then activates the transmitter for this packet. If space
\r
357 is available in the FIFO, the function will return once pacLen bytes of the
\r
358 packet have been placed into the FIFO and the transmitter has been started.
\r
359 This function will not wait for the transmission to complete. If space is not
\r
360 available in FIFO, the function will keep trying until time_out expires. The
\r
361 function will wait for the transmission to complete when the time_out parameter
\r
362 is set to MSS_MAC_BLOCKING.
\r
365 The pacData parameter is a pointer to the packet data to be transmitted.
\r
368 The pacLen parameter is the number of bytes in the packet to be transmitted.
\r
371 The time_out parameter is the timeout value for the transmission in milliseconds.
\r
372 The time_out parameter value can be one of the following values:
\r
373 \95 Unsigned integer greater than 0 and less than 0x01000000
\r
374 \95 MSS_MAC_BLOCKING
\96 there will be no timeout.
\r
375 \95 MSS_MAC_NONBLOCKING
\96 the function will return immediately if the MSS Ethernet
\r
376 MAC does not have any available transmit descriptor. This would happen when
\r
377 several packets are already queued into the MSS Ethernet MAC transmit descriptor FIFO.
\r
380 The function returns zero if a timeout occurs otherwise it returns size of the packet.
\r
382 @see MAC_rx_packet()
\r
388 const uint8_t *pacData,
\r
394 int32_t error = MAC_OK;
\r
396 ASSERT( MAC_test_instance() == MAC_OK );
\r
398 ASSERT( pacData != NULL_buffer );
\r
400 ASSERT( pacLen >= 12 );
\r
402 if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
\r
404 ASSERT( pacLen <= MSS_MAX_PACKET_SIZE );
\r
407 ASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
408 (time_out == MSS_MAC_NONBLOCKING) ||
\r
409 ((time_out >= 1) && (time_out <= 0x01000000uL)) );
\r
411 if( time_out == MSS_MAC_NONBLOCKING )
\r
413 /* Check if current descriptor is free */
\r
414 if(((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
\r
416 error = MAC_BUFFER_IS_FULL;
\r
421 /* Wait until descriptor is free */
\r
422 if( time_out != MSS_MAC_BLOCKING ) {
\r
423 MAC_set_time_out( time_out );
\r
426 while( (((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
\r
427 && (error == MAC_OK) )
\r
429 /* transmit poll demand */
\r
432 if(time_out != MSS_MAC_BLOCKING){
\r
433 if(MAC_get_time_out() == 0u) {
\r
434 error = MAC_TIME_OUT;
\r
440 if( error == MAC_OK ) {
\r
442 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
\r
444 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
445 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
\r
448 /* Every buffer can hold a full frame so they are always first and last
\r
450 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;
\r
452 /* set data size */
\r
453 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= pacLen;
\r
455 /* reset end of ring */
\r
456 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
458 /* copy data into buffer */
\r
459 if( pacLen > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
461 pacLen = (uint16_t)MSS_TX_BUFF_SIZE;
\r
465 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1,
\r
466 pacData, (uint32_t)pacLen );
\r
468 /* update counters */
\r
469 desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
\r
470 if( (desc & TDES0_LO) != 0u ) {
\r
471 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
473 if( (desc & TDES0_NC) != 0u ) {
\r
474 g_mss_mac.statistics.tx_no_carrier++;
\r
476 if( (desc & TDES0_LC) != 0u ) {
\r
477 g_mss_mac.statistics.tx_late_collision++;
\r
479 if( (desc & TDES0_EC) != 0u ) {
\r
480 g_mss_mac.statistics.tx_excessive_collision++;
\r
482 if( (desc & TDES0_UF) != 0u ) {
\r
483 g_mss_mac.statistics.tx_underflow_error++;
\r
485 g_mss_mac.statistics.tx_collision_count +=
\r
486 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
488 /* Give ownership of descriptor to the MAC */
\r
489 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;
\r
491 g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
\r
493 /* Start transmission */
\r
494 MAC_start_transmission();
\r
496 /* transmit poll demand */
\r
500 if (error == MAC_OK)
\r
502 error = (int32_t)pacLen;
\r
512 /***************************************************************************//**
\r
513 * Returns available packet size.
\r
515 * @param instance Pointer to a MAC_instance_t structure
\r
516 * @return size of packet, bigger than 0, if a packet is available.
\r
517 * If not, returns 0.
\r
518 * @see MAC_rx_packet()
\r
521 MSS_MAC_rx_pckt_size
\r
527 ASSERT( MAC_test_instance() == MAC_OK );
\r
529 MAC_dismiss_bad_frames();
\r
531 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
\r
533 /* Current descriptor is empty */
\r
538 uint32_t frame_length;
\r
539 frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;
\r
540 retval = (int32_t)( frame_length );
\r
546 /***************************************************************************//**
\r
547 * Receives a packet from the Ethernet Controller.
\r
548 * This function reads a packet from the receive FIFO of the controller and
\r
549 * places it into pacData. If time_out parameter is zero the function will return
\r
550 * immediately (after the copy operation if data is available. Otherwise the function
\r
551 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
552 * value is given as time_out, function will wait for the reception to complete.
\r
554 * @param instance Pointer to a MAC_instance_t structure
\r
555 * @param pacData The pointer to the packet data.
\r
556 * @param pacLen The pacLen parameter is the size in bytes of the pacData
\r
557 * buffer where the received data will be copied.
\r
558 * @param time_out Time out value in milli seconds for receiving.
\r
559 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
560 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
561 * if there is no packet waiting.
\r
562 * Otherwise value must be greater than 0 and smaller than
\r
564 * @return Size of packet if packet fits in pacData.
\r
565 * 0 if there is no received packet.
\r
566 * @see MAC_rx_pckt_size()
\r
567 * @see MAC_tx_packet()
\r
572 unsigned char **pacData,
\r
577 uint16_t frame_length=0u;
\r
580 ASSERT( MAC_test_instance() == MAC_OK );
\r
581 ASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
582 (time_out == MSS_MAC_NONBLOCKING) ||
\r
583 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
585 MAC_dismiss_bad_frames();
\r
587 /* wait for a packet */
\r
588 if( time_out != MSS_MAC_BLOCKING ) {
\r
589 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
590 MAC_set_time_out( 0u );
\r
592 MAC_set_time_out( time_out );
\r
596 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
597 RDES0_OWN) != 0u) && (exit == 0) )
\r
599 if( time_out != MSS_MAC_BLOCKING )
\r
601 if( MAC_get_time_out() == 0u ) {
\r
610 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
611 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
614 frame_length -= 4u;
\r
616 if( frame_length > pacLen ) {
\r
617 return MAC_NOT_ENOUGH_SPACE;
\r
620 *pacData = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
622 MSS_MAC_prepare_rx_descriptor();
\r
625 return ((int32_t)frame_length);
\r
629 /***************************************************************************//**
\r
630 * Receives a packet from the Ethernet Controller.
\r
631 * This function reads a packet from the receive FIFO of the controller and
\r
632 * sets the address of pacData to the received data.
\r
633 * If time_out parameter is zero the function will return
\r
634 * immediately (after the copy operation if data is available. Otherwise the function
\r
635 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
636 * value is given as time_out, function will wait for the reception to complete.
\r
638 * @param instance Pointer to a MAC_instance_t structure
\r
639 * @param pacData The pointer to the packet data.
\r
640 * @param time_out Time out value in milli seconds for receiving.
\r
641 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
642 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
643 * if there is no packet waiting.
\r
644 * Otherwise value must be greater than 0 and smaller than
\r
646 * @return Size of packet if packet fits in pacData.
\r
647 * 0 if there is no received packet.
\r
648 * @see MAC_rx_pckt_size()
\r
649 * @see MAC_tx_packet()
\r
652 MSS_MAC_rx_packet_ptrset
\r
658 uint16_t frame_length = 0u;
\r
661 ASSERT( MAC_test_instance() == MAC_OK );
\r
663 ASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
664 (time_out == MSS_MAC_NONBLOCKING) ||
\r
665 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
667 MAC_dismiss_bad_frames();
\r
669 /* wait for a packet */
\r
670 if( time_out != MSS_MAC_BLOCKING ) {
\r
671 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
672 MAC_set_time_out( 0u );
\r
674 MAC_set_time_out( time_out );
\r
678 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
679 RDES0_OWN) != 0u) && (exit == 0) )
\r
681 if( time_out != MSS_MAC_BLOCKING )
\r
683 if( MAC_get_time_out() == 0u ) {
\r
692 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
693 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
696 frame_length -= 4u;
\r
698 /* Here we are setting the buffer 'pacData' address to the address
\r
699 RX descriptor address. After this is called, the following function
\r
700 must be called 'MAC_prepare_rx_descriptor'
\r
701 to prepare the current rx descriptor for receiving the next packet.
\r
703 *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
\r
706 return ((int32_t)frame_length);
\r
709 /***************************************************************************//**
\r
710 * Returns the status of connection.
\r
712 * @return the logical OR of the following values:
\r
713 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
714 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
715 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
716 * @see MAC_auto_setup_link()
\r
719 MSS_MAC_link_status
\r
726 ASSERT( MAC_test_instance() == MAC_OK );
\r
728 link = PHY_link_status();
\r
729 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
730 link |= PHY_link_type();
\r
733 return ((int32_t)link);
\r
737 /***************************************************************************//**
\r
738 * Setups the link between PHY and MAC and returns the status of connection.
\r
740 * @return the logical OR of the following values:
\r
741 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
742 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
743 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
744 * @see MAC_link_status()
\r
747 MSS_MAC_auto_setup_link
\r
753 ASSERT( MAC_test_instance() == MAC_OK );
\r
755 PHY_auto_negotiate();
\r
757 link = MSS_MAC_link_status();
\r
759 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
761 ret = MAC_stop_transmission();
\r
762 MAC_CHECK( ret == MAC_OK, ret );
\r
764 ret = MAC_stop_receiving();
\r
765 MAC_CHECK( ret == MAC_OK, ret );
\r
766 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
767 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
768 MAC_start_transmission();
\r
769 MAC_start_receiving();
\r
776 /***************************************************************************//**
\r
777 * Sets mac address. New address must be unicast.
\r
779 * @param new_address Pointer to a MAC_instance_t structure
\r
780 * @see MAC_get_mac_address()
\r
783 MSS_MAC_set_mac_address
\r
785 const uint8_t *new_address
\r
788 ASSERT( MAC_test_instance() == MAC_OK );
\r
789 /* Check if the new address is unicast */
\r
790 ASSERT( (new_address[0]&1) == 0 );
\r
792 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
794 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
796 /* set unused filters to the new mac address */
\r
797 for( a=14*6; a>=0; a-=6 ) {
\r
798 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
799 /* Filters with multicast addresses are used */
\r
802 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
803 g_mss_mac.mac_address, 6u );
\r
808 MAC_send_setup_frame();
\r
812 /***************************************************************************//**
\r
813 * Returns mac address.
\r
815 * @param address Pointer to receive the MAC address
\r
816 * @see MAC_set_mac_address()
\r
819 MSS_MAC_get_mac_address
\r
824 ASSERT( MAC_test_instance() == MAC_OK );
\r
826 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
830 /***************************************************************************//**
\r
831 * Sets mac address filters. Addresses must be multicast.
\r
833 * @param filter_count number of addresses
\r
834 * @param filters Pointer to addresses to be filtered
\r
837 MSS_MAC_set_mac_filters
\r
839 uint16_t filter_count,
\r
840 const uint8_t *filters
\r
843 ASSERT( MAC_test_instance() == MAC_OK );
\r
844 ASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
845 /* Check if the mac addresses is multicast */
\r
848 for( a = 0u; a < filter_count; a++ ) {
\r
849 ASSERT( (filters[a*6]&1) == 1 );
\r
853 if( filter_count <= 15 ){
\r
855 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
857 /* copy new filters */
\r
858 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
860 /* set unused filters to our mac address */
\r
861 for( a=filter_count; a<15; a++ ) {
\r
862 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
863 g_mss_mac.mac_address, 6 );
\r
869 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
871 /* reset hash table */
\r
872 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
874 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
875 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
876 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
880 MAC_send_setup_frame();
\r
884 /***************************************************************************//**
\r
885 * MAC interrupt service routine.
\r
887 * @param instance Pointer to a MAC_instance_t structure
\r
888 * @see MAC_set_callback()
\r
890 #if defined(__GNUC__)
\r
891 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
893 void EthernetMAC_IRQHandler( void )
\r
897 uint32_t intr_status;
\r
899 ASSERT( MAC_test_instance() == MAC_OK );
\r
902 intr_status = MAC->CSR5;
\r
904 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
905 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
906 g_mss_mac.statistics.tx_interrupts++;
\r
907 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
910 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
911 g_mss_mac.statistics.rx_interrupts++;
\r
912 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
916 /* Clear interrupts */
\r
917 MAC->CSR5 = CSR5_INT_BITS;
\r
919 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
920 g_mss_mac.listener( events );
\r
925 /***************************************************************************//**
\r
926 * Sets MAC event listener.
\r
927 * Sets the given event listener function to be triggered inside MAC_isr().
\r
928 * Assigning NULL pointer as the listener function will disable it.
\r
930 * @param instance Pointer to a MAC_instance_t structure
\r
931 * @param listener function pointer to a MAC_callback_t function
\r
932 * @return #MAC_OK if everything is OK
\r
933 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
938 MSS_MAC_set_callback
\r
940 MSS_MAC_callback_t listener
\r
943 ASSERT( MAC_test_instance() == MAC_OK );
\r
945 /* disable tx and rx interrupts */
\r
946 MAC_BITBAND->CSR7_RIE = 0u;
\r
947 MAC_BITBAND->CSR7_TIE = 0u;
\r
949 g_mss_mac.listener = listener;
\r
951 if( listener != NULL_callback ) {
\r
952 /* enable tx and rx interrupts */
\r
953 MAC_BITBAND->CSR7_RIE = 1u;
\r
954 MAC_BITBAND->CSR7_TIE = 1u;
\r
959 /***************************************************************************//**
\r
960 * Returns description of last error.
\r
962 * @param instance Pointer to a MAC_instance_t structure
\r
963 * @return A string describing the error. This string must not be
\r
964 * modified by the application.
\r
965 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
974 int8_t error_msg_nb;
\r
975 const int8_t* returnvalue;
\r
977 ASSERT( MAC_test_instance() == MAC_OK );
\r
979 error_msg_nb = -(g_mss_mac.last_error);
\r
980 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
981 returnvalue = unknown_error;
\r
983 returnvalue = ErrorMessages[error_msg_nb];
\r
985 return returnvalue;
\r
989 /***************************************************************************//**
\r
990 * Returns statistics counter of stat_id identifier.
\r
992 * @param instance Pointer to a MAC_instance_t structure
\r
993 * @param stat_id Identifier of statistics counter.
\r
994 * @return Statistics counter of stat_id identifier.
\r
995 * On error returns 0.
\r
998 MSS_MAC_get_statistics
\r
1000 mss_mac_statistics_id_t stat_id
\r
1003 uint32_t returnval = 0u;
\r
1004 ASSERT( MAC_test_instance() == MAC_OK );
\r
1006 switch( stat_id ) {
\r
1007 case MSS_MAC_RX_INTERRUPTS:
\r
1008 returnval = g_mss_mac.statistics.rx_interrupts;
\r
1010 case MSS_MAC_RX_FILTERING_FAIL:
\r
1011 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
1013 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
1014 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
1016 case MSS_MAC_RX_RUNT_FRAME:
\r
1017 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
1019 case MSS_MAC_RX_NOT_FIRST:
\r
1020 returnval = g_mss_mac.statistics.rx_not_first;
\r
1022 case MSS_MAC_RX_NOT_LAST:
\r
1023 returnval = g_mss_mac.statistics.rx_not_last;
\r
1025 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
1026 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
1028 case MSS_MAC_RX_COLLISION_SEEN:
\r
1029 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
1031 case MSS_MAC_RX_CRC_ERROR:
\r
1032 returnval = g_mss_mac.statistics.rx_crc_error;
\r
1034 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
1035 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
1037 case MSS_MAC_RX_MISSED_FRAME:
\r
1038 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
1040 case MSS_MAC_TX_INTERRUPTS:
\r
1041 returnval = g_mss_mac.statistics.tx_interrupts;
\r
1043 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
1044 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
1046 case MSS_MAC_TX_NO_CARRIER:
\r
1047 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
1049 case MSS_MAC_TX_LATE_COLLISION:
\r
1050 returnval = g_mss_mac.statistics.tx_late_collision;
\r
1052 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
1053 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
1055 case MSS_MAC_TX_COLLISION_COUNT:
\r
1056 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1058 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1059 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1069 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1071 /***************************************************************************//**
\r
1072 * Checks if instace is valid.
\r
1082 int32_t retval = MAC_WRONG_PARAMETER;
\r
1087 if( (&g_mss_mac != NULL_instance) &&
\r
1088 ((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&
\r
1089 ( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&
\r
1090 (val2 == (uint32_t)g_mss_mac.tx_descriptors ) )
\r
1097 /***************************************************************************//**
\r
1098 * Prepares current rx descriptor for receiving.
\r
1101 MSS_MAC_prepare_rx_descriptor
\r
1108 /* update counters */
\r
1109 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1110 if( (desc & RDES0_FF) != 0u ) {
\r
1111 g_mss_mac.statistics.rx_filtering_fail++;
\r
1113 if( (desc & RDES0_DE) != 0u ) {
\r
1114 g_mss_mac.statistics.rx_descriptor_error++;
\r
1116 if( (desc & RDES0_RF) != 0u ) {
\r
1117 g_mss_mac.statistics.rx_runt_frame++;
\r
1119 if( (desc & RDES0_FS) == 0u ) {
\r
1120 g_mss_mac.statistics.rx_not_first++;
\r
1122 if( (desc & RDES0_LS) == 0u ) {
\r
1123 g_mss_mac.statistics.rx_not_last++;
\r
1125 if( (desc & RDES0_TL) != 0u ) {
\r
1126 g_mss_mac.statistics.rx_frame_too_long++;
\r
1128 if( (desc & RDES0_CS) != 0u ) {
\r
1129 g_mss_mac.statistics.rx_collision_seen++;
\r
1131 if( (desc & RDES0_CE) != 0u ) {
\r
1132 g_mss_mac.statistics.rx_crc_error++;
\r
1136 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1137 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1138 g_mss_mac.statistics.rx_missed_frame +=
\r
1139 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1141 /* Give ownership of descriptor to the MAC */
\r
1142 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =
\r
1144 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1146 /* Start receive */
\r
1147 MAC_start_receiving();
\r
1151 /***************************************************************************//**
\r
1152 * Prepares a setup frame and sends it to MAC.
\r
1153 * This function is blocking.
\r
1154 * @return #MAC_OK if everything is ok.
\r
1155 * #MAC_TIME_OUT if timed out before packet send.
\r
1158 MAC_send_setup_frame
\r
1163 volatile MAC_descriptor_t descriptor;
\r
1164 uint8_t frame_data[192];
\r
1169 /* prepare descriptor */
\r
1170 descriptor.descriptor_0 = TDES0_OWN;
\r
1171 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1172 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1174 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1175 descriptor.descriptor_1 |= TDES1_FT0;
\r
1178 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1179 descriptor.buffer_2 = 0u;
\r
1181 /* prepare frame */
\r
1182 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1192 data = g_mss_mac.mac_address;
\r
1193 frame_data[b] = data[0];
\r
1194 frame_data[b+1] = data[1];
\r
1195 frame_data[b+4] = data[2];
\r
1196 frame_data[b+5] = data[3];
\r
1197 frame_data[b+8] = data[4];
\r
1198 frame_data[b+9] = data[5];
\r
1200 data = g_mss_mac.mac_filter_data;
\r
1201 for( a = 0; a < c; ) {
\r
1202 frame_data[d] = data[a++];
\r
1203 frame_data[d+1] = data[a++];
\r
1204 frame_data[d+4] = data[a++];
\r
1205 frame_data[d+5] = data[a++];
\r
1206 frame_data[d+8] = data[a++];
\r
1207 frame_data[d+9] = data[a++];
\r
1211 /* Stop transmission */
\r
1212 ret = MAC_stop_transmission();
\r
1213 ASSERT( ret == MAC_OK );
\r
1215 ret = MAC_stop_receiving();
\r
1216 ASSERT( ret == MAC_OK );
\r
1218 /* Set descriptor */
\r
1219 MAC->CSR4 = (uint32_t)&descriptor;
\r
1221 /* Start transmission */
\r
1222 MAC_start_transmission();
\r
1224 /* Wait until transmission over */
\r
1226 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1228 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1229 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1231 /* transmit poll demand */
\r
1233 if( MAC_get_time_out() == 0u ) {
\r
1234 ret = MAC_TIME_OUT;
\r
1238 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1240 /* Set tx descriptor */
\r
1241 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1243 /* Start receiving and transmission */
\r
1244 MAC_start_receiving();
\r
1245 MAC_start_transmission();
\r
1251 /***************************************************************************//**
\r
1252 * Stops transmission.
\r
1253 * Function will wait until transmit operation enters stop state.
\r
1255 * @return #MAC_OK if everything is ok.
\r
1256 * #MAC_TIME_OUT if timed out.
\r
1259 MAC_stop_transmission
\r
1264 int32_t retval = MAC_OK;
\r
1265 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1267 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1268 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1270 MAC_BITBAND->CSR6_ST = 0u;
\r
1271 if( MAC_get_time_out() == 0u ) {
\r
1272 retval = MAC_TIME_OUT;
\r
1279 /***************************************************************************//**
\r
1280 * Starts transmission.
\r
1283 MAC_start_transmission
\r
1288 MAC_BITBAND->CSR6_ST = 1u;
\r
1292 /***************************************************************************//**
\r
1293 * Stops transmission.
\r
1294 * Function will wait until transmit operation enters stop state.
\r
1296 * @return #MAC_OK if everything is ok.
\r
1297 * #MAC_TIME_OUT if timed out.
\r
1300 MAC_stop_receiving
\r
1305 int32_t retval = MAC_OK;
\r
1306 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1308 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1309 && (retval == MAC_OK) )
\r
1311 MAC_BITBAND->CSR6_SR = 0u;
\r
1312 if( MAC_get_time_out() == 0u ) {
\r
1313 retval = MAC_TIME_OUT;
\r
1321 /***************************************************************************//**
\r
1322 * Starts transmission.
\r
1325 MAC_start_receiving
\r
1330 MAC_BITBAND->CSR6_SR = 1u;
\r
1334 /***************************************************************************//**
\r
1335 * Dismisses bad frames.
\r
1337 * @return dismissed frame count.
\r
1340 MAC_dismiss_bad_frames
\r
1348 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1349 /* User wants bad frames too, don't dismiss anything */
\r
1353 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1354 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1356 /* check error summary */
\r
1357 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1358 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1360 MSS_MAC_prepare_rx_descriptor();
\r
1372 /***************************************************************************//**
\r
1373 * Sets time out value.
\r
1374 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1375 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1377 * @time_out time out value in milli seconds.
\r
1378 * Must be smaller than 0x01000000.
\r
1386 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1388 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1391 /***************************************************************************//**
\r
1392 * Returns time out value.
\r
1394 * @return timer out value in milli seconds.
\r
1403 uint32_t time = 0u;
\r
1405 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1407 if( timer > g_mss_mac.last_timer_value ) {
\r
1408 time = 0x0000ffffUL;
\r
1410 time += g_mss_mac.last_timer_value - timer;
\r
1412 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1415 if( g_mss_mac.time_out_value <= time ){
\r
1416 g_mss_mac.time_out_value = 0u;
\r
1418 g_mss_mac.time_out_value -= time;
\r
1421 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1423 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1426 /***************************************************************************//**
\r
1427 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1430 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1440 /***************************************************************************//**
\r
1441 * Fills all fields of MAC_instance_t with c.
\r
1443 * @return a pointer to the given MAC_instance_t s.
\r
1445 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1448 s->base_address = (addr_t)c;
\r
1449 s->flags = (uint8_t)c;
\r
1450 s->last_error = (int8_t)c;
\r
1451 s->last_timer_value = (uint16_t)c;
\r
1452 s->listener = NULL_callback;
\r
1453 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1454 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1455 s->phy_address = (uint8_t)c;
\r
1456 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1458 MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
\r
1460 s->rx_desc_index =c;
\r
1461 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1463 s->rx_descriptors[count].buffer_1 = c;
\r
1464 s->rx_descriptors[count].buffer_2 = c;
\r
1465 s->rx_descriptors[count].descriptor_0 = c;
\r
1466 s->rx_descriptors[count].descriptor_1 = c;
\r
1468 s->statistics.rx_collision_seen =c;
\r
1469 s->statistics.rx_crc_error = c;
\r
1470 s->statistics.rx_descriptor_error = c;
\r
1471 s->statistics.rx_fifo_overflow = c;
\r
1472 s->statistics.rx_filtering_fail = c;
\r
1473 s->statistics.rx_frame_too_long = c;
\r
1474 s->statistics.rx_interrupts = c;
\r
1475 s->statistics.rx_missed_frame = c;
\r
1476 s->statistics.rx_not_first = c;
\r
1477 s->statistics.rx_not_last = c;
\r
1478 s->statistics.rx_runt_frame = c;
\r
1479 s->statistics.tx_collision_count = c;
\r
1480 s->statistics.tx_excessive_collision = c;
\r
1481 s->statistics.tx_interrupts = c;
\r
1482 s->statistics.tx_late_collision = c;
\r
1483 s->statistics.tx_loss_of_carrier = c;
\r
1484 s->statistics.tx_no_carrier = c;
\r
1485 s->statistics.tx_underflow_error = c;
\r
1486 s->time_out_value = c;
\r
1487 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1489 MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
\r
1491 s->tx_desc_index = c;
\r
1492 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1494 s->tx_descriptors[count].buffer_1 = c;
\r
1495 s->tx_descriptors[count].buffer_2 = c;
\r
1496 s->tx_descriptors[count].descriptor_0 = c;
\r
1497 s->tx_descriptors[count].descriptor_1 = c;
\r
1501 /***************************************************************************//**
\r
1502 * Copies n bytes from memory area src to memory area dest.
\r
1503 * The memory areas should not overlap.
\r
1505 * @return a pointer to the memory area dest.
\r
1507 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1509 uint8_t *d = dest;
\r
1517 #ifdef __cplusplus
\r
1521 /******************************** END OF FILE *********************************/
\r