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
13 * NOTE: This driver has been roughly modified specifically for use with the
\r
14 * uIP stack. It is no longer a generic driver.
\r
21 #include "FreeRTOS.h"
\r
26 #include "mss_ethernet_mac.h"
\r
27 #include "mss_ethernet_mac_regs.h"
\r
28 #include "mss_ethernet_mac_desc.h"
\r
29 #include "mss_ethernet_mac_conf.h"
\r
30 #include "../../CMSIS/mss_assert.h"
\r
34 /**************************** INTERNAL DEFINES ********************************/
\r
36 #define MAC_CHECK(CHECK,ERRNO) \
\r
37 {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); configASSERT((CHECK));}}
\r
42 #define FLAG_MAC_INIT_DONE 1u
\r
43 #define FLAG_PERFECT_FILTERING 2u
\r
44 #define FLAG_CRC_DISABLE 4u
\r
45 #define FLAG_EXCEED_LIMIT 8u
\r
51 #define MAC_FAIL (-1)
\r
52 #define MAC_WRONG_PARAMETER (-2)
\r
53 #define MAC_TOO_BIG_PACKET (-3)
\r
54 #define MAC_BUFFER_IS_FULL (-4)
\r
55 #define MAC_NOT_ENOUGH_SPACE (-5)
\r
56 #define MAC_TIME_OUT (-6)
\r
57 #define MAC_TOO_SMALL_PACKET (-7)
\r
59 /* Allocating this many buffers will always ensure there is one free as, even
\r
60 though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
\r
61 to the same buffer. */
\r
62 #define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 2
\r
63 #define macBUFFER_SIZE 1488
\r
65 /***************************************************************/
\r
66 MAC_instance_t g_mss_mac;
\r
68 /**************************** INTERNAL DATA ***********************************/
\r
69 #define ERROR_MESSAGE_COUNT 8
\r
70 #define MAX_ERROR_MESSAGE_WIDTH 40
\r
71 static const int8_t unknown_error[] = "Unknown error";
\r
72 static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
\r
75 "Wrong parameter pased to function",
\r
76 "Frame is too long",
\r
77 "Not enough space in buffer",
\r
78 "Not enough space in buffer",
\r
80 "Frame is too small"
\r
86 static uint8_t* NULL_buffer;
\r
87 static MSS_MAC_callback_t NULL_callback;
\r
89 /* Declare the uip_buf as a pointer, rather than the traditional array, as this
\r
90 is a zero copy driver. uip_buf just gets set to whichever buffer is being
\r
92 unsigned char *uip_buf = NULL;
\r
94 /**************************** INTERNAL FUNCTIONS ******************************/
\r
96 static int32_t MAC_dismiss_bad_frames( void );
\r
97 static int32_t MAC_send_setup_frame( void );
\r
99 static int32_t MAC_stop_transmission( void );
\r
100 static void MAC_start_transmission( void );
\r
101 static int32_t MAC_stop_receiving( void );
\r
102 static void MAC_start_receiving( void );
\r
104 static void MAC_set_time_out( uint32_t time_out );
\r
105 static uint32_t MAC_get_time_out( void );
\r
107 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n);
\r
108 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);
\r
109 static void MAC_memset_All(MAC_instance_t *s, uint32_t c);
\r
111 static unsigned char *MAC_obtain_buffer( void );
\r
112 static void MAC_release_buffer( unsigned char *pcBufferToRelease );
\r
114 #if( TX_RING_SIZE != 2 )
\r
115 #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2
\r
118 /* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.
\r
119 The union is used for alignment only. */
\r
120 static union xMAC_BUFFERS
\r
122 unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */
\r
123 unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
\r
126 /* Each array position indicates whether or not the buffer of the same index
\r
127 is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */
\r
128 static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
\r
130 /***************************************************************************//**
\r
131 * Initializes the Ethernet Controller.
\r
132 * This function will prepare the Ethernet Controller for first time use in a
\r
133 * given hardware/software configuration. This function should be called before
\r
134 * any other Ethernet API functions are called.
\r
136 * Initialization of registers - config registers, enable Tx/Rx interrupts,
\r
137 * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address
\r
138 * filter table (unicats/multicast)/hash init
\r
143 uint8_t phy_address
\r
146 const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };
\r
149 /* To start with all buffers are free. */
\r
150 for( a = 0; a < macNUM_BUFFERS; a++ )
\r
152 ucMACBufferInUse[ a ] = pdFALSE;
\r
155 /* Try to reset chip */
\r
156 MAC_BITBAND->CSR0_SWR = 1u;
\r
161 } while ( 1u == MAC_BITBAND->CSR0_SWR );
\r
163 /* Check reset values of some registers to constrol
\r
164 * base address validity */
\r
165 configASSERT( MAC->CSR0 == 0xFE000000uL );
\r
166 configASSERT( MAC->CSR5 == 0xF0000000uL );
\r
167 configASSERT( MAC->CSR6 == 0x32000040uL );
\r
169 /* Instance setup */
\r
170 MAC_memset_All( &g_mss_mac, 0u );
\r
172 g_mss_mac.base_address = MAC_BASE;
\r
173 g_mss_mac.phy_address = phy_address;
\r
175 for( a=0; a<RX_RING_SIZE; a++ )
\r
177 /* Give the ownership to the MAC */
\r
178 g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;
\r
179 g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);
\r
181 /* Allocate a buffer to the descriptor, then mark the buffer as in use
\r
183 g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );
\r
184 ucMACBufferInUse[ a ] = pdTRUE;
\r
186 g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
\r
188 for( a = 0; a < TX_RING_SIZE; a++ )
\r
190 /* Buffers only get allocated to the Tx buffers when something is
\r
191 actually tranmitted. */
\r
192 g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL;
\r
194 g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;
\r
196 /* Configurable settings */
\r
197 MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;
\r
198 MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);
\r
199 MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;
\r
200 MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
\r
202 /* Fixed settings */
\r
203 /* No space between descriptors */
\r
204 MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
\r
205 /* General-purpose timer works in continuous mode */
\r
206 MAC_BITBAND->CSR11_CON = 1u;
\r
207 /* Start general-purpose */
\r
208 MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
\r
210 /* Disable transmit interrupt mitigation. */
\r
211 MAC->CSR11 = ( MAC->CSR11 & ~CSR11_TT_MASK );
\r
212 MAC->CSR11 = ( MAC->CSR11 & ~CSR11_NTP_MASK );
\r
214 /* Automatic Tx descriptor polling. */
\r
215 MAC->CSR0 = ( MAC->CSR0 & ~CSR0_TAP_MASK );
\r
216 MAC->CSR0 = ( MAC->CSR0 | ( 0x01 << CSR0_TAP_SHIFT ) );
\r
218 /* Set descriptors */
\r
219 MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
\r
220 MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);
\r
222 /* enable normal interrupts */
\r
223 MAC_BITBAND->CSR7_NIE = 1u;
\r
225 /* Set default MAC address and reset mac filters */
\r
226 MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
\r
227 MSS_MAC_set_mac_address((uint8_t *)mac_address);
\r
230 if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
\r
233 configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
\r
239 /* Configure chip according to PHY status */
\r
240 MSS_MAC_auto_setup_link();
\r
242 /* Ensure uip_buf starts by pointing somewhere. */
\r
243 uip_buf = MAC_obtain_buffer();
\r
247 /***************************************************************************//**
\r
248 * Sets the configuration of the Ethernet Controller.
\r
249 * After the EthernetInit function has been called, this API function can be
\r
250 * used to configure the various features of the Ethernet Controller.
\r
252 * @param instance Pointer to a MAC_instance_t structure
\r
253 * @param config The logical OR of the following values:
\r
254 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
255 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
256 * - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD
\r
257 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
258 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
259 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
260 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
261 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
262 * @see MAC_get_configuration()
\r
267 uint32_t configuration
\r
272 ret = MAC_stop_transmission();
\r
273 configASSERT( ret == MAC_OK );
\r
275 ret = MAC_stop_receiving();
\r
276 configASSERT( ret == MAC_OK );
\r
278 MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
\r
279 MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
\r
280 MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
\r
282 switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
\r
283 case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
\r
284 MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
\r
286 case MSS_MAC_CFG_THRESHOLD_CONTROL_01:
\r
287 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );
\r
289 case MSS_MAC_CFG_THRESHOLD_CONTROL_10:
\r
290 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );
\r
292 case MSS_MAC_CFG_THRESHOLD_CONTROL_11:
\r
293 MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );
\r
298 MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );
\r
299 MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );
\r
300 MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );
\r
301 MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );
\r
302 PHY_set_link_type( (uint8_t)
\r
303 ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |
\r
304 (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );
\r
306 MSS_MAC_auto_setup_link();
\r
310 /***************************************************************************//**
\r
311 * Returns the configuration of the Ethernet Controller.
\r
313 * @param instance Pointer to a MAC_instance_t structure
\r
314 * @return The logical OR of the following values:
\r
315 * - #MSS_MAC_CFG_RECEIVE_ALL
\r
316 * - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE
\r
317 * - #MSS_MAC_CFG_STORE_AND_FORWARD
\r
318 * - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]
\r
319 * - #MSS_MAC_CFG_FULL_DUPLEX_MODE
\r
320 * - #MSS_MAC_CFG_PASS_ALL_MULTICAST
\r
321 * - #MSS_MAC_CFG_PROMISCUOUS_MODE
\r
322 * - #MSS_MAC_CFG_INVERSE_FILTERING
\r
323 * - #MSS_MAC_CFG_PASS_BAD_FRAMES
\r
324 * - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE
\r
325 * - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE
\r
326 * @see MAC_configure()
\r
329 MSS_MAC_get_configuration( void )
\r
331 uint32_t configuration;
\r
333 configuration = 0u;
\r
334 if( MAC_BITBAND->CSR6_RA != 0u ) {
\r
335 configuration |= MSS_MAC_CFG_RECEIVE_ALL;
\r
338 if( MAC_BITBAND->CSR6_TTM != 0u ) {
\r
339 configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;
\r
342 if( MAC_BITBAND->CSR6_SF != 0u ) {
\r
343 configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;
\r
346 switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {
\r
347 case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;
\r
348 case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;
\r
349 case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;
\r
352 if( MAC_BITBAND->CSR6_FD != 0u ) {
\r
353 configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;
\r
356 if( MAC_BITBAND->CSR6_PM != 0u ) {
\r
357 configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;
\r
360 if( MAC_BITBAND->CSR6_PR != 0u ) {
\r
361 configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;
\r
364 if( MAC_BITBAND->CSR6_IF != 0u ) {
\r
365 configuration |= MSS_MAC_CFG_INVERSE_FILTERING;
\r
368 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
369 configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;
\r
372 if( MAC_BITBAND->CSR6_HO != 0u ) {
\r
373 configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;
\r
376 if( MAC_BITBAND->CSR6_HP != 0u ) {
\r
377 configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
\r
380 return (int32_t)configuration;
\r
384 /***************************************************************************//**
\r
385 Sends a packet from the uIP stack to the Ethernet Controller.
\r
386 The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
\r
387 MAC. This function writes uip_len bytes of the packet contained in uip_buf into
\r
388 the transmit FIFO and then activates the transmitter for this packet. If space
\r
389 is available in the FIFO, the function will return once pac_len bytes of the
\r
390 packet have been placed into the FIFO and the transmitter has been started.
\r
391 This function will not wait for the transmission to complete.
\r
394 The function returns zero if a timeout occurs otherwise it returns size of the packet.
\r
396 @see MAC_rx_packet()
\r
402 unsigned short usLength
\r
406 unsigned long ulDescriptor;
\r
407 int32_t error = MAC_OK;
\r
409 configASSERT( uip_buf != NULL_buffer );
\r
411 configASSERT( usLength >= 12 );
\r
413 if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
\r
415 configASSERT( usLength <= MSS_MAX_PACKET_SIZE );
\r
418 /* Check if second descriptor is free, if it is then the first must
\r
420 if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )
\r
422 error = MAC_BUFFER_IS_FULL;
\r
424 /* Check the buffers pointed to by the Tx descriptors, just in case a Tx
\r
425 interrupt has been missed and a free buffer remains marked as in use. */
\r
426 MSS_MAC_CheckTxBufferStatus();
\r
430 if( error == MAC_OK )
\r
432 /* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
\r
434 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
\r
436 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
\r
438 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
\r
439 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
\r
442 /* Every buffer can hold a full frame so they are always first and last
\r
444 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
\r
446 /* set data size */
\r
447 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
\r
449 /* reset end of ring */
\r
450 g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
\r
452 if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
\r
454 usLength = (uint16_t)MSS_TX_BUFF_SIZE;
\r
457 /* The data buffer is assigned to the Tx descriptor. */
\r
458 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;
\r
460 /* update counters */
\r
461 desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
\r
462 if( (desc & TDES0_LO) != 0u ) {
\r
463 g_mss_mac.statistics.tx_loss_of_carrier++;
\r
465 if( (desc & TDES0_NC) != 0u ) {
\r
466 g_mss_mac.statistics.tx_no_carrier++;
\r
468 if( (desc & TDES0_LC) != 0u ) {
\r
469 g_mss_mac.statistics.tx_late_collision++;
\r
471 if( (desc & TDES0_EC) != 0u ) {
\r
472 g_mss_mac.statistics.tx_excessive_collision++;
\r
474 if( (desc & TDES0_UF) != 0u ) {
\r
475 g_mss_mac.statistics.tx_underflow_error++;
\r
477 g_mss_mac.statistics.tx_collision_count +=
\r
478 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
\r
480 /* Give ownership of descriptor to the MAC */
\r
481 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;
\r
483 g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
\r
485 MAC_start_transmission();
\r
490 if (error == MAC_OK)
\r
492 error = (int32_t)usLength;
\r
494 /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
\r
495 Find anothere free buffer for uip_buf. */
\r
496 uip_buf = MAC_obtain_buffer();
\r
506 /***************************************************************************//**
\r
507 * Returns available packet size.
\r
509 * @param instance Pointer to a MAC_instance_t structure
\r
510 * @return size of packet, bigger than 0, if a packet is available.
\r
511 * If not, returns 0.
\r
512 * @see MAC_rx_packet()
\r
515 MSS_MAC_rx_pckt_size
\r
521 MAC_dismiss_bad_frames();
\r
523 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
\r
525 /* Current descriptor is empty */
\r
530 uint32_t frame_length;
\r
531 frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;
\r
532 retval = (int32_t)( frame_length );
\r
538 /***************************************************************************//**
\r
539 * Receives a packet from the Ethernet Controller into the uIP stack.
\r
540 * This function reads a packet from the receive FIFO of the controller and
\r
541 * places it into uip_buf.
\r
543 * @return Size of packet if packet fits in uip_buf.
\r
544 * 0 if there is no received packet.
\r
545 * @see MAC_rx_pckt_size()
\r
546 * @see MAC_tx_packet()
\r
554 uint16_t frame_length=0u;
\r
556 MAC_dismiss_bad_frames();
\r
558 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
\r
561 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>
\r
562 RDES0_FL_OFFSET ) & RDES0_FL_MASK );
\r
565 frame_length -= 4u;
\r
567 if( frame_length > macBUFFER_SIZE ) {
\r
568 return MAC_NOT_ENOUGH_SPACE;
\r
571 /* uip_buf is about to point to the buffer that contains the received
\r
572 data, mark the buffer that uip_buf is currently pointing to as free
\r
574 MAC_release_buffer( uip_buf );
\r
575 uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;
\r
577 /* The buffer the Rx descriptor was pointing to is now in use by the
\r
578 uIP stack - allocate a new buffer to the Rx descriptor. */
\r
579 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();
\r
581 MSS_MAC_prepare_rx_descriptor();
\r
583 return ((int32_t)frame_length);
\r
587 /***************************************************************************//**
\r
588 * Receives a packet from the Ethernet Controller.
\r
589 * This function reads a packet from the receive FIFO of the controller and
\r
590 * sets the address of pacData to the received data.
\r
591 * If time_out parameter is zero the function will return
\r
592 * immediately (after the copy operation if data is available. Otherwise the function
\r
593 * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
\r
594 * value is given as time_out, function will wait for the reception to complete.
\r
596 * @param instance Pointer to a MAC_instance_t structure
\r
597 * @param pacData The pointer to the packet data.
\r
598 * @param time_out Time out value in milli seconds for receiving.
\r
599 * if value is #MSS_MAC_BLOCKING, there will be no time out.
\r
600 * if value is #MSS_MAC_NONBLOCKING, function will return immediately
\r
601 * if there is no packet waiting.
\r
602 * Otherwise value must be greater than 0 and smaller than
\r
604 * @return Size of packet if packet fits in pacData.
\r
605 * 0 if there is no received packet.
\r
606 * @see MAC_rx_pckt_size()
\r
607 * @see MAC_tx_packet()
\r
610 MSS_MAC_rx_packet_ptrset
\r
616 uint16_t frame_length = 0u;
\r
619 configASSERT( (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 link = PHY_link_status();
\r
683 if( link == MSS_MAC_LINK_STATUS_LINK ) {
\r
684 link |= PHY_link_type();
\r
687 return ((int32_t)link);
\r
691 /***************************************************************************//**
\r
692 * Setups the link between PHY and MAC and returns the status of connection.
\r
694 * @return the logical OR of the following values:
\r
695 * #MSS_MAC_LINK_STATUS_LINK - Link up/down
\r
696 * #MSS_MAC_LINK_STATUS_100MB - Connection is 100Mb/10Mb
\r
697 * #MSS_MAC_LINK_STATUS_FDX - Connection is full/half duplex
\r
698 * @see MAC_link_status()
\r
701 MSS_MAC_auto_setup_link
\r
708 PHY_auto_negotiate();
\r
710 link = MSS_MAC_link_status();
\r
712 if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {
\r
714 ret = MAC_stop_transmission();
\r
715 MAC_CHECK( ret == MAC_OK, ret );
\r
717 ret = MAC_stop_receiving();
\r
718 MAC_CHECK( ret == MAC_OK, ret );
\r
719 MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );
\r
720 MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );
\r
721 MAC_start_transmission();
\r
722 MAC_start_receiving();
\r
729 /***************************************************************************//**
\r
730 * Sets mac address. New address must be unicast.
\r
732 * @param new_address Pointer to a MAC_instance_t structure
\r
733 * @see MAC_get_mac_address()
\r
736 MSS_MAC_set_mac_address
\r
738 const uint8_t *new_address
\r
741 /* Check if the new address is unicast */
\r
742 configASSERT( (new_address[0]&1) == 0 );
\r
744 MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
\r
746 if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
748 /* set unused filters to the new mac address */
\r
749 for( a=14*6; a>=0; a-=6 ) {
\r
750 if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {
\r
751 /* Filters with multicast addresses are used */
\r
754 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),
\r
755 g_mss_mac.mac_address, 6u );
\r
760 MAC_send_setup_frame();
\r
764 /***************************************************************************//**
\r
765 * Returns mac address.
\r
767 * @param address Pointer to receive the MAC address
\r
768 * @see MAC_set_mac_address()
\r
771 MSS_MAC_get_mac_address
\r
776 MAC_memcpy( address, g_mss_mac.mac_address, 6u );
\r
780 /***************************************************************************//**
\r
781 * Sets mac address filters. Addresses must be multicast.
\r
783 * @param filter_count number of addresses
\r
784 * @param filters Pointer to addresses to be filtered
\r
787 MSS_MAC_set_mac_filters
\r
789 uint16_t filter_count,
\r
790 const uint8_t *filters
\r
793 configASSERT( (filter_count==0) || (filters != NULL_buffer) );
\r
794 /* Check if the mac addresses is multicast */
\r
797 for( a = 0u; a < filter_count; a++ ) {
\r
798 configASSERT( (filters[a*6]&1) == 1 );
\r
802 if( filter_count <= 15 ){
\r
804 g_mss_mac.flags |= FLAG_PERFECT_FILTERING;
\r
806 /* copy new filters */
\r
807 MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));
\r
809 /* set unused filters to our mac address */
\r
810 for( a=filter_count; a<15; a++ ) {
\r
811 MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),
\r
812 g_mss_mac.mac_address, 6 );
\r
818 g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;
\r
820 /* reset hash table */
\r
821 MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );
\r
823 for( a=0, b=0; a<filter_count; a++, b+=6 ) {
\r
824 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;
\r
825 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);
\r
829 MAC_send_setup_frame();
\r
833 /***************************************************************************//**
\r
834 * MAC interrupt service routine.
\r
836 * @param instance Pointer to a MAC_instance_t structure
\r
837 * @see MAC_set_callback()
\r
839 #if defined(__GNUC__)
\r
840 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )
\r
842 void EthernetMAC_IRQHandler( void )
\r
846 uint32_t intr_status;
\r
849 intr_status = MAC->CSR5;
\r
851 if( (intr_status & CSR5_NIS_MASK) != 0u ) {
\r
852 if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */
\r
853 g_mss_mac.statistics.tx_interrupts++;
\r
854 events |= MSS_MAC_EVENT_PACKET_SEND;
\r
857 if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */
\r
858 g_mss_mac.statistics.rx_interrupts++;
\r
859 events |= MSS_MAC_EVENT_PACKET_RECEIVED;
\r
863 /* Clear interrupts */
\r
864 MAC->CSR5 = CSR5_INT_BITS;
\r
866 if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
\r
867 g_mss_mac.listener( events );
\r
872 /***************************************************************************//**
\r
873 * Sets MAC event listener.
\r
874 * Sets the given event listener function to be triggered inside MAC_isr().
\r
875 * Assigning NULL pointer as the listener function will disable it.
\r
877 * @param instance Pointer to a MAC_instance_t structure
\r
878 * @param listener function pointer to a MAC_callback_t function
\r
879 * @return #MAC_OK if everything is OK
\r
880 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
885 MSS_MAC_set_callback
\r
887 MSS_MAC_callback_t listener
\r
890 /* disable tx and rx interrupts */
\r
891 MAC_BITBAND->CSR7_RIE = 0u;
\r
892 MAC_BITBAND->CSR7_TIE = 0u;
\r
894 g_mss_mac.listener = listener;
\r
896 if( listener != NULL_callback ) {
\r
897 /* enable tx and rx interrupts */
\r
898 MAC_BITBAND->CSR7_RIE = 1u;
\r
899 MAC_BITBAND->CSR7_TIE = 1u;
\r
904 /***************************************************************************//**
\r
905 * Returns description of last error.
\r
907 * @param instance Pointer to a MAC_instance_t structure
\r
908 * @return A string describing the error. This string must not be
\r
909 * modified by the application.
\r
910 * #MAC_WRONG_PARAMETER if instance is null or hasn't been
\r
919 int8_t error_msg_nb;
\r
920 const int8_t* returnvalue;
\r
922 error_msg_nb = -(g_mss_mac.last_error);
\r
923 if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
\r
924 returnvalue = unknown_error;
\r
926 returnvalue = ErrorMessages[error_msg_nb];
\r
928 return returnvalue;
\r
932 /***************************************************************************//**
\r
933 * Returns statistics counter of stat_id identifier.
\r
935 * @param instance Pointer to a MAC_instance_t structure
\r
936 * @param stat_id Identifier of statistics counter.
\r
937 * @return Statistics counter of stat_id identifier.
\r
938 * On error returns 0.
\r
941 MSS_MAC_get_statistics
\r
943 mss_mac_statistics_id_t stat_id
\r
946 uint32_t returnval = 0u;
\r
948 switch( stat_id ) {
\r
949 case MSS_MAC_RX_INTERRUPTS:
\r
950 returnval = g_mss_mac.statistics.rx_interrupts;
\r
952 case MSS_MAC_RX_FILTERING_FAIL:
\r
953 returnval = g_mss_mac.statistics.rx_filtering_fail;
\r
955 case MSS_MAC_RX_DESCRIPTOR_ERROR:
\r
956 returnval = g_mss_mac.statistics.rx_descriptor_error;
\r
958 case MSS_MAC_RX_RUNT_FRAME:
\r
959 returnval = g_mss_mac.statistics.rx_runt_frame;
\r
961 case MSS_MAC_RX_NOT_FIRST:
\r
962 returnval = g_mss_mac.statistics.rx_not_first;
\r
964 case MSS_MAC_RX_NOT_LAST:
\r
965 returnval = g_mss_mac.statistics.rx_not_last;
\r
967 case MSS_MAC_RX_FRAME_TOO_LONG:
\r
968 returnval = g_mss_mac.statistics.rx_frame_too_long;
\r
970 case MSS_MAC_RX_COLLISION_SEEN:
\r
971 returnval = g_mss_mac.statistics.rx_collision_seen;
\r
973 case MSS_MAC_RX_CRC_ERROR:
\r
974 returnval = g_mss_mac.statistics.rx_crc_error;
\r
976 case MSS_MAC_RX_FIFO_OVERFLOW:
\r
977 returnval = g_mss_mac.statistics.rx_fifo_overflow;
\r
979 case MSS_MAC_RX_MISSED_FRAME:
\r
980 returnval = g_mss_mac.statistics.rx_missed_frame;
\r
982 case MSS_MAC_TX_INTERRUPTS:
\r
983 returnval = g_mss_mac.statistics.tx_interrupts;
\r
985 case MSS_MAC_TX_LOSS_OF_CARRIER:
\r
986 returnval = g_mss_mac.statistics.tx_loss_of_carrier;
\r
988 case MSS_MAC_TX_NO_CARRIER:
\r
989 returnval = g_mss_mac.statistics.tx_no_carrier;
\r
991 case MSS_MAC_TX_LATE_COLLISION:
\r
992 returnval = g_mss_mac.statistics.tx_late_collision;
\r
994 case MSS_MAC_TX_EXCESSIVE_COLLISION:
\r
995 returnval = g_mss_mac.statistics.tx_excessive_collision;
\r
997 case MSS_MAC_TX_COLLISION_COUNT:
\r
998 returnval = g_mss_mac.statistics.tx_collision_count;
\r
1000 case MSS_MAC_TX_UNDERFLOW_ERROR:
\r
1001 returnval = g_mss_mac.statistics.tx_underflow_error;
\r
1011 /**************************** INTERNAL FUNCTIONS ******************************/
\r
1014 /***************************************************************************//**
\r
1015 * Prepares current rx descriptor for receiving.
\r
1018 MSS_MAC_prepare_rx_descriptor
\r
1025 /* update counters */
\r
1026 desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;
\r
1027 if( (desc & RDES0_FF) != 0u ) {
\r
1028 g_mss_mac.statistics.rx_filtering_fail++;
\r
1030 if( (desc & RDES0_DE) != 0u ) {
\r
1031 g_mss_mac.statistics.rx_descriptor_error++;
\r
1033 if( (desc & RDES0_RF) != 0u ) {
\r
1034 g_mss_mac.statistics.rx_runt_frame++;
\r
1036 if( (desc & RDES0_FS) == 0u ) {
\r
1037 g_mss_mac.statistics.rx_not_first++;
\r
1039 if( (desc & RDES0_LS) == 0u ) {
\r
1040 g_mss_mac.statistics.rx_not_last++;
\r
1042 if( (desc & RDES0_TL) != 0u ) {
\r
1043 g_mss_mac.statistics.rx_frame_too_long++;
\r
1045 if( (desc & RDES0_CS) != 0u ) {
\r
1046 g_mss_mac.statistics.rx_collision_seen++;
\r
1048 if( (desc & RDES0_CE) != 0u ) {
\r
1049 g_mss_mac.statistics.rx_crc_error++;
\r
1053 g_mss_mac.statistics.rx_fifo_overflow +=
\r
1054 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
\r
1055 g_mss_mac.statistics.rx_missed_frame +=
\r
1056 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
\r
1058 /* Give ownership of descriptor to the MAC */
\r
1059 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =
\r
1061 g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
\r
1063 /* Start receive */
\r
1064 MAC_start_receiving();
\r
1068 /***************************************************************************//**
\r
1069 * Prepares a setup frame and sends it to MAC.
\r
1070 * This function is blocking.
\r
1071 * @return #MAC_OK if everything is ok.
\r
1072 * #MAC_TIME_OUT if timed out before packet send.
\r
1075 MAC_send_setup_frame
\r
1080 volatile MAC_descriptor_t descriptor;
\r
1081 uint8_t frame_data[192];
\r
1086 /* prepare descriptor */
\r
1087 descriptor.descriptor_0 = TDES0_OWN;
\r
1088 descriptor.descriptor_1 = TDES1_SET | TDES1_TER |
\r
1089 (sizeof(frame_data) << TDES1_TBS1_OFFSET);
\r
1091 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {
\r
1092 descriptor.descriptor_1 |= TDES1_FT0;
\r
1095 descriptor.buffer_1 = (uint32_t)frame_data;
\r
1096 descriptor.buffer_2 = 0u;
\r
1098 /* prepare frame */
\r
1099 if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {
\r
1109 data = g_mss_mac.mac_address;
\r
1110 frame_data[b] = data[0];
\r
1111 frame_data[b+1] = data[1];
\r
1112 frame_data[b+4] = data[2];
\r
1113 frame_data[b+5] = data[3];
\r
1114 frame_data[b+8] = data[4];
\r
1115 frame_data[b+9] = data[5];
\r
1117 data = g_mss_mac.mac_filter_data;
\r
1118 for( a = 0; a < c; ) {
\r
1119 frame_data[d] = data[a++];
\r
1120 frame_data[d+1] = data[a++];
\r
1121 frame_data[d+4] = data[a++];
\r
1122 frame_data[d+5] = data[a++];
\r
1123 frame_data[d+8] = data[a++];
\r
1124 frame_data[d+9] = data[a++];
\r
1128 /* Stop transmission */
\r
1129 ret = MAC_stop_transmission();
\r
1130 configASSERT( ret == MAC_OK );
\r
1132 ret = MAC_stop_receiving();
\r
1133 configASSERT( ret == MAC_OK );
\r
1135 /* Set descriptor */
\r
1136 MAC->CSR4 = (uint32_t)&descriptor;
\r
1138 /* Start transmission */
\r
1139 MAC_start_transmission();
\r
1141 /* Wait until transmission over */
\r
1143 MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
\r
1145 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1146 CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
\r
1148 /* transmit poll demand */
\r
1150 if( MAC_get_time_out() == 0u ) {
\r
1151 ret = MAC_TIME_OUT;
\r
1155 MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );
\r
1157 /* Set tx descriptor */
\r
1158 MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
\r
1160 /* Start receiving and transmission */
\r
1161 MAC_start_receiving();
\r
1162 MAC_start_transmission();
\r
1168 /***************************************************************************//**
\r
1169 * Stops transmission.
\r
1170 * Function will wait until transmit operation enters stop state.
\r
1172 * @return #MAC_OK if everything is ok.
\r
1173 * #MAC_TIME_OUT if timed out.
\r
1176 MAC_stop_transmission
\r
1181 int32_t retval = MAC_OK;
\r
1182 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1184 while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
\r
1185 CSR5_TS_STOPPED) && (retval == MAC_OK) )
\r
1187 MAC_BITBAND->CSR6_ST = 0u;
\r
1188 if( MAC_get_time_out() == 0u ) {
\r
1189 retval = MAC_TIME_OUT;
\r
1196 /***************************************************************************//**
\r
1197 * Starts transmission.
\r
1200 MAC_start_transmission
\r
1205 MAC_BITBAND->CSR6_ST = 1u;
\r
1209 /***************************************************************************//**
\r
1210 * Stops transmission.
\r
1211 * Function will wait until transmit operation enters stop state.
\r
1213 * @return #MAC_OK if everything is ok.
\r
1214 * #MAC_TIME_OUT if timed out.
\r
1217 MAC_stop_receiving
\r
1222 int32_t retval = MAC_OK;
\r
1223 MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
\r
1225 while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)
\r
1226 && (retval == MAC_OK) )
\r
1228 MAC_BITBAND->CSR6_SR = 0u;
\r
1229 if( MAC_get_time_out() == 0u ) {
\r
1230 retval = MAC_TIME_OUT;
\r
1238 /***************************************************************************//**
\r
1239 * Starts transmission.
\r
1242 MAC_start_receiving
\r
1247 MAC_BITBAND->CSR6_SR = 1u;
\r
1251 /***************************************************************************//**
\r
1252 * Dismisses bad frames.
\r
1254 * @return dismissed frame count.
\r
1257 MAC_dismiss_bad_frames
\r
1265 if( MAC_BITBAND->CSR6_PB != 0u ) {
\r
1266 /* User wants bad frames too, don't dismiss anything */
\r
1270 while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1271 RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */
\r
1273 /* check error summary */
\r
1274 if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &
\r
1275 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )
\r
1277 MSS_MAC_prepare_rx_descriptor();
\r
1289 /***************************************************************************//**
\r
1290 * Sets time out value.
\r
1291 * #MAC_get_time_out must be called frequently to make time out value updated.
\r
1292 * Because of user may not be using ISR, we can not update time out in ISR.
\r
1294 * @time_out time out value in milli seconds.
\r
1295 * Must be smaller than 0x01000000.
\r
1303 g_mss_mac.time_out_value = (time_out * 122u) / 10u;
\r
1305 g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );
\r
1308 /***************************************************************************//**
\r
1309 * Returns time out value.
\r
1311 * @return timer out value in milli seconds.
\r
1320 uint32_t time = 0u;
\r
1322 timer = ( MAC->CSR11 & CSR11_TIM_MASK );
\r
1324 if( timer > g_mss_mac.last_timer_value ) {
\r
1325 time = 0x0000ffffUL;
\r
1327 time += g_mss_mac.last_timer_value - timer;
\r
1329 if( MAC_BITBAND->CSR6_TTM == 0u ) {
\r
1332 if( g_mss_mac.time_out_value <= time ){
\r
1333 g_mss_mac.time_out_value = 0u;
\r
1335 g_mss_mac.time_out_value -= time;
\r
1338 g_mss_mac.last_timer_value = (uint16_t)timer;
\r
1340 return ((g_mss_mac.time_out_value * 10u) / 122u);
\r
1343 /***************************************************************************//**
\r
1344 * Fills the first n bytes of the memory area pointed to by s with the constant
\r
1347 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)
\r
1357 /***************************************************************************//**
\r
1358 * Fills all fields of MAC_instance_t with c.
\r
1360 * @return a pointer to the given MAC_instance_t s.
\r
1362 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
\r
1365 s->base_address = (addr_t)c;
\r
1366 s->flags = (uint8_t)c;
\r
1367 s->last_error = (int8_t)c;
\r
1368 s->last_timer_value = (uint16_t)c;
\r
1369 s->listener = NULL_callback;
\r
1370 MAC_memset( s->mac_address, (uint8_t)c, 6u );
\r
1371 MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
\r
1372 s->phy_address = (uint8_t)c;
\r
1373 s->rx_desc_index =c;
\r
1374 for(count = 0; count<RX_RING_SIZE ;count++)
\r
1376 s->rx_descriptors[count].buffer_1 = c;
\r
1377 s->rx_descriptors[count].buffer_2 = c;
\r
1378 s->rx_descriptors[count].descriptor_0 = c;
\r
1379 s->rx_descriptors[count].descriptor_1 = c;
\r
1381 s->statistics.rx_collision_seen =c;
\r
1382 s->statistics.rx_crc_error = c;
\r
1383 s->statistics.rx_descriptor_error = c;
\r
1384 s->statistics.rx_fifo_overflow = c;
\r
1385 s->statistics.rx_filtering_fail = c;
\r
1386 s->statistics.rx_frame_too_long = c;
\r
1387 s->statistics.rx_interrupts = c;
\r
1388 s->statistics.rx_missed_frame = c;
\r
1389 s->statistics.rx_not_first = c;
\r
1390 s->statistics.rx_not_last = c;
\r
1391 s->statistics.rx_runt_frame = c;
\r
1392 s->statistics.tx_collision_count = c;
\r
1393 s->statistics.tx_excessive_collision = c;
\r
1394 s->statistics.tx_interrupts = c;
\r
1395 s->statistics.tx_late_collision = c;
\r
1396 s->statistics.tx_loss_of_carrier = c;
\r
1397 s->statistics.tx_no_carrier = c;
\r
1398 s->statistics.tx_underflow_error = c;
\r
1399 s->time_out_value = c;
\r
1400 s->tx_desc_index = c;
\r
1401 for(count = 0; count < TX_RING_SIZE ;count++)
\r
1403 s->tx_descriptors[count].buffer_1 = c;
\r
1404 s->tx_descriptors[count].buffer_2 = c;
\r
1405 s->tx_descriptors[count].descriptor_0 = c;
\r
1406 s->tx_descriptors[count].descriptor_1 = c;
\r
1410 /***************************************************************************//**
\r
1411 * Copies n bytes from memory area src to memory area dest.
\r
1412 * The memory areas should not overlap.
\r
1414 * @return a pointer to the memory area dest.
\r
1416 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
\r
1418 uint8_t *d = dest;
\r
1426 /***************************************************************************//**
\r
1427 * Check the buffers assigned to the Tx descriptors to ensure that none remain
\r
1428 * marked as in use even though the Tx has completed. This could happen if a
\r
1429 * Tx interrupt was missed.
\r
1432 void MSS_MAC_CheckTxBufferStatus( void )
\r
1434 unsigned char *pxTransmittedBuffer;
\r
1435 long lDescriptor, lIndex;
\r
1437 for( lDescriptor = 1; lDescriptor < TX_RING_SIZE; lDescriptor++ )
\r
1439 if( ( g_mss_mac.tx_descriptors[ lDescriptor ].descriptor_0 & TDES0_OWN ) == 0UL )
\r
1441 pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1;
\r
1443 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1445 if( pxTransmittedBuffer == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
\r
1447 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1454 /***************************************************************************//**
\r
1455 * Look through the array of buffers until one is found that is free for use -
\r
1456 * that is, not currently assigned to an Rx or a Tx descriptor. Mark the buffer
\r
1457 * as in use, then return its address.
\r
1459 * @return a pointer to a free buffer.
\r
1461 unsigned char *MAC_obtain_buffer( void )
\r
1464 unsigned char *pcReturn = NULL;
\r
1466 /* Find and return the address of a buffer that is not being used. Mark
\r
1467 the buffer as now in use. */
\r
1468 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1470 if( ucMACBufferInUse[ lIndex ] == pdFALSE )
\r
1472 pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
\r
1473 ucMACBufferInUse[ lIndex ] = pdTRUE;
\r
1478 configASSERT( pcReturn );
\r
1482 /***************************************************************************//**
\r
1483 * Return a buffer to the list of free buffers, it was in use, but is not now.
\r
1486 void MAC_release_buffer( unsigned char *pucBufferToRelease )
\r
1490 /* uip_buf is going to point to a different buffer - first ensure the buffer
\r
1491 it is currently pointing to is marked as being free again. */
\r
1492 for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
\r
1494 if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
\r
1496 /* This is the buffer in use, mark it as being free. */
\r
1497 ucMACBufferInUse[ lIndex ] = pdFALSE;
\r
1502 /* Check the buffers pointed to by the Tx descriptors, just in case a Tx
\r
1503 interrupt has been missed and a free buffer remains marked as in use. */
\r
1504 MSS_MAC_CheckTxBufferStatus();
\r
1506 configASSERT( lIndex < macNUM_BUFFERS );
\r
1511 #ifdef __cplusplus
\r
1515 /******************************** END OF FILE *********************************/
\r