]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
Update MAC drivers so they use a uIP specific zero copy mechanism.
[freertos] / Demo / CORTEX_A2F200_IAR_and_Keil / MicroSemi_Code / drivers / mss_ethernet_mac / mss_ethernet_mac.c
1 /***************************************************************************//**\r
2  * @file\r
3  * SmartFusion MSS Ethernet MAC driver implementation.\r
4  *\r
5  * (c) Copyright 2007 Actel Corporation\r
6  *\r
7  * SVN $Revision: 2369 $\r
8  * SVN $Date: 2010-03-01 18:31:45 +0000 (Mon, 01 Mar 2010) $\r
9  *\r
10  ******************************************************************************/\r
11 \r
12 /*\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
15  */\r
16 \r
17 #ifdef __cplusplus\r
18 extern "C" {\r
19 #endif\r
20 \r
21 #include "FreeRTOS.h"\r
22 #include "task.h"\r
23 \r
24 #include "crc32.h"\r
25 \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
31 \r
32 #include "phy.h"\r
33 \r
34 /**************************** INTERNAL DEFINES ********************************/\r
35 \r
36 #define MAC_CHECK(CHECK,ERRNO)  \\r
37         {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); configASSERT((CHECK));}}\r
38 \r
39 /*\r
40  * Flags\r
41  */\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
46 \r
47 /*\r
48  * Return types\r
49  */\r
50 #define MAC_OK                    0\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
58 \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
64 \r
65 /***************************************************************/\r
66 MAC_instance_t g_mss_mac;\r
67 \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
73         "No error occured",\r
74         "Method failed",\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
79         "Timed out",\r
80         "Frame is too small"\r
81 };\r
82 \r
83 /*\r
84  * Null variables\r
85  */\r
86 static uint8_t*                 NULL_buffer;\r
87 static MSS_MAC_callback_t       NULL_callback;\r
88 \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
91 processed. */\r
92 unsigned char *uip_buf = NULL;\r
93 \r
94 /**************************** INTERNAL FUNCTIONS ******************************/\r
95 \r
96 static int32_t  MAC_dismiss_bad_frames( void );\r
97 static int32_t  MAC_send_setup_frame( void );\r
98 \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
103 \r
104 static void             MAC_set_time_out( uint32_t time_out );\r
105 static uint32_t MAC_get_time_out( void );\r
106 \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
110 \r
111 static unsigned char *MAC_obtain_buffer( void );\r
112 static void MAC_release_buffer( unsigned char *pcBufferToRelease );\r
113 \r
114 #if( TX_RING_SIZE != 2 )\r
115         #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2\r
116 #endif\r
117 \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
121 {\r
122         unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */\r
123         unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];\r
124 } xMACBuffers;\r
125 \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
129 \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
135  *\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
139  */\r
140 void\r
141 MSS_MAC_init\r
142 (\r
143         uint8_t phy_address\r
144 )\r
145 {\r
146     const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };\r
147     int32_t a;\r
148 \r
149         /* To start with all buffers are free. */\r
150         for( a = 0; a < macNUM_BUFFERS; a++ )\r
151         {\r
152                 ucMACBufferInUse[ a ] = pdFALSE;\r
153         }\r
154         \r
155     /* Try to reset chip */\r
156     MAC_BITBAND->CSR0_SWR = 1u;\r
157 \r
158     do\r
159     {\r
160         vTaskDelay( 10 );\r
161     } while ( 1u == MAC_BITBAND->CSR0_SWR );\r
162 \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
168 \r
169     /* Instance setup */\r
170     MAC_memset_All( &g_mss_mac, 0u );\r
171 \r
172     g_mss_mac.base_address = MAC_BASE;\r
173     g_mss_mac.phy_address = phy_address;\r
174 \r
175     for( a=0; a<RX_RING_SIZE; a++ )\r
176     {\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
180                 \r
181                 /* Allocate a buffer to the descriptor, then mark the buffer as in use\r
182                 (not free). */\r
183         g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );\r
184                 ucMACBufferInUse[ a ] = pdTRUE;\r
185     }\r
186     g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;\r
187 \r
188     for( a = 0; a < TX_RING_SIZE; a++ )\r
189     {\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
193     }\r
194     g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;\r
195 \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
201 \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
209 \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
213 \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
217         \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
221 \r
222         /* enable normal interrupts */\r
223     MAC_BITBAND->CSR7_NIE = 1u;\r
224 \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
228         \r
229     /* Detect PHY */\r
230     if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )\r
231     {\r
232         PHY_probe();\r
233         configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );\r
234     }\r
235 \r
236     /* Reset PHY */\r
237     PHY_reset();\r
238 \r
239         /* Configure chip according to PHY status */\r
240     MSS_MAC_auto_setup_link();\r
241         \r
242         /* Ensure uip_buf starts by pointing somewhere. */\r
243         uip_buf = MAC_obtain_buffer();  \r
244 }\r
245 \r
246 \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
251  *\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
263  */\r
264 void\r
265 MSS_MAC_configure\r
266 (\r
267     uint32_t configuration\r
268 )\r
269 {\r
270     int32_t ret;\r
271 \r
272     ret = MAC_stop_transmission();\r
273     configASSERT( ret == MAC_OK );\r
274 \r
275     ret = MAC_stop_receiving();\r
276     configASSERT( ret == MAC_OK );\r
277 \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
281 \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
285         break;\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
288         break;\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
291         break;\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
294         break;\r
295     default:\r
296         break;\r
297     }\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
305 \r
306     MSS_MAC_auto_setup_link();\r
307 }\r
308 \r
309 \r
310 /***************************************************************************//**\r
311  * Returns the configuration of the Ethernet Controller.\r
312  *\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
327  */\r
328 int32_t\r
329 MSS_MAC_get_configuration( void )\r
330 {\r
331     uint32_t configuration;\r
332 \r
333     configuration = 0u;\r
334     if( MAC_BITBAND->CSR6_RA != 0u ) {\r
335         configuration |= MSS_MAC_CFG_RECEIVE_ALL;\r
336     }\r
337 \r
338     if( MAC_BITBAND->CSR6_TTM != 0u ) {\r
339         configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;\r
340     }\r
341 \r
342     if( MAC_BITBAND->CSR6_SF != 0u ) {\r
343         configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;\r
344     }\r
345 \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
350     default: break;\r
351     }\r
352     if( MAC_BITBAND->CSR6_FD != 0u ) {\r
353         configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;\r
354     }\r
355 \r
356     if( MAC_BITBAND->CSR6_PM != 0u ) {\r
357         configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;\r
358     }\r
359 \r
360     if( MAC_BITBAND->CSR6_PR != 0u ) {\r
361         configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;\r
362     }\r
363 \r
364     if( MAC_BITBAND->CSR6_IF != 0u ) {\r
365         configuration |= MSS_MAC_CFG_INVERSE_FILTERING;\r
366     }\r
367 \r
368     if( MAC_BITBAND->CSR6_PB != 0u ) {\r
369         configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;\r
370     }\r
371 \r
372     if( MAC_BITBAND->CSR6_HO != 0u ) {\r
373         configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;\r
374     }\r
375 \r
376     if( MAC_BITBAND->CSR6_HP != 0u ) {\r
377         configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;\r
378     }\r
379 \r
380     return (int32_t)configuration;\r
381 }\r
382 \r
383 \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
392 \r
393   @return\r
394     The function returns zero if a timeout occurs otherwise it returns size of the packet.\r
395 \r
396   @see   MAC_rx_packet()\r
397  */\r
398 \r
399 int32_t\r
400 MSS_MAC_tx_packet\r
401 (\r
402     unsigned short usLength\r
403 )\r
404 {\r
405         uint32_t desc;\r
406         unsigned long ulDescriptor;\r
407     int32_t error = MAC_OK;\r
408 \r
409     configASSERT( uip_buf != NULL_buffer );\r
410 \r
411         configASSERT( usLength >= 12 );\r
412 \r
413     if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )\r
414     {\r
415                 configASSERT( usLength <= MSS_MAX_PACKET_SIZE );\r
416         }\r
417 \r
418         /* Check if second descriptor is free, if it is then the first must\r
419         also be free. */\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
421         {\r
422                 error = MAC_BUFFER_IS_FULL;\r
423                 \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
427         }\r
428 \r
429         \r
430         if( error == MAC_OK )\r
431         {\r
432                 /* Assumed TX_RING_SIZE == 2.  A #error directive checks this is the\r
433                 case. */\r
434                 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
435                 {\r
436                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
437 \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
440                         }\r
441 \r
442                         /* Every buffer can hold a full frame so they are always first and last\r
443                            descriptor */\r
444                 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;\r
445 \r
446                         /* set data size */\r
447                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;\r
448 \r
449                         /* reset end of ring */\r
450                         g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
451 \r
452                         if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
453                         {\r
454                                 usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
455                         }\r
456 \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
459 \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
464                         }\r
465                         if( (desc & TDES0_NC) != 0u ) {\r
466                                 g_mss_mac.statistics.tx_no_carrier++;\r
467                         }\r
468                         if( (desc & TDES0_LC) != 0u ) {\r
469                                 g_mss_mac.statistics.tx_late_collision++;\r
470                         }\r
471                         if( (desc & TDES0_EC) != 0u ) {\r
472                                 g_mss_mac.statistics.tx_excessive_collision++;\r
473                         }\r
474                         if( (desc & TDES0_UF) != 0u ) {\r
475                                 g_mss_mac.statistics.tx_underflow_error++;\r
476                         }\r
477                         g_mss_mac.statistics.tx_collision_count +=\r
478                                 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
479 \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
482                         \r
483                         g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
484                         \r
485                         MAC_start_transmission();\r
486                         MAC->CSR1 = 1u;\r
487                 }               \r
488     }\r
489         \r
490     if (error == MAC_OK)\r
491     {\r
492         error = (int32_t)usLength;\r
493                 \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
497     }\r
498     else\r
499     {\r
500         error = 0;\r
501     }\r
502     return ( error );\r
503 }\r
504 \r
505 \r
506 /***************************************************************************//**\r
507  * Returns available packet size.\r
508  *\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
513  */\r
514 int32_t\r
515 MSS_MAC_rx_pckt_size\r
516 (\r
517     void\r
518 )\r
519 {\r
520     int32_t retval;\r
521     MAC_dismiss_bad_frames();\r
522 \r
523     if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &     RDES0_OWN) != 0u )\r
524     {\r
525         /* Current descriptor is empty */\r
526         retval = 0;\r
527     }\r
528     else\r
529     {\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
533     }\r
534     return retval;\r
535 }\r
536 \r
537 \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
542 \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
547  */\r
548 int32_t\r
549 MSS_MAC_rx_packet\r
550 (\r
551         void\r
552 )\r
553 {\r
554         uint16_t frame_length=0u;\r
555 \r
556     MAC_dismiss_bad_frames();\r
557 \r
558     if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )\r
559     {\r
560         frame_length = ( (\r
561             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
562             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
563 \r
564         /* strip crc */\r
565         frame_length -= 4u;\r
566 \r
567         if( frame_length > macBUFFER_SIZE ) {\r
568                 return MAC_NOT_ENOUGH_SPACE;\r
569         }\r
570 \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
573                 again. */\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
576                 \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
580 \r
581         MSS_MAC_prepare_rx_descriptor();\r
582     }\r
583     return ((int32_t)frame_length);\r
584 }\r
585 \r
586 \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
595  *\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
603  *                                          0x01000000.\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
608  */\r
609 int32_t\r
610 MSS_MAC_rx_packet_ptrset\r
611 (\r
612     uint8_t **pacData,\r
613     uint32_t time_out\r
614 )\r
615 {\r
616         uint16_t frame_length = 0u;\r
617     int8_t exit = 0;\r
618 \r
619     configASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
620                         (time_out == MSS_MAC_NONBLOCKING) ||\r
621                         ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
622 \r
623     MAC_dismiss_bad_frames();\r
624 \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
629                 } else {\r
630                 MAC_set_time_out( time_out );\r
631                 }\r
632         }\r
633 \r
634     while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
635         RDES0_OWN) != 0u) && (exit == 0) )\r
636     {\r
637         if( time_out != MSS_MAC_BLOCKING )\r
638         {\r
639                 if( MAC_get_time_out() == 0u ) {\r
640                         exit = 1;\r
641                 }\r
642         }\r
643     }\r
644 \r
645     if(exit == 0)\r
646     {\r
647         frame_length = ( (\r
648             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
649             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
650 \r
651         /* strip crc */\r
652         frame_length -= 4u;\r
653 \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
658        */\r
659         *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;\r
660 \r
661     }\r
662     return ((int32_t)frame_length);\r
663 }\r
664 \r
665 /***************************************************************************//**\r
666  * Returns the status of connection.\r
667  *\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
673  */\r
674 int32_t\r
675 MSS_MAC_link_status\r
676 (\r
677     void\r
678 )\r
679 {\r
680         uint32_t link;\r
681 \r
682     link = PHY_link_status();\r
683     if( link == MSS_MAC_LINK_STATUS_LINK ) {\r
684         link |= PHY_link_type();\r
685     }\r
686 \r
687     return ((int32_t)link);\r
688 }\r
689 \r
690 \r
691 /***************************************************************************//**\r
692  * Setups the link between PHY and MAC and returns the status of connection.\r
693  *\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
699  */\r
700 int32_t\r
701 MSS_MAC_auto_setup_link\r
702 (\r
703     void\r
704 )\r
705 {\r
706         int32_t link;\r
707 \r
708     PHY_auto_negotiate();\r
709 \r
710     link = MSS_MAC_link_status();\r
711 \r
712     if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {\r
713         int32_t ret;\r
714             ret = MAC_stop_transmission();\r
715             MAC_CHECK( ret == MAC_OK, ret );\r
716 \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
723     }\r
724 \r
725     return link;\r
726 }\r
727 \r
728 \r
729 /***************************************************************************//**\r
730  * Sets mac address. New address must be unicast.\r
731  *\r
732  * @param new_address   Pointer to a MAC_instance_t structure\r
733  * @see   MAC_get_mac_address()\r
734  */\r
735 void\r
736 MSS_MAC_set_mac_address\r
737 (\r
738     const uint8_t *new_address\r
739 )\r
740 {\r
741     /* Check if the new address is unicast */\r
742     configASSERT( (new_address[0]&1) == 0 );\r
743 \r
744         MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );\r
745 \r
746         if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
747                 int32_t a;\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
752                                 a = -1;\r
753                         } else {\r
754                                 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),\r
755                                         g_mss_mac.mac_address, 6u );\r
756                         }\r
757                 }\r
758         }\r
759 \r
760         MAC_send_setup_frame();\r
761 }\r
762 \r
763 \r
764 /***************************************************************************//**\r
765  * Returns mac address.\r
766  *\r
767  * @param address       Pointer to receive the MAC address\r
768  * @see   MAC_set_mac_address()\r
769  */\r
770 void\r
771 MSS_MAC_get_mac_address\r
772 (\r
773     uint8_t *address\r
774 )\r
775 {\r
776         MAC_memcpy( address, g_mss_mac.mac_address, 6u );\r
777 }\r
778 \r
779 \r
780 /***************************************************************************//**\r
781  * Sets mac address filters. Addresses must be multicast.\r
782  *\r
783  * @param filter_count  number of addresses\r
784  * @param filters       Pointer to addresses to be filtered\r
785  */\r
786 void\r
787 MSS_MAC_set_mac_filters\r
788 (\r
789         uint16_t filter_count,\r
790         const uint8_t *filters\r
791 )\r
792 {\r
793     configASSERT( (filter_count==0) || (filters != NULL_buffer) );\r
794     /* Check if the mac addresses is multicast */\r
795     {\r
796         int32_t a;\r
797         for( a = 0u; a < filter_count; a++ ) {\r
798                 configASSERT( (filters[a*6]&1) == 1 );\r
799         }\r
800     }\r
801 \r
802     if( filter_count <= 15 ){\r
803         int32_t a;\r
804         g_mss_mac.flags |= FLAG_PERFECT_FILTERING;\r
805 \r
806         /* copy new filters */\r
807         MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));\r
808 \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
813         }\r
814     } else {\r
815         int32_t a,b;\r
816         uint32_t hash;\r
817 \r
818         g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;\r
819 \r
820         /* reset hash table */\r
821         MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );\r
822 \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
826         }\r
827     }\r
828 \r
829     MAC_send_setup_frame();\r
830 }\r
831 \r
832 \r
833 /***************************************************************************//**\r
834  * MAC interrupt service routine.\r
835  *\r
836  * @param instance      Pointer to a MAC_instance_t structure\r
837  * @see   MAC_set_callback()\r
838  */\r
839 #if defined(__GNUC__)\r
840 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )\r
841 #else\r
842 void EthernetMAC_IRQHandler( void )\r
843 #endif\r
844 {\r
845     uint32_t events;\r
846     uint32_t intr_status;\r
847 \r
848     events = 0u;\r
849     intr_status = MAC->CSR5;\r
850 \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
855         }\r
856 \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
860         }\r
861     }\r
862 \r
863     /* Clear interrupts */\r
864     MAC->CSR5 = CSR5_INT_BITS;\r
865 \r
866     if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {\r
867         g_mss_mac.listener( events );\r
868     }\r
869 }\r
870 \r
871 \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
876  *\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
881  *                                              initialized.\r
882  * @see   MAC_isr()\r
883  */\r
884 void\r
885 MSS_MAC_set_callback\r
886 (\r
887     MSS_MAC_callback_t listener\r
888 )\r
889 {\r
890         /* disable tx and rx interrupts */\r
891     MAC_BITBAND->CSR7_RIE = 0u;\r
892     MAC_BITBAND->CSR7_TIE = 0u;\r
893 \r
894     g_mss_mac.listener = listener;\r
895 \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
900         }\r
901 }\r
902 \r
903 \r
904 /***************************************************************************//**\r
905  * Returns description of last error.\r
906  *\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
911  *                      initialized.\r
912  */\r
913 const int8_t*\r
914 MSS_MAC_last_error\r
915 (\r
916     void\r
917 )\r
918 {\r
919         int8_t error_msg_nb;\r
920     const int8_t* returnvalue;\r
921 \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
925         } else {\r
926                 returnvalue = ErrorMessages[error_msg_nb];\r
927         }\r
928         return returnvalue;\r
929 }\r
930 \r
931 \r
932 /***************************************************************************//**\r
933  * Returns statistics counter of stat_id identifier.\r
934  *\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
939  */\r
940 uint32_t\r
941 MSS_MAC_get_statistics\r
942 (\r
943     mss_mac_statistics_id_t stat_id\r
944 )\r
945 {\r
946     uint32_t returnval = 0u;\r
947 \r
948         switch( stat_id ) {\r
949         case MSS_MAC_RX_INTERRUPTS:\r
950                 returnval = g_mss_mac.statistics.rx_interrupts;\r
951         break;\r
952         case MSS_MAC_RX_FILTERING_FAIL:\r
953                 returnval = g_mss_mac.statistics.rx_filtering_fail;\r
954         break;\r
955         case MSS_MAC_RX_DESCRIPTOR_ERROR:\r
956                 returnval = g_mss_mac.statistics.rx_descriptor_error;\r
957         break;\r
958         case MSS_MAC_RX_RUNT_FRAME:\r
959                 returnval = g_mss_mac.statistics.rx_runt_frame;\r
960         break;\r
961         case MSS_MAC_RX_NOT_FIRST:\r
962                 returnval = g_mss_mac.statistics.rx_not_first;\r
963         break;\r
964         case MSS_MAC_RX_NOT_LAST:\r
965                 returnval = g_mss_mac.statistics.rx_not_last;\r
966         break;\r
967         case MSS_MAC_RX_FRAME_TOO_LONG:\r
968                 returnval = g_mss_mac.statistics.rx_frame_too_long;\r
969         break;\r
970         case MSS_MAC_RX_COLLISION_SEEN:\r
971                 returnval = g_mss_mac.statistics.rx_collision_seen;\r
972         break;\r
973         case MSS_MAC_RX_CRC_ERROR:\r
974                 returnval = g_mss_mac.statistics.rx_crc_error;\r
975         break;\r
976         case MSS_MAC_RX_FIFO_OVERFLOW:\r
977                 returnval = g_mss_mac.statistics.rx_fifo_overflow;\r
978         break;\r
979         case MSS_MAC_RX_MISSED_FRAME:\r
980                 returnval = g_mss_mac.statistics.rx_missed_frame;\r
981         break;\r
982         case MSS_MAC_TX_INTERRUPTS:\r
983                 returnval = g_mss_mac.statistics.tx_interrupts;\r
984         break;\r
985         case MSS_MAC_TX_LOSS_OF_CARRIER:\r
986                 returnval = g_mss_mac.statistics.tx_loss_of_carrier;\r
987         break;\r
988         case MSS_MAC_TX_NO_CARRIER:\r
989                 returnval = g_mss_mac.statistics.tx_no_carrier;\r
990         break;\r
991         case MSS_MAC_TX_LATE_COLLISION:\r
992                 returnval = g_mss_mac.statistics.tx_late_collision;\r
993         break;\r
994         case MSS_MAC_TX_EXCESSIVE_COLLISION:\r
995                 returnval = g_mss_mac.statistics.tx_excessive_collision;\r
996         break;\r
997         case MSS_MAC_TX_COLLISION_COUNT:\r
998                 returnval = g_mss_mac.statistics.tx_collision_count;\r
999         break;\r
1000         case MSS_MAC_TX_UNDERFLOW_ERROR:\r
1001                 returnval = g_mss_mac.statistics.tx_underflow_error;\r
1002         break;\r
1003     default:\r
1004         break;\r
1005         }\r
1006 \r
1007         return returnval;\r
1008 }\r
1009 \r
1010 \r
1011 /**************************** INTERNAL FUNCTIONS ******************************/\r
1012 \r
1013 \r
1014 /***************************************************************************//**\r
1015  * Prepares current rx descriptor for receiving.\r
1016  */\r
1017 void\r
1018 MSS_MAC_prepare_rx_descriptor\r
1019 (\r
1020     void\r
1021 )\r
1022 {\r
1023         uint32_t desc;\r
1024 \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
1029         }\r
1030         if( (desc & RDES0_DE) != 0u ) {\r
1031                 g_mss_mac.statistics.rx_descriptor_error++;\r
1032         }\r
1033         if( (desc & RDES0_RF) != 0u ) {\r
1034                 g_mss_mac.statistics.rx_runt_frame++;\r
1035         }\r
1036         if( (desc & RDES0_FS) == 0u ) {\r
1037                 g_mss_mac.statistics.rx_not_first++;\r
1038         }\r
1039         if( (desc & RDES0_LS) == 0u ) {\r
1040                 g_mss_mac.statistics.rx_not_last++;\r
1041         }\r
1042         if( (desc & RDES0_TL) != 0u ) {\r
1043                 g_mss_mac.statistics.rx_frame_too_long++;\r
1044         }\r
1045         if( (desc & RDES0_CS) != 0u ) {\r
1046                 g_mss_mac.statistics.rx_collision_seen++;\r
1047         }\r
1048         if( (desc & RDES0_CE) != 0u ) {\r
1049                 g_mss_mac.statistics.rx_crc_error++;\r
1050         }\r
1051 \r
1052         desc = MAC->CSR8;\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
1057 \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
1060                 RDES0_OWN;\r
1061         g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;\r
1062 \r
1063         /* Start receive */\r
1064     MAC_start_receiving();\r
1065 }\r
1066 \r
1067 \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
1073  */\r
1074 static int32_t\r
1075 MAC_send_setup_frame\r
1076 (\r
1077     void\r
1078 )\r
1079 {\r
1080         volatile MAC_descriptor_t descriptor;\r
1081         uint8_t frame_data[192];\r
1082         uint8_t *data;\r
1083         int32_t a,b,c,d;\r
1084         int32_t ret;\r
1085 \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
1090 \r
1091         if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {\r
1092                 descriptor.descriptor_1 |= TDES1_FT0;\r
1093         }\r
1094 \r
1095         descriptor.buffer_1 = (uint32_t)frame_data;\r
1096         descriptor.buffer_2 = 0u;\r
1097 \r
1098     /* prepare frame */\r
1099     if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
1100         b = 0;\r
1101         d = 12;\r
1102         c = 90;\r
1103     } else {\r
1104         b = 156;\r
1105         d = 0;\r
1106         c = 64;\r
1107     }\r
1108 \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
1116 \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
1125                 d += 12;\r
1126         }\r
1127 \r
1128         /* Stop transmission */\r
1129     ret = MAC_stop_transmission();\r
1130     configASSERT( ret == MAC_OK );\r
1131 \r
1132     ret = MAC_stop_receiving();\r
1133     configASSERT( ret == MAC_OK );\r
1134 \r
1135     /* Set descriptor */\r
1136     MAC->CSR4 = (uint32_t)&descriptor;\r
1137 \r
1138         /* Start transmission */\r
1139     MAC_start_transmission();\r
1140 \r
1141     /* Wait until transmission over */\r
1142     ret = MAC_OK;\r
1143     MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );\r
1144 \r
1145     while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
1146         CSR5_TS_SUSPENDED) && (MAC_OK == ret) )\r
1147     {\r
1148         /* transmit poll demand */\r
1149         MAC->CSR1 = 1u;\r
1150         if( MAC_get_time_out() == 0u ) {\r
1151                 ret = MAC_TIME_OUT;\r
1152         }\r
1153     }\r
1154 \r
1155         MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );\r
1156 \r
1157     /* Set tx descriptor */\r
1158     MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;\r
1159 \r
1160     /* Start receiving and transmission */\r
1161     MAC_start_receiving();\r
1162     MAC_start_transmission();\r
1163 \r
1164     return ret;\r
1165 }\r
1166 \r
1167 \r
1168 /***************************************************************************//**\r
1169  * Stops transmission.\r
1170  * Function will wait until transmit operation enters stop state.\r
1171  *\r
1172  * @return                      #MAC_OK if everything is ok.\r
1173  *                                      #MAC_TIME_OUT if timed out.\r
1174  */\r
1175 static int32_t\r
1176 MAC_stop_transmission\r
1177 (\r
1178     void\r
1179 )\r
1180 {\r
1181     int32_t retval = MAC_OK;\r
1182     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1183 \r
1184         while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
1185                 CSR5_TS_STOPPED) && (retval == MAC_OK) )\r
1186         {\r
1187         MAC_BITBAND->CSR6_ST = 0u;\r
1188         if( MAC_get_time_out() == 0u ) {\r
1189                 retval = MAC_TIME_OUT;\r
1190         }\r
1191         }\r
1192         return retval;\r
1193 }\r
1194 \r
1195 \r
1196 /***************************************************************************//**\r
1197  * Starts transmission.\r
1198  */\r
1199 static void\r
1200 MAC_start_transmission\r
1201 (\r
1202     void\r
1203 )\r
1204 {\r
1205     MAC_BITBAND->CSR6_ST = 1u;\r
1206 }\r
1207 \r
1208 \r
1209 /***************************************************************************//**\r
1210  * Stops transmission.\r
1211  * Function will wait until transmit operation enters stop state.\r
1212  *\r
1213  * @return                      #MAC_OK if everything is ok.\r
1214  *                                      #MAC_TIME_OUT if timed out.\r
1215  */\r
1216 static int32_t\r
1217 MAC_stop_receiving\r
1218 (\r
1219     void\r
1220 )\r
1221 {\r
1222     int32_t retval = MAC_OK;\r
1223     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1224 \r
1225         while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)\r
1226             && (retval == MAC_OK) )\r
1227         {\r
1228         MAC_BITBAND->CSR6_SR = 0u;\r
1229         if( MAC_get_time_out() == 0u ) {\r
1230                 retval = MAC_TIME_OUT;\r
1231         }\r
1232         }\r
1233 \r
1234         return retval;\r
1235 }\r
1236 \r
1237 \r
1238 /***************************************************************************//**\r
1239  * Starts transmission.\r
1240  */\r
1241 static void\r
1242 MAC_start_receiving\r
1243 (\r
1244     void\r
1245 )\r
1246 {\r
1247     MAC_BITBAND->CSR6_SR = 1u;\r
1248 }\r
1249 \r
1250 \r
1251 /***************************************************************************//**\r
1252  * Dismisses bad frames.\r
1253  *\r
1254  * @return              dismissed frame count.\r
1255  */\r
1256 static int32_t\r
1257 MAC_dismiss_bad_frames\r
1258 (\r
1259     void\r
1260 )\r
1261 {\r
1262         int32_t dc = 0;\r
1263         int8_t cont = 1;\r
1264 \r
1265         if( MAC_BITBAND->CSR6_PB != 0u ) {\r
1266                 /* User wants bad frames too, don't dismiss anything */\r
1267                 cont = 0;\r
1268         }\r
1269 \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
1272     {\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
1276         {\r
1277                 MSS_MAC_prepare_rx_descriptor();\r
1278                 dc++;\r
1279         }\r
1280         else\r
1281         {\r
1282                 cont = 0;\r
1283         }\r
1284     }\r
1285 \r
1286         return dc;\r
1287 }\r
1288 \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
1293  *\r
1294  * @time_out    time out value in milli seconds.\r
1295  *                              Must be smaller than 0x01000000.\r
1296  */\r
1297 static void\r
1298 MAC_set_time_out\r
1299 (\r
1300     uint32_t time_out\r
1301 )\r
1302 {\r
1303         g_mss_mac.time_out_value = (time_out * 122u) / 10u;\r
1304 \r
1305         g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );\r
1306 }\r
1307 \r
1308 /***************************************************************************//**\r
1309  * Returns time out value.\r
1310  *\r
1311  * @return              timer out value in milli seconds.\r
1312  */\r
1313 static uint32_t\r
1314 MAC_get_time_out\r
1315 (\r
1316     void\r
1317 )\r
1318 {\r
1319         uint32_t timer;\r
1320         uint32_t time = 0u;\r
1321 \r
1322         timer = ( MAC->CSR11 & CSR11_TIM_MASK );\r
1323 \r
1324         if( timer > g_mss_mac.last_timer_value ) {\r
1325                 time = 0x0000ffffUL;\r
1326         }\r
1327         time += g_mss_mac.last_timer_value - timer;\r
1328 \r
1329         if( MAC_BITBAND->CSR6_TTM == 0u ) {\r
1330                 time *= 10u;\r
1331         }\r
1332         if( g_mss_mac.time_out_value <= time ){\r
1333                 g_mss_mac.time_out_value = 0u;\r
1334         } else {\r
1335                 g_mss_mac.time_out_value -= time;\r
1336         }\r
1337 \r
1338         g_mss_mac.last_timer_value = (uint16_t)timer;\r
1339 \r
1340         return ((g_mss_mac.time_out_value * 10u) / 122u);\r
1341 }\r
1342 \r
1343 /***************************************************************************//**\r
1344  * Fills the first n bytes of the memory area pointed to by s with the constant\r
1345  * byte c.\r
1346  */\r
1347 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)\r
1348 {\r
1349     uint8_t *sb = s;\r
1350 \r
1351     while( n > 0u ) {\r
1352         n--;\r
1353         sb[n] = c;\r
1354     }\r
1355 }\r
1356 \r
1357 /***************************************************************************//**\r
1358  * Fills all fields of MAC_instance_t with c.\r
1359  *\r
1360  * @return          a pointer to the given MAC_instance_t s.\r
1361  */\r
1362 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)\r
1363 {\r
1364     int32_t count;\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
1375     {\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
1380     }\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
1402     {\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
1407     }\r
1408 }\r
1409 \r
1410 /***************************************************************************//**\r
1411  * Copies n bytes from memory area src to memory area dest.\r
1412  * The memory areas should not overlap.\r
1413  *\r
1414  * @return          a pointer to the memory area dest.\r
1415  */\r
1416 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)\r
1417 {\r
1418     uint8_t *d = dest;\r
1419 \r
1420     while( n > 0u ) {\r
1421         n--;\r
1422         d[n] = src[n];\r
1423     }\r
1424 }\r
1425 \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
1430  *\r
1431  */\r
1432 void MSS_MAC_CheckTxBufferStatus( void )\r
1433 {\r
1434 unsigned char *pxTransmittedBuffer;\r
1435 long lDescriptor, lIndex;\r
1436 \r
1437         for( lDescriptor = 1; lDescriptor < TX_RING_SIZE; lDescriptor++ )\r
1438         {\r
1439                 if( ( g_mss_mac.tx_descriptors[ lDescriptor ].descriptor_0 & TDES0_OWN ) == 0UL )\r
1440                 {\r
1441                         pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1;\r
1442 \r
1443                         for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
1444                         {\r
1445                                 if( pxTransmittedBuffer == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )\r
1446                                 {\r
1447                                         ucMACBufferInUse[ lIndex ] = pdFALSE;\r
1448                                 }\r
1449                         }                       \r
1450                 }\r
1451         }\r
1452 }\r
1453 \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
1458  *\r
1459  * @return          a pointer to a free buffer.\r
1460  */\r
1461 unsigned char *MAC_obtain_buffer( void )\r
1462 {\r
1463 long lIndex;\r
1464 unsigned char *pcReturn = NULL;\r
1465 \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
1469         {\r
1470                 if( ucMACBufferInUse[ lIndex ] == pdFALSE )\r
1471                 {\r
1472                         pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
1473                         ucMACBufferInUse[ lIndex ] = pdTRUE;\r
1474                         break;\r
1475                 }\r
1476         }\r
1477         \r
1478         configASSERT( pcReturn );\r
1479         return pcReturn;\r
1480 }\r
1481 \r
1482 /***************************************************************************//**\r
1483  * Return a buffer to the list of free buffers, it was in use, but is not now.\r
1484  *\r
1485  */\r
1486 void MAC_release_buffer( unsigned char *pucBufferToRelease )\r
1487 {\r
1488 long lIndex;\r
1489 \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
1493         {\r
1494                 if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )\r
1495                 {\r
1496                         /* This is the buffer in use, mark it as being free. */\r
1497                         ucMACBufferInUse[ lIndex ] = pdFALSE;\r
1498                         break;\r
1499                 }\r
1500         }\r
1501         \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
1505         \r
1506         configASSERT( lIndex < macNUM_BUFFERS );\r
1507 }\r
1508 \r
1509 \r
1510 \r
1511 #ifdef __cplusplus\r
1512 }\r
1513 #endif\r
1514 \r
1515 /******************************** END OF FILE *********************************/\r
1516 \r