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); configASSERT((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 + 1
\r
58 #define macBUFFER_SIZE 1488
\r
60 /***************************************************************/
\r
61 MAC_instance_t g_mss_mac __attribute__((aligned(4)));
\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 ] __attribute__((aligned(4)));
\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 ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
\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 ucMACBufferInUse[ a ] = pdFALSE;
\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 configASSERT( MAC->CSR0 == 0xFE000000uL );
\r
155 configASSERT( MAC->CSR5 == 0xF0000000uL );
\r
156 configASSERT( 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 ucMACBufferInUse[ a ] = pdTRUE;
\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 configASSERT( 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
234 MAC_BITBAND->CSR6_PR = 1; /* Promiscuous mode. */
\r
235 MSS_MAC_set_mac_address((uint8_t *)mac_address);
\r
237 /* Ensure uip_buf starts by pointing somewhere. */
\r
238 uip_buf = MAC_obtain_buffer();
\r
242 /***************************************************************************//**
\r
243 * Sets the configuration of the Ethernet Controller.
\r
244 * After the EthernetInit function has been called, this API function can be
\r
245 * used to configure the various features of the Ethernet Controller.
\r
247 * @param instance Pointer to a MAC_instance_t structure
\r
248 * @param config The logical OR of the following values:
\r
249 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
250 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
251 * - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD
\r
252 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
253 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
254 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
255 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
256 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
257 * @see MAC_get_configuration()
\r
262 uint32_t configuration
\r
267 configASSERT( MAC_test_instance() == MAC_OK );
\r
269 ret = MAC_stop_transmission();
\r
270 configASSERT( ret == MAC_OK );
\r
272 ret = MAC_stop_receiving();
\r
273 configASSERT( ret == MAC_OK );
\r
275 MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
\r
276 MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
\r
277 MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
\r
279 switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
\r
280 case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
\r
281 MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
\r
283 case MSS_MAC_CFG_THRESHOLD_CONTROL_01:
\r
284 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );
\r
286 case MSS_MAC_CFG_THRESHOLD_CONTROL_10:
\r
287 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );
\r
289 case MSS_MAC_CFG_THRESHOLD_CONTROL_11:
\r
290 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );
\r
295 MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );
\r
296 MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );
\r
297 MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );
\r
298 MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );
\r
299 PHY_set_link_type( (uint8_t)
\r
300 ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |
\r
301 (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );
\r
303 MSS_MAC_auto_setup_link();
\r
307 /***************************************************************************//**
\r
308 * Returns the configuration of the Ethernet Controller.
\r
310 * @param instance Pointer to a MAC_instance_t structure
\r
311 * @return The logical OR of the following values:
\r
312 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
313 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
314 * - #MSS_MAC_CFG_STORE_AND_FORWARD
\r
315 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
316 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
317 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
318 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
319 * - #MSS_MAC_CFG_INVERSE_FILTERING
\r
320 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
321 * - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE
\r
322 * - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE
\r
323 * @see MAC_configure()
\r
326 MSS_MAC_get_configuration( void )
\r
328 uint32_t configuration;
\r
330 configASSERT( MAC_test_instance() == MAC_OK );
\r
332 configuration = 0u;
\r
333 if( MAC_BITBAND->CSR6_RA != 0u ) {
\r
334 configuration |= MSS_MAC_CFG_RECEIVE_ALL;
\r
337 if( MAC_BITBAND->CSR6_TTM != 0u ) {
\r
338 configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;
\r
341 if( MAC_BITBAND->CSR6_SF != 0u ) {
\r
342 configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;
\r
345 switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {
\r
346 case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;
\r
347 case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;
\r
348 case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;
\r
351 if( MAC_BITBAND->CSR6_FD != 0u ) {
\r
352 configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;
\r
355 if( MAC_BITBAND->CSR6_PM != 0u ) {
\r
356 configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;
\r
359 if( MAC_BITBAND->CSR6_PR != 0u ) {
\r
360 configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;
\r
363 if( MAC_BITBAND->CSR6_IF != 0u ) {
\r
364 configuration |= MSS_MAC_CFG_INVERSE_FILTERING;
\r
367 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
368 configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;
\r
371 if( MAC_BITBAND->CSR6_HO != 0u ) {
\r
372 configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;
\r
375 if( MAC_BITBAND->CSR6_HP != 0u ) {
\r
376 configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
\r
379 return (int32_t)configuration;
\r
383 /***************************************************************************//**
\r
384 Sends a packet from the uIP stack to the Ethernet Controller.
\r
385 The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
\r
386 MAC. This function writes uip_len bytes of the packet contained in uip_buf into
\r
387 the transmit FIFO and then activates the transmitter for this packet. If space
\r
388 is available in the FIFO, the function will return once pac_len bytes of the
\r
389 packet have been placed into the FIFO and the transmitter has been started.
\r
390 This function will not wait for the transmission to complete.
\r
393 The function returns zero if a timeout occurs otherwise it returns size of the packet.
\r
395 @see MAC_rx_packet()
\r
401 unsigned short usLength
\r
405 unsigned long ulDescriptor;
\r
406 int32_t error = MAC_OK;
\r
407 extern unsigned char *uip_buf;
\r
409 configASSERT( MAC_test_instance() == MAC_OK );
\r
411 configASSERT( uip_buf != NULL_buffer );
\r
413 configASSERT( usLength >= 12 );
\r
415 if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
\r
417 configASSERT( usLength <= MSS_MAX_PACKET_SIZE );
\r
420 /* Check if second descriptor is free, if it is then the first must
\r
422 if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
\r
424 error = MAC_BUFFER_IS_FULL;
\r
427 if( error == MAC_OK )
\r
429 /* Assumed TX_RING_SIZE == 2. */
\r
430 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
\r
432 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u;
\r
434 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
435 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC;
\r
438 /* Every buffer can hold a full frame so they are always first and last
\r
440 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
\r
442 /* set data size */
\r
443 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength;
\r
445 /* reset end of ring */
\r
446 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
448 if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
450 usLength = (uint16_t)MSS_TX_BUFF_SIZE;
\r
453 /* The data buffer is assigned to the Tx descriptor. */
\r
454 g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf;
\r
456 /* update counters */
\r
457 desc = g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0;
\r
458 if( (desc & TDES0_LO) != 0u ) {
\r
459 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
461 if( (desc & TDES0_NC) != 0u ) {
\r
462 g_mss_mac.statistics.tx_no_carrier++;
\r
464 if( (desc & TDES0_LC) != 0u ) {
\r
465 g_mss_mac.statistics.tx_late_collision++;
\r
467 if( (desc & TDES0_EC) != 0u ) {
\r
468 g_mss_mac.statistics.tx_excessive_collision++;
\r
470 if( (desc & TDES0_UF) != 0u ) {
\r
471 g_mss_mac.statistics.tx_underflow_error++;
\r
473 g_mss_mac.statistics.tx_collision_count +=
\r
474 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
476 /* Give ownership of descriptor to the MAC */
\r
477 g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = RDES0_OWN;
\r
480 /* Start transmission */
\r
481 MAC_start_transmission();
\r
482 g_mss_mac.tx_desc_index = 0;
\r
483 /* transmit poll demand */
\r
490 if (error == MAC_OK)
\r
492 /* The buffer uip_buf was pointing to is now under the control of the
\r
493 MAC (it is being transmitted). Set uip_buf to point to a free buffer. */
\r
494 uip_buf = MAC_obtain_buffer();
\r
495 error = (int32_t)usLength;
\r
505 /***************************************************************************//**
\r
506 * Returns available packet size.
\r
508 * @param instance Pointer to a MAC_instance_t structure
\r
509 * @return size of packet, bigger than 0, if a packet is available.
\r
510 * If not, returns 0.
\r
511 * @see MAC_rx_packet()
\r
514 MSS_MAC_rx_pckt_size
\r
520 configASSERT( MAC_test_instance() == MAC_OK );
\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 configASSERT( MAC_test_instance() == MAC_OK );
\r
559 MAC_dismiss_bad_frames();
\r
561 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
\r
564 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
565 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
568 frame_length -= 4u;
\r
570 if( frame_length > macBUFFER_SIZE ) {
\r
571 return MAC_NOT_ENOUGH_SPACE;
\r
574 /* uip_buf is about to point to the buffer that contains the received
\r
575 data, mark the buffer that uip_buf is currently pointing to as free
\r
577 MAC_release_buffer( uip_buf );
\r
578 uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
580 /* The buffer the Rx descriptor was pointing to is now in use by the
\r
581 uIP stack - allocate a new buffer to the Rx descriptor. */
\r
582 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();
\r
584 MSS_MAC_prepare_rx_descriptor();
\r
586 return ((int32_t)frame_length);
\r
590 /***************************************************************************//**
\r
591 * Receives a packet from the Ethernet Controller.
\r
592 * This function reads a packet from the receive FIFO of the controller and
\r
593 * sets the address of pacData to the received data.
\r
594 * If time_out parameter is zero the function will return
\r
595 * immediately (after the copy operation if data is available. Otherwise the function
\r
596 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
597 * value is given as time_out, function will wait for the reception to complete.
\r
599 * @param instance Pointer to a MAC_instance_t structure
\r
600 * @param pacData The pointer to the packet data.
\r
601 * @param time_out Time out value in milli seconds for receiving.
\r
602 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
603 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
604 * if there is no packet waiting.
\r
605 * Otherwise value must be greater than 0 and smaller than
\r
607 * @return Size of packet if packet fits in pacData.
\r
608 * 0 if there is no received packet.
\r
609 * @see MAC_rx_pckt_size()
\r
610 * @see MAC_tx_packet()
\r
613 MSS_MAC_rx_packet_ptrset
\r
619 uint16_t frame_length = 0u;
\r
622 configASSERT( MAC_test_instance() == MAC_OK );
\r
624 configASSERT( (time_out == MSS_MAC_BLOCKING) ||
\r
625 (time_out == MSS_MAC_NONBLOCKING) ||
\r
626 ((time_out >= 1) && (time_out <= 0x01000000UL)) );
\r
628 MAC_dismiss_bad_frames();
\r
630 /* wait for a packet */
\r
631 if( time_out != MSS_MAC_BLOCKING ) {
\r
632 if( time_out == MSS_MAC_NONBLOCKING ) {
\r
633 MAC_set_time_out( 0u );
\r
635 MAC_set_time_out( time_out );
\r
639 while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
640 RDES0_OWN) != 0u) && (exit == 0) )
\r
642 if( time_out != MSS_MAC_BLOCKING )
\r
644 if( MAC_get_time_out() == 0u ) {
\r
653 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
654 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
657 frame_length -= 4u;
\r
659 /* Here we are setting the buffer 'pacData' address to the address
\r
660 RX descriptor address. After this is called, the following function
\r
661 must be called 'MAC_prepare_rx_descriptor'
\r
662 to prepare the current rx descriptor for receiving the next packet.
\r
664 *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
\r
667 return ((int32_t)frame_length);
\r
670 /***************************************************************************//**
\r
671 * Returns the status of connection.
\r
673 * @return the logical OR of the following values:
\r
674 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
675 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
676 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
677 * @see MAC_auto_setup_link()
\r
680 MSS_MAC_link_status
\r
687 configASSERT( MAC_test_instance() == MAC_OK );
\r
689 link = PHY_link_status();
\r
690 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
691 link |= PHY_link_type();
\r
694 return ((int32_t)link);
\r
698 /***************************************************************************//**
\r
699 * Setups the link between PHY and MAC and returns the status of connection.
\r
701 * @return the logical OR of the following values:
\r
702 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
703 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
704 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
705 * @see MAC_link_status()
\r
708 MSS_MAC_auto_setup_link
\r
714 configASSERT( MAC_test_instance() == MAC_OK );
\r
716 PHY_auto_negotiate();
\r
718 link = MSS_MAC_link_status();
\r
720 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
722 ret = MAC_stop_transmission();
\r
723 MAC_CHECK( ret == MAC_OK, ret );
\r
725 ret = MAC_stop_receiving();
\r
726 MAC_CHECK( ret == MAC_OK, ret );
\r
727 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
728 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
729 MAC_start_transmission();
\r
730 MAC_start_receiving();
\r
737 /***************************************************************************//**
\r
738 * Sets mac address. New address must be unicast.
\r
740 * @param new_address Pointer to a MAC_instance_t structure
\r
741 * @see MAC_get_mac_address()
\r
744 MSS_MAC_set_mac_address
\r
746 const uint8_t *new_address
\r
749 configASSERT( MAC_test_instance() == MAC_OK );
\r
750 /* Check if the new address is unicast */
\r
751 configASSERT( (new_address[0]&1) == 0 );
\r
753 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
755 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
757 /* set unused filters to the new mac address */
\r
758 for( a=14*6; a>=0; a-=6 ) {
\r
759 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
760 /* Filters with multicast addresses are used */
\r
763 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
764 g_mss_mac.mac_address, 6u );
\r
769 MAC_send_setup_frame();
\r
773 /***************************************************************************//**
\r
774 * Returns mac address.
\r
776 * @param address Pointer to receive the MAC address
\r
777 * @see MAC_set_mac_address()
\r
780 MSS_MAC_get_mac_address
\r
785 configASSERT( MAC_test_instance() == MAC_OK );
\r
787 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
791 /***************************************************************************//**
\r
792 * Sets mac address filters. Addresses must be multicast.
\r
794 * @param filter_count number of addresses
\r
795 * @param filters Pointer to addresses to be filtered
\r
798 MSS_MAC_set_mac_filters
\r
800 uint16_t filter_count,
\r
801 const uint8_t *filters
\r
804 configASSERT( MAC_test_instance() == MAC_OK );
\r
805 configASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
806 /* Check if the mac addresses is multicast */
\r
809 for( a = 0u; a < filter_count; a++ ) {
\r
810 configASSERT( (filters[a*6]&1) == 1 );
\r
814 if( filter_count <= 15 ){
\r
816 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
818 /* copy new filters */
\r
819 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
821 /* set unused filters to our mac address */
\r
822 for( a=filter_count; a<15; a++ ) {
\r
823 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
824 g_mss_mac.mac_address, 6 );
\r
830 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
832 /* reset hash table */
\r
833 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
835 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
836 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
837 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
841 MAC_send_setup_frame();
\r
845 /***************************************************************************//**
\r
846 * MAC interrupt service routine.
\r
848 * @param instance Pointer to a MAC_instance_t structure
\r
849 * @see MAC_set_callback()
\r
851 #if defined(__GNUC__)
\r
852 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
854 void EthernetMAC_IRQHandler( void )
\r
858 uint32_t intr_status;
\r
860 configASSERT( MAC_test_instance() == MAC_OK );
\r
863 intr_status = MAC->CSR5;
\r
865 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
866 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
867 g_mss_mac.statistics.tx_interrupts++;
\r
868 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
871 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
872 g_mss_mac.statistics.rx_interrupts++;
\r
873 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
877 /* Clear interrupts */
\r
878 MAC->CSR5 = CSR5_INT_BITS;
\r
880 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
881 g_mss_mac.listener( events );
\r
886 /***************************************************************************//**
\r
887 * Sets MAC event listener.
\r
888 * Sets the given event listener function to be triggered inside MAC_isr().
\r
889 * Assigning NULL pointer as the listener function will disable it.
\r
891 * @param instance Pointer to a MAC_instance_t structure
\r
892 * @param listener function pointer to a MAC_callback_t function
\r
893 * @return #MAC_OK if everything is OK
\r
894 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
899 MSS_MAC_set_callback
\r
901 MSS_MAC_callback_t listener
\r
904 configASSERT( MAC_test_instance() == MAC_OK );
\r
906 /* disable tx and rx interrupts */
\r
907 MAC_BITBAND->CSR7_RIE = 0u;
\r
908 MAC_BITBAND->CSR7_TIE = 0u;
\r
910 g_mss_mac.listener = listener;
\r
912 if( listener != NULL_callback ) {
\r
913 /* enable tx and rx interrupts */
\r
914 MAC_BITBAND->CSR7_RIE = 1u;
\r
915 MAC_BITBAND->CSR7_TIE = 1u;
\r
920 /***************************************************************************//**
\r
921 * Returns description of last error.
\r
923 * @param instance Pointer to a MAC_instance_t structure
\r
924 * @return A string describing the error. This string must not be
\r
925 * modified by the application.
\r
926 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
935 int8_t error_msg_nb;
\r
936 const int8_t* returnvalue;
\r
938 configASSERT( MAC_test_instance() == MAC_OK );
\r
940 error_msg_nb = -(g_mss_mac.last_error);
\r
941 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
942 returnvalue = unknown_error;
\r
944 returnvalue = ErrorMessages[error_msg_nb];
\r
946 return returnvalue;
\r
950 /***************************************************************************//**
\r
951 * Returns statistics counter of stat_id identifier.
\r
953 * @param instance Pointer to a MAC_instance_t structure
\r
954 * @param stat_id Identifier of statistics counter.
\r
955 * @return Statistics counter of stat_id identifier.
\r
956 * On error returns 0.
\r
959 MSS_MAC_get_statistics
\r
961 mss_mac_statistics_id_t stat_id
\r
964 uint32_t returnval = 0u;
\r
965 configASSERT( MAC_test_instance() == MAC_OK );
\r
967 switch( stat_id ) {
\r
968 case MSS_MAC_RX_INTERRUPTS:
\r
969 returnval = g_mss_mac.statistics.rx_interrupts;
\r
971 case MSS_MAC_RX_FILTERING_FAIL:
\r
972 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
974 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
975 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
977 case MSS_MAC_RX_RUNT_FRAME:
\r
978 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
980 case MSS_MAC_RX_NOT_FIRST:
\r
981 returnval = g_mss_mac.statistics.rx_not_first;
\r
983 case MSS_MAC_RX_NOT_LAST:
\r
984 returnval = g_mss_mac.statistics.rx_not_last;
\r
986 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
987 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
989 case MSS_MAC_RX_COLLISION_SEEN:
\r
990 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
992 case MSS_MAC_RX_CRC_ERROR:
\r
993 returnval = g_mss_mac.statistics.rx_crc_error;
\r
995 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
996 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
998 case MSS_MAC_RX_MISSED_FRAME:
\r
999 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
1001 case MSS_MAC_TX_INTERRUPTS:
\r
1002 returnval = g_mss_mac.statistics.tx_interrupts;
\r
1004 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
1005 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
1007 case MSS_MAC_TX_NO_CARRIER:
\r
1008 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
1010 case MSS_MAC_TX_LATE_COLLISION:
\r
1011 returnval = g_mss_mac.statistics.tx_late_collision;
\r
1013 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
1014 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
1016 case MSS_MAC_TX_COLLISION_COUNT:
\r
1017 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1019 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1020 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1030 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1032 /***************************************************************************//**
\r
1033 * Checks if instace is valid.
\r
1043 int32_t retval = MAC_WRONG_PARAMETER;
\r
1048 if( (&g_mss_mac != NULL_instance) &&
\r
1049 ((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&
\r
1050 ( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&
\r
1051 (val2 == (uint32_t)g_mss_mac.tx_descriptors ) )
\r
1058 /***************************************************************************//**
\r
1059 * Prepares current rx descriptor for receiving.
\r
1062 MSS_MAC_prepare_rx_descriptor
\r
1069 /* update counters */
\r
1070 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1071 if( (desc & RDES0_FF) != 0u ) {
\r
1072 g_mss_mac.statistics.rx_filtering_fail++;
\r
1074 if( (desc & RDES0_DE) != 0u ) {
\r
1075 g_mss_mac.statistics.rx_descriptor_error++;
\r
1077 if( (desc & RDES0_RF) != 0u ) {
\r
1078 g_mss_mac.statistics.rx_runt_frame++;
\r
1080 if( (desc & RDES0_FS) == 0u ) {
\r
1081 g_mss_mac.statistics.rx_not_first++;
\r
1083 if( (desc & RDES0_LS) == 0u ) {
\r
1084 g_mss_mac.statistics.rx_not_last++;
\r
1086 if( (desc & RDES0_TL) != 0u ) {
\r
1087 g_mss_mac.statistics.rx_frame_too_long++;
\r
1089 if( (desc & RDES0_CS) != 0u ) {
\r
1090 g_mss_mac.statistics.rx_collision_seen++;
\r
1092 if( (desc & RDES0_CE) != 0u ) {
\r
1093 g_mss_mac.statistics.rx_crc_error++;
\r
1097 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1098 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1099 g_mss_mac.statistics.rx_missed_frame +=
\r
1100 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1102 /* Give ownership of descriptor to the MAC */
\r
1103 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =
\r
1105 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1107 /* Start receive */
\r
1108 MAC_start_receiving();
\r
1112 /***************************************************************************//**
\r
1113 * Prepares a setup frame and sends it to MAC.
\r
1114 * This function is blocking.
\r
1115 * @return #MAC_OK if everything is ok.
\r
1116 * #MAC_TIME_OUT if timed out before packet send.
\r
1119 MAC_send_setup_frame
\r
1124 volatile MAC_descriptor_t descriptor;
\r
1125 uint8_t frame_data[192];
\r
1130 /* prepare descriptor */
\r
1131 descriptor.descriptor_0 = TDES0_OWN;
\r
1132 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1133 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1135 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1136 descriptor.descriptor_1 |= TDES1_FT0;
\r
1139 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1140 descriptor.buffer_2 = 0u;
\r
1142 /* prepare frame */
\r
1143 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1153 data = g_mss_mac.mac_address;
\r
1154 frame_data[b] = data[0];
\r
1155 frame_data[b+1] = data[1];
\r
1156 frame_data[b+4] = data[2];
\r
1157 frame_data[b+5] = data[3];
\r
1158 frame_data[b+8] = data[4];
\r
1159 frame_data[b+9] = data[5];
\r
1161 data = g_mss_mac.mac_filter_data;
\r
1162 for( a = 0; a < c; ) {
\r
1163 frame_data[d] = data[a++];
\r
1164 frame_data[d+1] = data[a++];
\r
1165 frame_data[d+4] = data[a++];
\r
1166 frame_data[d+5] = data[a++];
\r
1167 frame_data[d+8] = data[a++];
\r
1168 frame_data[d+9] = data[a++];
\r
1172 /* Stop transmission */
\r
1173 ret = MAC_stop_transmission();
\r
1174 configASSERT( ret == MAC_OK );
\r
1176 ret = MAC_stop_receiving();
\r
1177 configASSERT( ret == MAC_OK );
\r
1179 /* Set descriptor */
\r
1180 MAC->CSR4 = (uint32_t)&descriptor;
\r
1182 /* Start transmission */
\r
1183 MAC_start_transmission();
\r
1185 /* Wait until transmission over */
\r
1187 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1189 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1190 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1192 /* transmit poll demand */
\r
1194 if( MAC_get_time_out() == 0u ) {
\r
1195 ret = MAC_TIME_OUT;
\r
1199 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1201 /* Set tx descriptor */
\r
1202 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1204 /* Start receiving and transmission */
\r
1205 MAC_start_receiving();
\r
1206 MAC_start_transmission();
\r
1212 /***************************************************************************//**
\r
1213 * Stops transmission.
\r
1214 * Function will wait until transmit operation enters stop state.
\r
1216 * @return #MAC_OK if everything is ok.
\r
1217 * #MAC_TIME_OUT if timed out.
\r
1220 MAC_stop_transmission
\r
1225 int32_t retval = MAC_OK;
\r
1226 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1228 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1229 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1231 MAC_BITBAND->CSR6_ST = 0u;
\r
1232 if( MAC_get_time_out() == 0u ) {
\r
1233 retval = MAC_TIME_OUT;
\r
1240 /***************************************************************************//**
\r
1241 * Starts transmission.
\r
1244 MAC_start_transmission
\r
1249 MAC_BITBAND->CSR6_ST = 1u;
\r
1253 /***************************************************************************//**
\r
1254 * Stops transmission.
\r
1255 * Function will wait until transmit operation enters stop state.
\r
1257 * @return #MAC_OK if everything is ok.
\r
1258 * #MAC_TIME_OUT if timed out.
\r
1261 MAC_stop_receiving
\r
1266 int32_t retval = MAC_OK;
\r
1267 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1269 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1270 && (retval == MAC_OK) )
\r
1272 MAC_BITBAND->CSR6_SR = 0u;
\r
1273 if( MAC_get_time_out() == 0u ) {
\r
1274 retval = MAC_TIME_OUT;
\r
1282 /***************************************************************************//**
\r
1283 * Starts transmission.
\r
1286 MAC_start_receiving
\r
1291 MAC_BITBAND->CSR6_SR = 1u;
\r
1295 /***************************************************************************//**
\r
1296 * Dismisses bad frames.
\r
1298 * @return dismissed frame count.
\r
1301 MAC_dismiss_bad_frames
\r
1309 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1310 /* User wants bad frames too, don't dismiss anything */
\r
1314 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1315 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1317 /* check error summary */
\r
1318 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1319 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1321 MSS_MAC_prepare_rx_descriptor();
\r
1333 /***************************************************************************//**
\r
1334 * Sets time out value.
\r
1335 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1336 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1338 * @time_out time out value in milli seconds.
\r
1339 * Must be smaller than 0x01000000.
\r
1347 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1349 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1352 /***************************************************************************//**
\r
1353 * Returns time out value.
\r
1355 * @return timer out value in milli seconds.
\r
1364 uint32_t time = 0u;
\r
1366 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1368 if( timer > g_mss_mac.last_timer_value ) {
\r
1369 time = 0x0000ffffUL;
\r
1371 time += g_mss_mac.last_timer_value - timer;
\r
1373 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1376 if( g_mss_mac.time_out_value <= time ){
\r
1377 g_mss_mac.time_out_value = 0u;
\r
1379 g_mss_mac.time_out_value -= time;
\r
1382 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1384 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1387 /***************************************************************************//**
\r
1388 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1391 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1401 /***************************************************************************//**
\r
1402 * Fills all fields of MAC_instance_t with c.
\r
1404 * @return a pointer to the given MAC_instance_t s.
\r
1406 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1409 s->base_address = (addr_t)c;
\r
1410 s->flags = (uint8_t)c;
\r
1411 s->last_error = (int8_t)c;
\r
1412 s->last_timer_value = (uint16_t)c;
\r
1413 s->listener = NULL_callback;
\r
1414 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1415 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1416 s->phy_address = (uint8_t)c;
\r
1417 // for(count = 0; count<RX_RING_SIZE ;count++)
\r
1419 // MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
\r
1421 s->rx_desc_index =c;
\r
1422 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1424 s->rx_descriptors[count].buffer_1 = c;
\r
1425 s->rx_descriptors[count].buffer_2 = c;
\r
1426 s->rx_descriptors[count].descriptor_0 = c;
\r
1427 s->rx_descriptors[count].descriptor_1 = c;
\r
1429 s->statistics.rx_collision_seen =c;
\r
1430 s->statistics.rx_crc_error = c;
\r
1431 s->statistics.rx_descriptor_error = c;
\r
1432 s->statistics.rx_fifo_overflow = c;
\r
1433 s->statistics.rx_filtering_fail = c;
\r
1434 s->statistics.rx_frame_too_long = c;
\r
1435 s->statistics.rx_interrupts = c;
\r
1436 s->statistics.rx_missed_frame = c;
\r
1437 s->statistics.rx_not_first = c;
\r
1438 s->statistics.rx_not_last = c;
\r
1439 s->statistics.rx_runt_frame = c;
\r
1440 s->statistics.tx_collision_count = c;
\r
1441 s->statistics.tx_excessive_collision = c;
\r
1442 s->statistics.tx_interrupts = c;
\r
1443 s->statistics.tx_late_collision = c;
\r
1444 s->statistics.tx_loss_of_carrier = c;
\r
1445 s->statistics.tx_no_carrier = c;
\r
1446 s->statistics.tx_underflow_error = c;
\r
1447 s->time_out_value = c;
\r
1448 // for(count = 0; count < TX_RING_SIZE ;count++)
\r
1450 // MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
\r
1452 s->tx_desc_index = c;
\r
1453 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1455 s->tx_descriptors[count].buffer_1 = c;
\r
1456 s->tx_descriptors[count].buffer_2 = c;
\r
1457 s->tx_descriptors[count].descriptor_0 = c;
\r
1458 s->tx_descriptors[count].descriptor_1 = c;
\r
1462 /***************************************************************************//**
\r
1463 * Copies n bytes from memory area src to memory area dest.
\r
1464 * The memory areas should not overlap.
\r
1466 * @return a pointer to the memory area dest.
\r
1468 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1470 uint8_t *d = dest;
\r
1478 void MSS_MAC_TxBufferCompleted( void )
\r
1480 unsigned char *pxTransmittedBuffer;
\r
1482 /* Was it the second transmission that has completed? */
\r
1483 if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )
\r
1485 pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1;
\r
1487 /* The buffer has been transmitted and is no longer in use. */
\r
1488 MAC_release_buffer( pxTransmittedBuffer );
\r
1492 // configASSERT( 0 );
\r
1496 static unsigned char *MAC_obtain_buffer( void )
\r
1499 unsigned char *pcReturn = NULL;
\r
1501 /* Find and return the address of a buffer that is not being used. Mark
\r
1502 the buffer as now in use. */
\r
1503 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1505 if( ucMACBufferInUse[ lIndex ] == pdFALSE )
\r
1507 pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] );
\r
1508 ucMACBufferInUse[ lIndex ] = pdTRUE;
\r
1513 configASSERT( pcReturn );
\r
1517 void MAC_release_buffer( unsigned char *pucBufferToRelease )
\r
1521 /* uip_buf is going to point to a different buffer - first ensure the buffer
\r
1522 it is currently pointing to is marked as being free again. */
\r
1523 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1525 if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) )
\r
1527 /* This is the buffer in use, mark it as being free. */
\r
1528 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1533 configASSERT( lIndex < macNUM_BUFFERS );
\r
1538 #ifdef __cplusplus
\r
1542 /******************************** END OF FILE *********************************/
\r