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