]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
daebab325ba352f1ea9a69226cbc00bf01541d19
[freertos] / Demo / CORTEX_A2F200_SoftConsole / 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 #ifdef __cplusplus\r
13 extern "C" {\r
14 #endif \r
15 \r
16 \r
17 #include "crc32.h"\r
18 \r
19 #include "mss_ethernet_mac.h"\r
20 #include "mss_ethernet_mac_regs.h"\r
21 #include "mss_ethernet_mac_desc.h"\r
22 #include "mss_ethernet_mac_conf.h"\r
23 #include "../../CMSIS/mss_assert.h"\r
24 \r
25 #include "phy.h"\r
26 \r
27 /**************************** INTERNAL DEFINES ********************************/\r
28 \r
29 #define MAC_CHECK(CHECK,ERRNO)  \\r
30         {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); ASSERT((CHECK));}}\r
31 \r
32 /*\r
33  * Flags\r
34  */\r
35 #define FLAG_MAC_INIT_DONE              1u\r
36 #define FLAG_PERFECT_FILTERING  2u\r
37 #define FLAG_CRC_DISABLE                4u\r
38 #define FLAG_EXCEED_LIMIT               8u\r
39 \r
40 /*\r
41  * Return types\r
42  */\r
43 #define MAC_OK                    0\r
44 #define MAC_FAIL                  (-1)\r
45 #define MAC_WRONG_PARAMETER       (-2)\r
46 #define MAC_TOO_BIG_PACKET        (-3)\r
47 #define MAC_BUFFER_IS_FULL        (-4)\r
48 #define MAC_NOT_ENOUGH_SPACE      (-5)\r
49 #define MAC_TIME_OUT                      (-6)\r
50 #define MAC_TOO_SMALL_PACKET      (-7)\r
51 \r
52 /***************************************************************/\r
53 MAC_instance_t g_mss_mac;\r
54 \r
55 /**************************** INTERNAL DATA ***********************************/\r
56 #define ERROR_MESSAGE_COUNT             8\r
57 #define MAX_ERROR_MESSAGE_WIDTH 40\r
58 static const int8_t unknown_error[] = "Unknown error";\r
59 static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {\r
60         "No error occured",\r
61         "Method failed",\r
62         "Wrong parameter pased to function",\r
63         "Frame is too long",\r
64         "Not enough space in buffer",\r
65         "Not enough space in buffer",\r
66         "Timed out",\r
67         "Frame is too small"\r
68 };\r
69 \r
70 /*\r
71  * Null variables\r
72  */\r
73 static MAC_instance_t*  NULL_instance;\r
74 static uint8_t*                 NULL_buffer;\r
75 static MSS_MAC_callback_t       NULL_callback;\r
76 \r
77 /**************************** INTERNAL FUNCTIONS ******************************/\r
78 \r
79 static int32_t  MAC_test_instance( void );\r
80 \r
81 static int32_t  MAC_dismiss_bad_frames( void );\r
82 static int32_t  MAC_send_setup_frame( void );\r
83 \r
84 static int32_t  MAC_stop_transmission( void );\r
85 static void             MAC_start_transmission( void );\r
86 static int32_t  MAC_stop_receiving( void );\r
87 static void             MAC_start_receiving( void );\r
88 \r
89 static void             MAC_set_time_out( uint32_t time_out );\r
90 static uint32_t MAC_get_time_out( void );\r
91 \r
92 static void     MAC_memset(uint8_t *s, uint8_t c, uint32_t n);\r
93 static void     MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);\r
94 static void     MAC_memset_All(MAC_instance_t *s, uint32_t c);\r
95 \r
96 /***************************************************************************//**\r
97  * Initializes the Ethernet Controller.\r
98  * This function will prepare the Ethernet Controller for first time use in a\r
99  * given hardware/software configuration. This function should be called before\r
100  * any other Ethernet API functions are called.\r
101  *\r
102  * Initialization of registers - config registers, enable Tx/Rx interrupts,\r
103  * enable Tx/Rx, initialize MAC addr, init PHY, autonegotiation, MAC address\r
104  * filter table (unicats/multicast)/hash init\r
105  */\r
106 void\r
107 MSS_MAC_init\r
108 (\r
109         uint8_t phy_address\r
110 )\r
111 {\r
112     const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };\r
113 \r
114     int32_t a;\r
115 \r
116     /* Try to reset chip */\r
117     MAC_BITBAND->CSR0_SWR = 1u;\r
118     \r
119     while ( 1u == MAC_BITBAND->CSR0_SWR )\r
120     {\r
121         ;\r
122     }\r
123 \r
124     /* Check reset values of some registers to constrol\r
125      * base address validity */\r
126     ASSERT( MAC->CSR0 == 0xFE000000uL );\r
127     ASSERT( MAC->CSR5 == 0xF0000000uL );\r
128     ASSERT( MAC->CSR6 == 0x32000040uL );\r
129 \r
130     /* Instance setup */\r
131     MAC_memset_All( &g_mss_mac, 0u );\r
132 \r
133     g_mss_mac.base_address = MAC_BASE;\r
134     g_mss_mac.phy_address = phy_address;\r
135 \r
136     for( a=0; a<RX_RING_SIZE; a++ )\r
137     {\r
138         /* Give the ownership to the MAC */\r
139         g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;\r
140         g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);\r
141         g_mss_mac.rx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.rx_buffers[a];\r
142     }\r
143     g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;\r
144 \r
145     for( a = 0; a < TX_RING_SIZE; a++ )\r
146     {\r
147         g_mss_mac.tx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.tx_buffers[a];\r
148     }\r
149     g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;\r
150 \r
151     /* Configurable settings */\r
152     MAC_BITBAND->CSR0_DBO = DESCRIPTOR_BYTE_ORDERING_MODE;\r
153     MAC->CSR0 = (MAC->CSR0 & ~CSR0_PBL_MASK) | ((uint32_t)PROGRAMMABLE_BURST_LENGTH << CSR0_PBL_SHIFT);\r
154     MAC_BITBAND->CSR0_BLE = BUFFER_BYTE_ORDERING_MODE;\r
155     MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;\r
156 \r
157     /* Fixed settings */\r
158     /* No automatic polling */\r
159     MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;\r
160     /* No space between descriptors */\r
161     MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;\r
162     /* General-purpose timer works in continuous mode */\r
163     MAC_BITBAND->CSR11_CON = 1u;\r
164     /* Start general-purpose */\r
165     MAC->CSR11 =  (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);\r
166 \r
167     /* Disable promiscuous mode */\r
168     MAC_BITBAND->CSR6_PR = 0u;\r
169 \r
170     /* Enable store and forward */\r
171     MAC_BITBAND->CSR6_SF = 1u;\r
172 \r
173     /* Set descriptors */\r
174     MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);\r
175     MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);\r
176     \r
177         /* enable normal interrupts */\r
178     MAC_BITBAND->CSR7_NIE = 1u;\r
179 \r
180     /* Detect PHY */\r
181     if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )\r
182     {\r
183         PHY_probe();\r
184         ASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );\r
185     }\r
186 \r
187     /* Reset PHY */\r
188     PHY_reset();\r
189 \r
190         /* Set flags */\r
191     g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;\r
192 \r
193         /* Configure chip according to PHY status */\r
194     MSS_MAC_auto_setup_link();\r
195 \r
196     /* Set default MAC address and reset mac filters */\r
197         MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );\r
198         MSS_MAC_set_mac_filters( 0u, NULL_buffer );\r
199 \r
200 \r
201     /* Start receiving and transmission */\r
202     MAC_start_receiving();\r
203     MAC_start_transmission();\r
204 }\r
205 \r
206 \r
207 /***************************************************************************//**\r
208  * Sets the configuration of the Ethernet Controller.\r
209  * After the EthernetInit function has been called, this API function can be\r
210  * used to configure the various features of the Ethernet Controller.\r
211  *\r
212  * @param instance      Pointer to a MAC_instance_t structure\r
213  * @param config        The logical OR of the following values:\r
214  *    - #MSS_MAC_CFG_RECEIVE_ALL\r
215  *    - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE\r
216  *    - #MSS_MSS_MAC_CFG_STORE_AND_FORWARD\r
217  *    - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]\r
218  *    - #MSS_MAC_CFG_FULL_DUPLEX_MODE\r
219  *    - #MSS_MAC_CFG_PASS_ALL_MULTICAST\r
220  *    - #MSS_MAC_CFG_PROMISCUOUS_MODE\r
221  *    - #MSS_MAC_CFG_PASS_BAD_FRAMES\r
222  * @see   MAC_get_configuration()\r
223  */\r
224 void\r
225 MSS_MAC_configure\r
226 (\r
227     uint32_t configuration\r
228 )\r
229 {\r
230     int32_t ret;\r
231 \r
232     ASSERT( MAC_test_instance() == MAC_OK );\r
233 \r
234     ret = MAC_stop_transmission();\r
235     ASSERT( ret == MAC_OK );\r
236 \r
237     ret = MAC_stop_receiving();\r
238     ASSERT( ret == MAC_OK );\r
239 \r
240     MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );\r
241     MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );\r
242     MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );\r
243     \r
244     switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {\r
245     case MSS_MAC_CFG_THRESHOLD_CONTROL_00:\r
246         MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;\r
247         break;\r
248     case MSS_MAC_CFG_THRESHOLD_CONTROL_01:\r
249         MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)1 << CSR6_TR_SHIFT );\r
250         break;\r
251     case MSS_MAC_CFG_THRESHOLD_CONTROL_10:\r
252         MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)2 << CSR6_TR_SHIFT );\r
253         break;\r
254     case MSS_MAC_CFG_THRESHOLD_CONTROL_11:\r
255         MAC->CSR6 = (MAC->CSR6 & ~CSR6_TR_MASK) | ((uint32_t)3 << CSR6_TR_SHIFT );\r
256         break;\r
257     default:\r
258         break;\r
259     }\r
260     MAC_BITBAND->CSR6_FD = (uint32_t)(((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? 1u : 0u );\r
261     MAC_BITBAND->CSR6_PM = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_ALL_MULTICAST) != 0u) ? 1u : 0u );\r
262     MAC_BITBAND->CSR6_PR = (uint32_t)(((configuration & MSS_MAC_CFG_PROMISCUOUS_MODE) != 0u) ? 1u : 0u );\r
263     MAC_BITBAND->CSR6_PB = (uint32_t)(((configuration & MSS_MAC_CFG_PASS_BAD_FRAMES) != 0u) ? 1u : 0u );\r
264     PHY_set_link_type( (uint8_t)\r
265         ((((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? MSS_MAC_LINK_STATUS_100MB : 0u ) |\r
266         (((configuration & MSS_MAC_CFG_FULL_DUPLEX_MODE) != 0u) ? MSS_MAC_LINK_STATUS_FDX : 0u )) );\r
267 \r
268     MAC_start_transmission();\r
269     MAC_start_receiving();\r
270 \r
271     MSS_MAC_auto_setup_link();\r
272 }\r
273 \r
274 \r
275 /***************************************************************************//**\r
276  * Returns the configuration of the Ethernet Controller.\r
277  *\r
278  * @param instance      Pointer to a MAC_instance_t structure\r
279  * @return              The logical OR of the following values:\r
280  *    - #MSS_MAC_CFG_RECEIVE_ALL\r
281  *    - #MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE\r
282  *    - #MSS_MAC_CFG_STORE_AND_FORWARD\r
283  *    - #MAC_CFG_THRESHOLD_CONTROL_[00,01,10,11]\r
284  *    - #MSS_MAC_CFG_FULL_DUPLEX_MODE\r
285  *    - #MSS_MAC_CFG_PASS_ALL_MULTICAST\r
286  *    - #MSS_MAC_CFG_PROMISCUOUS_MODE\r
287  *    - #MSS_MAC_CFG_INVERSE_FILTERING\r
288  *    - #MSS_MAC_CFG_PASS_BAD_FRAMES\r
289  *    - #MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE\r
290  *    - #MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE\r
291  * @see   MAC_configure()\r
292  */\r
293 int32_t\r
294 MSS_MAC_get_configuration( void )\r
295 {\r
296     uint32_t configuration;\r
297 \r
298     ASSERT( MAC_test_instance() == MAC_OK );\r
299 \r
300     configuration = 0u;\r
301     if( MAC_BITBAND->CSR6_RA != 0u ) {\r
302         configuration |= MSS_MAC_CFG_RECEIVE_ALL;\r
303     }\r
304 \r
305     if( MAC_BITBAND->CSR6_TTM != 0u ) {\r
306         configuration |= MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE;\r
307     }\r
308 \r
309     if( MAC_BITBAND->CSR6_SF != 0u ) {\r
310         configuration |= MSS_MAC_CFG_STORE_AND_FORWARD;\r
311     }\r
312 \r
313     switch( (MAC->CSR6 & CSR6_TR_MASK) >> CSR6_TR_SHIFT ) {\r
314     case 1: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_01; break;\r
315     case 2: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_10; break;\r
316     case 3: configuration |= MSS_MAC_CFG_THRESHOLD_CONTROL_11; break;\r
317     default: break;\r
318     }\r
319     if( MAC_BITBAND->CSR6_FD != 0u ) {\r
320         configuration |= MSS_MAC_CFG_FULL_DUPLEX_MODE;\r
321     }\r
322 \r
323     if( MAC_BITBAND->CSR6_PM != 0u ) {\r
324         configuration |= MSS_MAC_CFG_PASS_ALL_MULTICAST;\r
325     }\r
326 \r
327     if( MAC_BITBAND->CSR6_PR != 0u ) {\r
328         configuration |= MSS_MAC_CFG_PROMISCUOUS_MODE;\r
329     }\r
330 \r
331     if( MAC_BITBAND->CSR6_IF != 0u ) {\r
332         configuration |= MSS_MAC_CFG_INVERSE_FILTERING;\r
333     }\r
334 \r
335     if( MAC_BITBAND->CSR6_PB != 0u ) {\r
336         configuration |= MSS_MAC_CFG_PASS_BAD_FRAMES;\r
337     }\r
338 \r
339     if( MAC_BITBAND->CSR6_HO != 0u ) {\r
340         configuration |= MSS_MAC_CFG_HASH_ONLY_FILTERING_MODE;\r
341     }\r
342 \r
343     if( MAC_BITBAND->CSR6_HP != 0u ) {\r
344         configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;\r
345     }\r
346     \r
347     return (int32_t)configuration;\r
348 }\r
349 \r
350 \r
351 /***************************************************************************//**\r
352   Sends a packet to the Ethernet Controller.\r
353   The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet\r
354   MAC. This function writes pacLen bytes of the packet contained in pacData into\r
355   the transmit FIFO and then activates the transmitter for this packet. If space\r
356   is available in the FIFO, the function will return once pacLen bytes of the\r
357   packet have been placed into the FIFO and the transmitter has been started.\r
358   This function will not wait for the transmission to complete. If space is not\r
359   available in FIFO, the function will keep trying until time_out expires. The\r
360   function will wait for the transmission to complete when the time_out parameter\r
361   is set to MSS_MAC_BLOCKING.\r
362  \r
363   @param pacData\r
364     The pacData parameter is a pointer to the packet data to be transmitted.\r
365     \r
366   @param pacLen\r
367     The pacLen parameter is the number of bytes in the packet to be transmitted.\r
368     \r
369   @param time_out\r
370     The time_out parameter is the timeout value for the transmission in milliseconds.\r
371     The time_out parameter value can be one of the following values:\r
372     \95 Unsigned integer greater than 0 and less than 0x01000000\r
373     \95 MSS_MAC_BLOCKING \96 there will be no timeout. \r
374     \95 MSS_MAC_NONBLOCKING \96 the function will return immediately if the MSS Ethernet\r
375       MAC does not have any available transmit descriptor. This would happen when\r
376       several packets are already queued into the MSS Ethernet MAC transmit descriptor FIFO.\r
377 \r
378   @return\r
379     The function returns zero if a timeout occurs otherwise it returns size of the packet.\r
380     \r
381   @see   MAC_rx_packet()\r
382  */\r
383 \r
384 int32_t\r
385 MSS_MAC_tx_packet\r
386 (\r
387     const uint8_t *pacData,\r
388     uint16_t pacLen,\r
389     uint32_t time_out\r
390 )\r
391 {\r
392         uint32_t desc;\r
393     int32_t error = MAC_OK;\r
394 \r
395     ASSERT( MAC_test_instance() == MAC_OK );\r
396 \r
397     ASSERT( pacData != NULL_buffer );\r
398 \r
399         ASSERT( pacLen >= 12 );\r
400 \r
401     if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )\r
402     {\r
403                 ASSERT( pacLen <= MSS_MAX_PACKET_SIZE );\r
404         }\r
405 \r
406     ASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
407                         (time_out == MSS_MAC_NONBLOCKING) ||\r
408                         ((time_out >= 1) && (time_out <= 0x01000000uL)) );\r
409 \r
410     if( time_out == MSS_MAC_NONBLOCKING )\r
411     {\r
412         /* Check if current descriptor is free */\r
413         if(((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )\r
414         {\r
415                         error = MAC_BUFFER_IS_FULL;\r
416         }\r
417     }\r
418     else\r
419         {\r
420             /* Wait until descriptor is free */\r
421             if( time_out != MSS_MAC_BLOCKING ) {\r
422             MAC_set_time_out( time_out );\r
423             }\r
424         \r
425         while( (((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )\r
426                 && (error == MAC_OK) )\r
427             {\r
428                      /* transmit poll demand */\r
429             MAC->CSR1 = 1u;\r
430             \r
431                 if(time_out != MSS_MAC_BLOCKING){\r
432                         if(MAC_get_time_out() == 0u) {\r
433                                 error = MAC_TIME_OUT;\r
434                         }\r
435                 }\r
436             }\r
437         }\r
438 \r
439         if( error == MAC_OK ) {\r
440 \r
441                 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
442 \r
443                 if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
444                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |=     TDES1_AC;\r
445                 }\r
446 \r
447         /* Every buffer can hold a full frame so they are always first and last\r
448            descriptor */\r
449         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;\r
450 \r
451         /* set data size */\r
452         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= pacLen;\r
453 \r
454         /* reset end of ring */\r
455         g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
456 \r
457         /* copy data into buffer */\r
458         if( pacLen > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
459         {\r
460                 pacLen = (uint16_t)MSS_TX_BUFF_SIZE;\r
461         }\r
462         MAC_memcpy(\r
463                 (uint8_t*)\r
464                 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1,\r
465                 pacData, (uint32_t)pacLen );\r
466 \r
467         /* update counters */\r
468         desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;\r
469         if( (desc & TDES0_LO) != 0u ) {\r
470                 g_mss_mac.statistics.tx_loss_of_carrier++;\r
471         }\r
472         if( (desc & TDES0_NC) != 0u ) {\r
473                 g_mss_mac.statistics.tx_no_carrier++;\r
474         }\r
475         if( (desc & TDES0_LC) != 0u ) {\r
476                 g_mss_mac.statistics.tx_late_collision++;\r
477         }\r
478         if( (desc & TDES0_EC) != 0u ) {\r
479                 g_mss_mac.statistics.tx_excessive_collision++;\r
480         }\r
481         if( (desc & TDES0_UF) != 0u ) {\r
482                 g_mss_mac.statistics.tx_underflow_error++;\r
483         }\r
484         g_mss_mac.statistics.tx_collision_count +=\r
485                 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
486 \r
487         /* Give ownership of descriptor to the MAC */\r
488         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;\r
489 \r
490         g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
491 \r
492         /* Start transmission */\r
493         MAC_start_transmission();\r
494 \r
495         /* transmit poll demand */\r
496         MAC->CSR1 = 1u;\r
497     }\r
498     \r
499     if (error == MAC_OK)\r
500     {\r
501         error = (int32_t)pacLen;\r
502     }\r
503     else\r
504     {\r
505         error = 0;\r
506     }\r
507     return ( error );\r
508 }\r
509 \r
510 \r
511 /***************************************************************************//**\r
512  * Returns available packet size.\r
513  *\r
514  * @param instance      Pointer to a MAC_instance_t structure\r
515  * @return              size of packet, bigger than 0, if a packet is available.\r
516  *                      If not, returns 0.\r
517  * @see   MAC_rx_packet()\r
518  */\r
519 int32_t\r
520 MSS_MAC_rx_pckt_size\r
521 (\r
522     void\r
523 )\r
524 {\r
525     int32_t retval;\r
526     ASSERT( MAC_test_instance() == MAC_OK );\r
527 \r
528     MAC_dismiss_bad_frames();\r
529 \r
530     if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &     RDES0_OWN) != 0u )\r
531     {\r
532         /* Current descriptor is empty */\r
533         retval = 0;\r
534     }\r
535     else\r
536     {\r
537         uint32_t frame_length;\r
538         frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;\r
539         retval = (int32_t)( frame_length );\r
540     }\r
541     return retval;\r
542 }\r
543 \r
544 \r
545 /***************************************************************************//**\r
546  * Receives a packet from the Ethernet Controller.\r
547  * This function reads a packet from the receive FIFO of the controller and\r
548  * places it into pacData. If time_out parameter is zero the function will return\r
549  * immediately (after the copy operation if data is available. Otherwise the function\r
550  * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING\r
551  * value is given as time_out, function will wait for the reception to complete.\r
552  *\r
553  * @param instance      Pointer to a MAC_instance_t structure\r
554  * @param pacData       The pointer to the packet data.\r
555  * @param pacLen        The pacLen parameter is the size in bytes of the pacData\r
556  *                      buffer where the received data will be copied.\r
557  * @param time_out      Time out value in milli seconds for receiving.\r
558  *                                          if value is #MSS_MAC_BLOCKING, there will be no time out.\r
559  *                                          if value is #MSS_MAC_NONBLOCKING, function will return immediately\r
560  *                                          if there is no packet waiting.\r
561  *                                          Otherwise value must be greater than 0 and smaller than\r
562  *                                          0x01000000.\r
563  * @return              Size of packet if packet fits in pacData.\r
564  *                                          0 if there is no received packet.\r
565  * @see   MAC_rx_pckt_size()\r
566  * @see   MAC_tx_packet()\r
567  */\r
568 int32_t\r
569 MSS_MAC_rx_packet\r
570 (\r
571     uint8_t *pacData,\r
572     uint16_t pacLen,\r
573     uint32_t time_out\r
574 )\r
575 {\r
576         uint16_t frame_length=0u;\r
577     int8_t exit=0;\r
578 \r
579     ASSERT( MAC_test_instance() == MAC_OK );\r
580 \r
581     ASSERT( pacData != NULL_buffer );\r
582 \r
583     ASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
584                         (time_out == MSS_MAC_NONBLOCKING) ||\r
585                         ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
586 \r
587     MAC_dismiss_bad_frames();\r
588 \r
589     /* wait for a packet */\r
590         if( time_out != MSS_MAC_BLOCKING ) {\r
591                 if( time_out == MSS_MAC_NONBLOCKING ) {\r
592                 MAC_set_time_out( 0u );\r
593                 } else {\r
594                 MAC_set_time_out( time_out );\r
595                 }\r
596         }\r
597 \r
598     while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
599         RDES0_OWN) != 0u) && (exit == 0) )\r
600     {\r
601         if( time_out != MSS_MAC_BLOCKING )\r
602         {\r
603                 if( MAC_get_time_out() == 0u ) {\r
604                         exit = 1;\r
605                 }\r
606         }\r
607     }\r
608 \r
609     if(exit == 0)\r
610     {\r
611         frame_length = ( (\r
612             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
613             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
614 \r
615         /* strip crc */\r
616         frame_length -= 4u;\r
617 \r
618         if( frame_length > pacLen ) {\r
619                 return MAC_NOT_ENOUGH_SPACE;\r
620         }\r
621        \r
622         MAC_memcpy( pacData,\r
623                 (uint8_t*)\r
624                 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1,\r
625                 (uint32_t)frame_length );\r
626 \r
627         MSS_MAC_prepare_rx_descriptor();\r
628        \r
629     }\r
630     return ((int32_t)frame_length);\r
631 }\r
632 \r
633 \r
634 /***************************************************************************//**\r
635  * Receives a packet from the Ethernet Controller.\r
636  * This function reads a packet from the receive FIFO of the controller and\r
637  * sets the address of pacData to the received data. \r
638  * If time_out parameter is zero the function will return\r
639  * immediately (after the copy operation if data is available. Otherwise the function\r
640  * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING\r
641  * value is given as time_out, function will wait for the reception to complete.\r
642  *\r
643  * @param instance      Pointer to a MAC_instance_t structure\r
644  * @param pacData       The pointer to the packet data.\r
645  * @param time_out      Time out value in milli seconds for receiving.\r
646  *                                          if value is #MSS_MAC_BLOCKING, there will be no time out.\r
647  *                                          if value is #MSS_MAC_NONBLOCKING, function will return immediately\r
648  *                                          if there is no packet waiting.\r
649  *                                          Otherwise value must be greater than 0 and smaller than\r
650  *                                          0x01000000.\r
651  * @return              Size of packet if packet fits in pacData.\r
652  *                                          0 if there is no received packet.\r
653  * @see   MAC_rx_pckt_size()\r
654  * @see   MAC_tx_packet()\r
655  */\r
656 int32_t\r
657 MSS_MAC_rx_packet_ptrset\r
658 (\r
659     uint8_t **pacData,\r
660     uint32_t time_out\r
661 )\r
662 {\r
663         uint16_t frame_length = 0u;\r
664     int8_t exit = 0;\r
665 \r
666     ASSERT( MAC_test_instance() == MAC_OK );\r
667 \r
668     ASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
669                         (time_out == MSS_MAC_NONBLOCKING) ||\r
670                         ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
671 \r
672     MAC_dismiss_bad_frames();\r
673 \r
674     /* wait for a packet */\r
675         if( time_out != MSS_MAC_BLOCKING ) {\r
676                 if( time_out == MSS_MAC_NONBLOCKING ) {\r
677                 MAC_set_time_out( 0u );\r
678                 } else {\r
679                 MAC_set_time_out( time_out );\r
680                 }\r
681         }\r
682 \r
683     while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
684         RDES0_OWN) != 0u) && (exit == 0) )\r
685     {\r
686         if( time_out != MSS_MAC_BLOCKING )\r
687         {\r
688                 if( MAC_get_time_out() == 0u ) {\r
689                         exit = 1;\r
690                 }\r
691         }\r
692     }\r
693 \r
694     if(exit == 0)\r
695     {\r
696         frame_length = ( (\r
697             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
698             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
699 \r
700         /* strip crc */\r
701         frame_length -= 4u;\r
702 \r
703        /* Here we are setting the buffer 'pacData' address to the address\r
704           RX descriptor address. After this is called, the following function\r
705           must be called 'MAC_prepare_rx_descriptor' \r
706           to prepare the current rx descriptor for receiving the next packet.\r
707        */       \r
708         *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;         \r
709         \r
710     }\r
711     return ((int32_t)frame_length);\r
712 }\r
713 \r
714 /***************************************************************************//**\r
715  * Returns the status of connection.\r
716  *\r
717  * @return              the logical OR of the following values:\r
718  *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
719  *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
720  *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
721  * @see   MAC_auto_setup_link()\r
722  */\r
723 int32_t\r
724 MSS_MAC_link_status\r
725 (\r
726     void\r
727 )\r
728 {\r
729         uint32_t link;\r
730 \r
731     ASSERT( MAC_test_instance() == MAC_OK );\r
732 \r
733     link = PHY_link_status();\r
734     if( link == MSS_MAC_LINK_STATUS_LINK ) {\r
735         link |= PHY_link_type();\r
736     }\r
737 \r
738     return ((int32_t)link);\r
739 }\r
740 \r
741 \r
742 /***************************************************************************//**\r
743  * Setups the link between PHY and MAC and returns the status of connection.\r
744  *\r
745  * @return              the logical OR of the following values:\r
746  *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
747  *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
748  *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
749  * @see   MAC_link_status()\r
750  */\r
751 int32_t\r
752 MSS_MAC_auto_setup_link\r
753 (\r
754     void\r
755 )\r
756 {\r
757         int32_t link;\r
758     ASSERT( MAC_test_instance() == MAC_OK );\r
759 \r
760     PHY_auto_negotiate();\r
761 \r
762     link = MSS_MAC_link_status();\r
763 \r
764     if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {\r
765         int32_t ret;\r
766             ret = MAC_stop_transmission();\r
767             MAC_CHECK( ret == MAC_OK, ret );\r
768 \r
769             ret = MAC_stop_receiving();\r
770             MAC_CHECK( ret == MAC_OK, ret );\r
771         MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );\r
772         MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );\r
773             MAC_start_transmission();\r
774             MAC_start_receiving();\r
775     }\r
776 \r
777     return link;\r
778 }\r
779 \r
780 \r
781 /***************************************************************************//**\r
782  * Sets mac address. New address must be unicast.\r
783  *\r
784  * @param new_address   Pointer to a MAC_instance_t structure\r
785  * @see   MAC_get_mac_address()\r
786  */\r
787 void\r
788 MSS_MAC_set_mac_address\r
789 (\r
790     const uint8_t *new_address\r
791 )\r
792 {\r
793     ASSERT( MAC_test_instance() == MAC_OK );\r
794     /* Check if the new address is unicast */\r
795     ASSERT( (new_address[0]&1) == 0 );\r
796 \r
797         MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );\r
798 \r
799         if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
800                 int32_t a;\r
801                 /* set unused filters to the new mac address */\r
802                 for( a=14*6; a>=0; a-=6 ) {\r
803                         if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {\r
804                                 /* Filters with multicast addresses are used */\r
805                                 a = -1;\r
806                         } else {\r
807                                 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),\r
808                                         g_mss_mac.mac_address, 6u );\r
809                         }\r
810                 }\r
811         }\r
812 \r
813         MAC_send_setup_frame();\r
814 }\r
815 \r
816 \r
817 /***************************************************************************//**\r
818  * Returns mac address.\r
819  *\r
820  * @param address       Pointer to receive the MAC address\r
821  * @see   MAC_set_mac_address()\r
822  */\r
823 void\r
824 MSS_MAC_get_mac_address\r
825 (\r
826     uint8_t *address\r
827 )\r
828 {\r
829     ASSERT( MAC_test_instance() == MAC_OK );\r
830 \r
831         MAC_memcpy( address, g_mss_mac.mac_address, 6u );\r
832 }\r
833 \r
834 \r
835 /***************************************************************************//**\r
836  * Sets mac address filters. Addresses must be multicast.\r
837  *\r
838  * @param filter_count  number of addresses\r
839  * @param filters       Pointer to addresses to be filtered\r
840  */\r
841 void\r
842 MSS_MAC_set_mac_filters\r
843 (\r
844         uint16_t filter_count,\r
845         const uint8_t *filters\r
846 )\r
847 {\r
848     ASSERT( MAC_test_instance() == MAC_OK );\r
849     ASSERT( (filter_count==0) || (filters != NULL_buffer) );\r
850     /* Check if the mac addresses is multicast */\r
851     {\r
852         int32_t a;\r
853         for( a = 0u; a < filter_count; a++ ) {\r
854                 ASSERT( (filters[a*6]&1) == 1 );\r
855         }\r
856     }\r
857 \r
858     if( filter_count <= 15 ){\r
859         int32_t a;\r
860         g_mss_mac.flags |= FLAG_PERFECT_FILTERING;\r
861 \r
862         /* copy new filters */\r
863         MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));\r
864 \r
865         /* set unused filters to our mac address */\r
866         for( a=filter_count; a<15; a++ ) {\r
867                         MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),\r
868                                 g_mss_mac.mac_address, 6 );\r
869         }\r
870     } else {\r
871         int32_t a,b;\r
872         uint32_t hash;\r
873 \r
874         g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;\r
875 \r
876         /* reset hash table */\r
877         MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );\r
878 \r
879         for( a=0, b=0; a<filter_count; a++, b+=6 ) {\r
880                 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;\r
881                 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);\r
882         }\r
883     }\r
884 \r
885     MAC_send_setup_frame();\r
886 }\r
887 \r
888 \r
889 /***************************************************************************//**\r
890  * MAC interrupt service routine.\r
891  *\r
892  * @param instance      Pointer to a MAC_instance_t structure\r
893  * @see   MAC_set_callback()\r
894  */\r
895 #if defined(__GNUC__)\r
896 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )\r
897 #else\r
898 void EthernetMAC_IRQHandler( void )\r
899 #endif\r
900 {\r
901     uint32_t events;\r
902     uint32_t intr_status;\r
903 \r
904     ASSERT( MAC_test_instance() == MAC_OK );\r
905 \r
906     events = 0u;\r
907     intr_status = MAC->CSR5;\r
908 \r
909     if( (intr_status & CSR5_NIS_MASK) != 0u ) {\r
910         if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */\r
911                 g_mss_mac.statistics.tx_interrupts++;\r
912                 events |= MSS_MAC_EVENT_PACKET_SEND;\r
913         }\r
914 \r
915         if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */\r
916                 g_mss_mac.statistics.rx_interrupts++;\r
917                 events |= MSS_MAC_EVENT_PACKET_RECEIVED;\r
918         }\r
919     }\r
920 \r
921     /* Clear interrupts */\r
922     MAC->CSR5 = CSR5_INT_BITS;\r
923     \r
924     if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {\r
925         g_mss_mac.listener( events );\r
926     }\r
927 }\r
928 \r
929 \r
930 /***************************************************************************//**\r
931  * Sets MAC event listener.\r
932  * Sets the given event listener function to be triggered inside MAC_isr().\r
933  * Assigning NULL pointer as the listener function will disable it.\r
934  *\r
935  * @param instance      Pointer to a MAC_instance_t structure\r
936  * @param listener      function pointer to a MAC_callback_t function\r
937  * @return              #MAC_OK if everything is OK\r
938  *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
939  *                                              initialized.\r
940  * @see   MAC_isr()\r
941  */\r
942 void\r
943 MSS_MAC_set_callback\r
944 (\r
945     MSS_MAC_callback_t listener\r
946 )\r
947 {\r
948     ASSERT( MAC_test_instance() == MAC_OK );\r
949 \r
950         /* disable tx and rx interrupts */\r
951     MAC_BITBAND->CSR7_RIE = 0u;\r
952     MAC_BITBAND->CSR7_TIE = 0u;\r
953     \r
954     g_mss_mac.listener = listener;\r
955 \r
956         if( listener != NULL_callback ) {\r
957                 /* enable tx and rx interrupts */\r
958         MAC_BITBAND->CSR7_RIE = 1u;\r
959         MAC_BITBAND->CSR7_TIE = 1u;\r
960         }\r
961 }\r
962 \r
963 \r
964 /***************************************************************************//**\r
965  * Returns description of last error.\r
966  *\r
967  * @param instance      Pointer to a MAC_instance_t structure\r
968  * @return              A string describing the error. This string must not be\r
969  *                                              modified by the application.\r
970  *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
971  *                      initialized.\r
972  */\r
973 const int8_t*\r
974 MSS_MAC_last_error\r
975 (\r
976     void\r
977 )\r
978 {\r
979         int8_t error_msg_nb;\r
980     const int8_t* returnvalue;\r
981     \r
982     ASSERT( MAC_test_instance() == MAC_OK );\r
983 \r
984         error_msg_nb = -(g_mss_mac.last_error);\r
985         if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {\r
986                 returnvalue = unknown_error;\r
987         } else {\r
988                 returnvalue = ErrorMessages[error_msg_nb];\r
989         }\r
990         return returnvalue;\r
991 }\r
992 \r
993 \r
994 /***************************************************************************//**\r
995  * Returns statistics counter of stat_id identifier.\r
996  *\r
997  * @param instance      Pointer to a MAC_instance_t structure\r
998  * @param stat_id               Identifier of statistics counter.\r
999  * @return                              Statistics counter of stat_id identifier.\r
1000  *                                              On error returns 0.\r
1001  */\r
1002 uint32_t\r
1003 MSS_MAC_get_statistics\r
1004 (\r
1005     mss_mac_statistics_id_t stat_id\r
1006 )\r
1007 {\r
1008     uint32_t returnval = 0u;\r
1009     ASSERT( MAC_test_instance() == MAC_OK );\r
1010 \r
1011         switch( stat_id ) {\r
1012         case MSS_MAC_RX_INTERRUPTS:\r
1013                 returnval = g_mss_mac.statistics.rx_interrupts;\r
1014         break;\r
1015         case MSS_MAC_RX_FILTERING_FAIL:\r
1016                 returnval = g_mss_mac.statistics.rx_filtering_fail;\r
1017         break;\r
1018         case MSS_MAC_RX_DESCRIPTOR_ERROR:\r
1019                 returnval = g_mss_mac.statistics.rx_descriptor_error;\r
1020         break;\r
1021         case MSS_MAC_RX_RUNT_FRAME:\r
1022                 returnval = g_mss_mac.statistics.rx_runt_frame;\r
1023         break;\r
1024         case MSS_MAC_RX_NOT_FIRST:\r
1025                 returnval = g_mss_mac.statistics.rx_not_first;\r
1026         break;\r
1027         case MSS_MAC_RX_NOT_LAST:\r
1028                 returnval = g_mss_mac.statistics.rx_not_last;\r
1029         break;\r
1030         case MSS_MAC_RX_FRAME_TOO_LONG:\r
1031                 returnval = g_mss_mac.statistics.rx_frame_too_long;\r
1032         break;\r
1033         case MSS_MAC_RX_COLLISION_SEEN:\r
1034                 returnval = g_mss_mac.statistics.rx_collision_seen;\r
1035         break;\r
1036         case MSS_MAC_RX_CRC_ERROR:\r
1037                 returnval = g_mss_mac.statistics.rx_crc_error;\r
1038         break;\r
1039         case MSS_MAC_RX_FIFO_OVERFLOW:\r
1040                 returnval = g_mss_mac.statistics.rx_fifo_overflow;\r
1041         break;\r
1042         case MSS_MAC_RX_MISSED_FRAME:\r
1043                 returnval = g_mss_mac.statistics.rx_missed_frame;\r
1044         break;\r
1045         case MSS_MAC_TX_INTERRUPTS:\r
1046                 returnval = g_mss_mac.statistics.tx_interrupts;\r
1047         break;\r
1048         case MSS_MAC_TX_LOSS_OF_CARRIER:\r
1049                 returnval = g_mss_mac.statistics.tx_loss_of_carrier;\r
1050         break;\r
1051         case MSS_MAC_TX_NO_CARRIER:\r
1052                 returnval = g_mss_mac.statistics.tx_no_carrier;\r
1053         break;\r
1054         case MSS_MAC_TX_LATE_COLLISION:\r
1055                 returnval = g_mss_mac.statistics.tx_late_collision;\r
1056         break;\r
1057         case MSS_MAC_TX_EXCESSIVE_COLLISION:\r
1058                 returnval = g_mss_mac.statistics.tx_excessive_collision;\r
1059         break;\r
1060         case MSS_MAC_TX_COLLISION_COUNT:\r
1061                 returnval = g_mss_mac.statistics.tx_collision_count;\r
1062         break;\r
1063         case MSS_MAC_TX_UNDERFLOW_ERROR:\r
1064                 returnval = g_mss_mac.statistics.tx_underflow_error;\r
1065         break;\r
1066     default:\r
1067         break;\r
1068         }\r
1069 \r
1070         return returnval;\r
1071 }\r
1072 \r
1073 \r
1074 /**************************** INTERNAL FUNCTIONS ******************************/\r
1075 \r
1076 /***************************************************************************//**\r
1077  * Checks if instace is valid.\r
1078  */\r
1079 static int32_t\r
1080 MAC_test_instance\r
1081 (\r
1082     void\r
1083 )\r
1084 {\r
1085     uint32_t val1;\r
1086     uint32_t val2;\r
1087     int32_t retval = MAC_WRONG_PARAMETER;\r
1088 \r
1089     val1 = MAC->CSR3;\r
1090     val2 = MAC->CSR4;\r
1091 \r
1092     if( (&g_mss_mac != NULL_instance) &&\r
1093         ((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&\r
1094         ( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&\r
1095         (val2 == (uint32_t)g_mss_mac.tx_descriptors ) )\r
1096     {\r
1097         retval = MAC_OK;\r
1098     }\r
1099     return retval;\r
1100 }\r
1101 \r
1102 /***************************************************************************//**\r
1103  * Prepares current rx descriptor for receiving.\r
1104  */\r
1105 void\r
1106 MSS_MAC_prepare_rx_descriptor\r
1107 (\r
1108     void\r
1109 )\r
1110 {\r
1111         uint32_t desc;\r
1112 \r
1113         /* update counters */\r
1114         desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;\r
1115         if( (desc & RDES0_FF) != 0u ) {\r
1116                 g_mss_mac.statistics.rx_filtering_fail++;\r
1117         }\r
1118         if( (desc & RDES0_DE) != 0u ) {\r
1119                 g_mss_mac.statistics.rx_descriptor_error++;\r
1120         }\r
1121         if( (desc & RDES0_RF) != 0u ) {\r
1122                 g_mss_mac.statistics.rx_runt_frame++;\r
1123         }\r
1124         if( (desc & RDES0_FS) == 0u ) {\r
1125                 g_mss_mac.statistics.rx_not_first++;\r
1126         }\r
1127         if( (desc & RDES0_LS) == 0u ) {\r
1128                 g_mss_mac.statistics.rx_not_last++;\r
1129         }\r
1130         if( (desc & RDES0_TL) != 0u ) {\r
1131                 g_mss_mac.statistics.rx_frame_too_long++;\r
1132         }\r
1133         if( (desc & RDES0_CS) != 0u ) {\r
1134                 g_mss_mac.statistics.rx_collision_seen++;\r
1135         }\r
1136         if( (desc & RDES0_CE) != 0u ) {\r
1137                 g_mss_mac.statistics.rx_crc_error++;\r
1138         }\r
1139     \r
1140         desc = MAC->CSR8;\r
1141         g_mss_mac.statistics.rx_fifo_overflow +=\r
1142                 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;\r
1143         g_mss_mac.statistics.rx_missed_frame +=\r
1144                 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));\r
1145 \r
1146         /* Give ownership of descriptor to the MAC */\r
1147         g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =\r
1148                 RDES0_OWN;\r
1149         g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;\r
1150 \r
1151         /* Start receive */\r
1152     MAC_start_receiving();\r
1153 }\r
1154 \r
1155 \r
1156 /***************************************************************************//**\r
1157  * Prepares a setup frame and sends it to MAC.\r
1158  * This function is blocking.\r
1159  * @return              #MAC_OK if everything is ok.\r
1160  *                              #MAC_TIME_OUT if timed out before packet send.\r
1161  */\r
1162 static int32_t\r
1163 MAC_send_setup_frame\r
1164 (\r
1165     void\r
1166 )\r
1167 {\r
1168         volatile MAC_descriptor_t descriptor;\r
1169         uint8_t frame_data[192];\r
1170         uint8_t *data;\r
1171         int32_t a,b,c,d;\r
1172         int32_t ret;\r
1173 \r
1174     /* prepare descriptor */\r
1175         descriptor.descriptor_0 = TDES0_OWN;\r
1176         descriptor.descriptor_1 = TDES1_SET | TDES1_TER |\r
1177                 (sizeof(frame_data) << TDES1_TBS1_OFFSET);\r
1178 \r
1179         if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {\r
1180                 descriptor.descriptor_1 |= TDES1_FT0;\r
1181         }\r
1182 \r
1183         descriptor.buffer_1 = (uint32_t)frame_data;\r
1184         descriptor.buffer_2 = 0u;\r
1185 \r
1186     /* prepare frame */\r
1187     if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
1188         b = 0;\r
1189         d = 12;\r
1190         c = 90;\r
1191     } else {\r
1192         b = 156;\r
1193         d = 0;\r
1194         c = 64;\r
1195     }\r
1196 \r
1197         data = g_mss_mac.mac_address;\r
1198         frame_data[b] = data[0];\r
1199         frame_data[b+1] = data[1];\r
1200         frame_data[b+4] = data[2];\r
1201         frame_data[b+5] = data[3];\r
1202         frame_data[b+8] = data[4];\r
1203         frame_data[b+9] = data[5];\r
1204 \r
1205         data = g_mss_mac.mac_filter_data;\r
1206     for( a = 0; a < c; ) {\r
1207                 frame_data[d] = data[a++];\r
1208                 frame_data[d+1] = data[a++];\r
1209                 frame_data[d+4] = data[a++];\r
1210                 frame_data[d+5] = data[a++];\r
1211                 frame_data[d+8] = data[a++];\r
1212                 frame_data[d+9] = data[a++];\r
1213                 d += 12;\r
1214         }\r
1215 \r
1216         /* Stop transmission */\r
1217     ret = MAC_stop_transmission();\r
1218     ASSERT( ret == MAC_OK );\r
1219 \r
1220     ret = MAC_stop_receiving();\r
1221     ASSERT( ret == MAC_OK );\r
1222 \r
1223     /* Set descriptor */\r
1224     MAC->CSR4 = (uint32_t)&descriptor;\r
1225     \r
1226         /* Start transmission */\r
1227     MAC_start_transmission();\r
1228 \r
1229     /* Wait until transmission over */\r
1230     ret = MAC_OK;\r
1231     MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );\r
1232     \r
1233     while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) != \r
1234         CSR5_TS_SUSPENDED) && (MAC_OK == ret) )\r
1235     {\r
1236         /* transmit poll demand */\r
1237         MAC->CSR1 = 1u;\r
1238         if( MAC_get_time_out() == 0u ) {\r
1239                 ret = MAC_TIME_OUT;\r
1240         }\r
1241     }\r
1242 \r
1243         MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );\r
1244 \r
1245     /* Set tx descriptor */\r
1246     MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;\r
1247     \r
1248     /* Start receiving and transmission */\r
1249     MAC_start_receiving();\r
1250     MAC_start_transmission();\r
1251 \r
1252     return ret;\r
1253 }\r
1254 \r
1255 \r
1256 /***************************************************************************//**\r
1257  * Stops transmission.\r
1258  * Function will wait until transmit operation enters stop state.\r
1259  *\r
1260  * @return                      #MAC_OK if everything is ok.\r
1261  *                                      #MAC_TIME_OUT if timed out.\r
1262  */\r
1263 static int32_t\r
1264 MAC_stop_transmission\r
1265 (\r
1266     void\r
1267 )\r
1268 {\r
1269     int32_t retval = MAC_OK;\r
1270     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1271     \r
1272         while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
1273                 CSR5_TS_STOPPED) && (retval == MAC_OK) )\r
1274         {\r
1275         MAC_BITBAND->CSR6_ST = 0u;\r
1276         if( MAC_get_time_out() == 0u ) {\r
1277                 retval = MAC_TIME_OUT;\r
1278         }\r
1279         }\r
1280         return retval;\r
1281 }\r
1282 \r
1283 \r
1284 /***************************************************************************//**\r
1285  * Starts transmission.\r
1286  */\r
1287 static void\r
1288 MAC_start_transmission\r
1289 (\r
1290     void\r
1291 )\r
1292 {\r
1293     MAC_BITBAND->CSR6_ST = 1u;\r
1294 }\r
1295 \r
1296 \r
1297 /***************************************************************************//**\r
1298  * Stops transmission.\r
1299  * Function will wait until transmit operation enters stop state.\r
1300  *\r
1301  * @return                      #MAC_OK if everything is ok.\r
1302  *                                      #MAC_TIME_OUT if timed out.\r
1303  */\r
1304 static int32_t\r
1305 MAC_stop_receiving\r
1306 (\r
1307     void\r
1308 )\r
1309 {\r
1310     int32_t retval = MAC_OK;\r
1311     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1312 \r
1313         while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)\r
1314             && (retval == MAC_OK) )\r
1315         {\r
1316         MAC_BITBAND->CSR6_SR = 0u;\r
1317         if( MAC_get_time_out() == 0u ) {\r
1318                 retval = MAC_TIME_OUT;\r
1319         }\r
1320         }\r
1321 \r
1322         return retval;\r
1323 }\r
1324 \r
1325 \r
1326 /***************************************************************************//**\r
1327  * Starts transmission.\r
1328  */\r
1329 static void\r
1330 MAC_start_receiving\r
1331 (\r
1332     void\r
1333 )\r
1334 {\r
1335     MAC_BITBAND->CSR6_SR = 1u;\r
1336 }\r
1337 \r
1338 \r
1339 /***************************************************************************//**\r
1340  * Dismisses bad frames.\r
1341  *\r
1342  * @return              dismissed frame count.\r
1343  */\r
1344 static int32_t\r
1345 MAC_dismiss_bad_frames\r
1346 (\r
1347     void\r
1348 )\r
1349 {\r
1350         int32_t dc = 0;\r
1351         int8_t cont = 1;\r
1352     \r
1353         if( MAC_BITBAND->CSR6_PB != 0u ) {\r
1354                 /* User wants bad frames too, don't dismiss anything */\r
1355                 cont = 0;\r
1356         }\r
1357 \r
1358         while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
1359             RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */\r
1360     {\r
1361         /* check error summary */\r
1362         if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
1363                 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )\r
1364         {\r
1365                 MSS_MAC_prepare_rx_descriptor();\r
1366                 dc++;\r
1367         }\r
1368         else\r
1369         {\r
1370                 cont = 0;\r
1371         }\r
1372     }\r
1373 \r
1374         return dc;\r
1375 }\r
1376 \r
1377 /***************************************************************************//**\r
1378  * Sets time out value.\r
1379  * #MAC_get_time_out must be called frequently to make time out value updated.\r
1380  * Because of user may not be using ISR, we can not update time out in ISR.\r
1381  *\r
1382  * @time_out    time out value in milli seconds.\r
1383  *                              Must be smaller than 0x01000000.\r
1384  */\r
1385 static void\r
1386 MAC_set_time_out\r
1387 (\r
1388     uint32_t time_out\r
1389 )\r
1390 {\r
1391         g_mss_mac.time_out_value = (time_out * 122u) / 10u;\r
1392 \r
1393         g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );\r
1394 }\r
1395 \r
1396 /***************************************************************************//**\r
1397  * Returns time out value.\r
1398  *\r
1399  * @return              timer out value in milli seconds.\r
1400  */\r
1401 static uint32_t\r
1402 MAC_get_time_out\r
1403 (\r
1404     void\r
1405 )\r
1406 {\r
1407         uint32_t timer;\r
1408         uint32_t time = 0u;\r
1409     \r
1410         timer = ( MAC->CSR11 & CSR11_TIM_MASK );\r
1411     \r
1412         if( timer > g_mss_mac.last_timer_value ) {\r
1413                 time = 0x0000ffffUL;\r
1414         }\r
1415         time += g_mss_mac.last_timer_value - timer;\r
1416     \r
1417         if( MAC_BITBAND->CSR6_TTM == 0u ) {\r
1418                 time *= 10u;\r
1419         }\r
1420         if( g_mss_mac.time_out_value <= time ){\r
1421                 g_mss_mac.time_out_value = 0u;\r
1422         } else {\r
1423                 g_mss_mac.time_out_value -= time;\r
1424         }\r
1425 \r
1426         g_mss_mac.last_timer_value = (uint16_t)timer;\r
1427 \r
1428         return ((g_mss_mac.time_out_value * 10u) / 122u);\r
1429 }\r
1430 \r
1431 /***************************************************************************//**\r
1432  * Fills the first n bytes of the memory area pointed to by s with the constant\r
1433  * byte c.\r
1434  */\r
1435 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)\r
1436 {\r
1437     uint8_t *sb = s;\r
1438 \r
1439     while( n > 0u ) {\r
1440         n--;\r
1441         sb[n] = c;\r
1442     }\r
1443 }\r
1444 \r
1445 /***************************************************************************//**\r
1446  * Fills all fields of MAC_instance_t with c.\r
1447  *\r
1448  * @return          a pointer to the given MAC_instance_t s.\r
1449  */\r
1450 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)\r
1451 {\r
1452     int32_t count;\r
1453     s->base_address = (addr_t)c;\r
1454     s->flags = (uint8_t)c;\r
1455     s->last_error = (int8_t)c;\r
1456     s->last_timer_value = (uint16_t)c;\r
1457     s->listener = NULL_callback;\r
1458         MAC_memset( s->mac_address, (uint8_t)c, 6u );\r
1459         MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );\r
1460     s->phy_address = (uint8_t)c;\r
1461     for(count = 0; count<RX_RING_SIZE ;count++)\r
1462     {\r
1463         MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );\r
1464     }\r
1465     s->rx_desc_index =c;\r
1466     for(count = 0; count<RX_RING_SIZE ;count++)\r
1467     {\r
1468         s->rx_descriptors[count].buffer_1 = c;\r
1469         s->rx_descriptors[count].buffer_2 = c;\r
1470         s->rx_descriptors[count].descriptor_0 = c;\r
1471         s->rx_descriptors[count].descriptor_1 = c;\r
1472     }\r
1473     s->statistics.rx_collision_seen =c;\r
1474     s->statistics.rx_crc_error = c;\r
1475     s->statistics.rx_descriptor_error = c;\r
1476     s->statistics.rx_fifo_overflow = c;\r
1477     s->statistics.rx_filtering_fail = c;\r
1478     s->statistics.rx_frame_too_long = c;\r
1479     s->statistics.rx_interrupts = c;\r
1480     s->statistics.rx_missed_frame = c;\r
1481     s->statistics.rx_not_first = c;\r
1482     s->statistics.rx_not_last = c;\r
1483     s->statistics.rx_runt_frame = c;\r
1484     s->statistics.tx_collision_count = c;\r
1485     s->statistics.tx_excessive_collision = c;\r
1486     s->statistics.tx_interrupts = c;\r
1487     s->statistics.tx_late_collision = c;\r
1488     s->statistics.tx_loss_of_carrier = c;\r
1489     s->statistics.tx_no_carrier = c;\r
1490     s->statistics.tx_underflow_error = c;\r
1491     s->time_out_value = c;\r
1492     for(count = 0; count < TX_RING_SIZE ;count++)\r
1493     {\r
1494         MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );\r
1495     }\r
1496     s->tx_desc_index = c;\r
1497     for(count = 0; count < TX_RING_SIZE ;count++)\r
1498     {\r
1499         s->tx_descriptors[count].buffer_1 = c;\r
1500         s->tx_descriptors[count].buffer_2 = c;\r
1501         s->tx_descriptors[count].descriptor_0 = c;\r
1502         s->tx_descriptors[count].descriptor_1 = c;\r
1503     }\r
1504 }\r
1505 \r
1506 /***************************************************************************//**\r
1507  * Copies n bytes from memory area src to memory area dest.\r
1508  * The memory areas should not overlap.\r
1509  *\r
1510  * @return          a pointer to the memory area dest.\r
1511  */\r
1512 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)\r
1513 {\r
1514     uint8_t *d = dest;\r
1515 \r
1516     while( n > 0u ) {\r
1517         n--;\r
1518         d[n] = src[n];\r
1519     }\r
1520 }\r
1521 \r
1522 #ifdef __cplusplus\r
1523 }\r
1524 #endif\r
1525 \r
1526 /******************************** END OF FILE *********************************/\r
1527 \r