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