]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
891cb888c812d742e5603d5b1dcef6c6cf863b94
[freertos] / Demo / CORTEX_A2F200_IAR_and_Keil / MicroSemi_Code / drivers / mss_ethernet_mac / mss_ethernet_mac.c
1 /***************************************************************************//**\r
2  * @file\r
3  * SmartFusion MSS Ethernet MAC driver implementation.\r
4  *\r
5  * (c) Copyright 2007 Actel Corporation\r
6  *\r
7  * SVN $Revision: 2369 $\r
8  * SVN $Date: 2010-03-01 18:31:45 +0000 (Mon, 01 Mar 2010) $\r
9  *\r
10  ******************************************************************************/\r
11 \r
12 /*\r
13  *\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 + 1\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         /* Check if second descriptor is free, if it is then the first must\r
424         also be free. */\r
425         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
426         {\r
427                 error = MAC_BUFFER_IS_FULL;\r
428         }\r
429 \r
430         \r
431         if( error == MAC_OK )\r
432         {\r
433                 /* Assumed TX_RING_SIZE == 2.  A #error directive checks this is the\r
434                 case. */\r
435                 for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
436                 {\r
437                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
438 \r
439                         if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
440                                 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;\r
441                         }\r
442 \r
443                         /* Every buffer can hold a full frame so they are always first and last\r
444                            descriptor */\r
445                 g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;\r
446 \r
447                         /* set data size */\r
448                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;\r
449 \r
450                         /* reset end of ring */\r
451                         g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
452 \r
453                         if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
454                         {\r
455                                 usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
456                         }\r
457 \r
458                         /* The data buffer is assigned to the Tx descriptor. */\r
459                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;\r
460 \r
461                         /* update counters */\r
462                         desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;\r
463                         if( (desc & TDES0_LO) != 0u ) {\r
464                                 g_mss_mac.statistics.tx_loss_of_carrier++;\r
465                         }\r
466                         if( (desc & TDES0_NC) != 0u ) {\r
467                                 g_mss_mac.statistics.tx_no_carrier++;\r
468                         }\r
469                         if( (desc & TDES0_LC) != 0u ) {\r
470                                 g_mss_mac.statistics.tx_late_collision++;\r
471                         }\r
472                         if( (desc & TDES0_EC) != 0u ) {\r
473                                 g_mss_mac.statistics.tx_excessive_collision++;\r
474                         }\r
475                         if( (desc & TDES0_UF) != 0u ) {\r
476                                 g_mss_mac.statistics.tx_underflow_error++;\r
477                         }\r
478                         g_mss_mac.statistics.tx_collision_count +=\r
479                                 (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
480 \r
481                         /* Give ownership of descriptor to the MAC */\r
482                         g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;\r
483                         \r
484                         g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
485                         \r
486                         MAC_start_transmission();\r
487                         MAC->CSR1 = 1u;\r
488                 }               \r
489     }\r
490         \r
491     if (error == MAC_OK)\r
492     {\r
493         error = (int32_t)usLength;\r
494                 \r
495                 /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.\r
496                 Find anothere free buffer for uip_buf. */\r
497                 uip_buf = MAC_obtain_buffer();\r
498     }\r
499     else\r
500     {\r
501         error = 0;\r
502     }\r
503     return ( error );\r
504 }\r
505 \r
506 \r
507 /***************************************************************************//**\r
508  * Returns available packet size.\r
509  *\r
510  * @param instance      Pointer to a MAC_instance_t structure\r
511  * @return              size of packet, bigger than 0, if a packet is available.\r
512  *                      If not, returns 0.\r
513  * @see   MAC_rx_packet()\r
514  */\r
515 int32_t\r
516 MSS_MAC_rx_pckt_size\r
517 (\r
518     void\r
519 )\r
520 {\r
521     int32_t retval;\r
522     MAC_dismiss_bad_frames();\r
523 \r
524     if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &     RDES0_OWN) != 0u )\r
525     {\r
526         /* Current descriptor is empty */\r
527         retval = 0;\r
528     }\r
529     else\r
530     {\r
531         uint32_t frame_length;\r
532         frame_length = ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> RDES0_FL_OFFSET ) & RDES0_FL_MASK;\r
533         retval = (int32_t)( frame_length );\r
534     }\r
535     return retval;\r
536 }\r
537 \r
538 \r
539 /***************************************************************************//**\r
540  * Receives a packet from the Ethernet Controller into the uIP stack.\r
541  * This function reads a packet from the receive FIFO of the controller and\r
542  * places it into uip_buf.\r
543 \r
544  * @return              Size of packet if packet fits in uip_buf.\r
545  *                                          0 if there is no received packet.\r
546  * @see   MAC_rx_pckt_size()\r
547  * @see   MAC_tx_packet()\r
548  */\r
549 int32_t\r
550 MSS_MAC_rx_packet\r
551 (\r
552         void\r
553 )\r
554 {\r
555         uint16_t frame_length=0u;\r
556 \r
557     MAC_dismiss_bad_frames();\r
558 \r
559     if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )\r
560     {\r
561         frame_length = ( (\r
562             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
563             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
564 \r
565         /* strip crc */\r
566         frame_length -= 4u;\r
567 \r
568         if( frame_length > macBUFFER_SIZE ) {\r
569                 return MAC_NOT_ENOUGH_SPACE;\r
570         }\r
571 \r
572                 /* uip_buf is about to point to the buffer that contains the received\r
573                 data, mark the buffer that uip_buf is currently pointing to as free\r
574                 again. */\r
575                 MAC_release_buffer( uip_buf );\r
576         uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;\r
577                 \r
578                 /* The buffer the Rx descriptor was pointing to is now in use by the\r
579                 uIP stack - allocate a new buffer to the Rx descriptor. */\r
580                 g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();\r
581 \r
582         MSS_MAC_prepare_rx_descriptor();\r
583     }\r
584     return ((int32_t)frame_length);\r
585 }\r
586 \r
587 \r
588 /***************************************************************************//**\r
589  * Receives a packet from the Ethernet Controller.\r
590  * This function reads a packet from the receive FIFO of the controller and\r
591  * sets the address of pacData to the received data.\r
592  * If time_out parameter is zero the function will return\r
593  * immediately (after the copy operation if data is available. Otherwise the function\r
594  * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING\r
595  * value is given as time_out, function will wait for the reception to complete.\r
596  *\r
597  * @param instance      Pointer to a MAC_instance_t structure\r
598  * @param pacData       The pointer to the packet data.\r
599  * @param time_out      Time out value in milli seconds for receiving.\r
600  *                                          if value is #MSS_MAC_BLOCKING, there will be no time out.\r
601  *                                          if value is #MSS_MAC_NONBLOCKING, function will return immediately\r
602  *                                          if there is no packet waiting.\r
603  *                                          Otherwise value must be greater than 0 and smaller than\r
604  *                                          0x01000000.\r
605  * @return              Size of packet if packet fits in pacData.\r
606  *                                          0 if there is no received packet.\r
607  * @see   MAC_rx_pckt_size()\r
608  * @see   MAC_tx_packet()\r
609  */\r
610 int32_t\r
611 MSS_MAC_rx_packet_ptrset\r
612 (\r
613     uint8_t **pacData,\r
614     uint32_t time_out\r
615 )\r
616 {\r
617         uint16_t frame_length = 0u;\r
618     int8_t exit = 0;\r
619 \r
620     configASSERT(  (time_out == MSS_MAC_BLOCKING) ||\r
621                         (time_out == MSS_MAC_NONBLOCKING) ||\r
622                         ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
623 \r
624     MAC_dismiss_bad_frames();\r
625 \r
626     /* wait for a packet */\r
627         if( time_out != MSS_MAC_BLOCKING ) {\r
628                 if( time_out == MSS_MAC_NONBLOCKING ) {\r
629                 MAC_set_time_out( 0u );\r
630                 } else {\r
631                 MAC_set_time_out( time_out );\r
632                 }\r
633         }\r
634 \r
635     while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
636         RDES0_OWN) != 0u) && (exit == 0) )\r
637     {\r
638         if( time_out != MSS_MAC_BLOCKING )\r
639         {\r
640                 if( MAC_get_time_out() == 0u ) {\r
641                         exit = 1;\r
642                 }\r
643         }\r
644     }\r
645 \r
646     if(exit == 0)\r
647     {\r
648         frame_length = ( (\r
649             g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
650             RDES0_FL_OFFSET ) & RDES0_FL_MASK );\r
651 \r
652         /* strip crc */\r
653         frame_length -= 4u;\r
654 \r
655        /* Here we are setting the buffer 'pacData' address to the address\r
656           RX descriptor address. After this is called, the following function\r
657           must be called 'MAC_prepare_rx_descriptor'\r
658           to prepare the current rx descriptor for receiving the next packet.\r
659        */\r
660         *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;\r
661 \r
662     }\r
663     return ((int32_t)frame_length);\r
664 }\r
665 \r
666 /***************************************************************************//**\r
667  * Returns the status of connection.\r
668  *\r
669  * @return              the logical OR of the following values:\r
670  *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
671  *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
672  *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
673  * @see   MAC_auto_setup_link()\r
674  */\r
675 int32_t\r
676 MSS_MAC_link_status\r
677 (\r
678     void\r
679 )\r
680 {\r
681         uint32_t link;\r
682 \r
683     link = PHY_link_status();\r
684     if( link == MSS_MAC_LINK_STATUS_LINK ) {\r
685         link |= PHY_link_type();\r
686     }\r
687 \r
688     return ((int32_t)link);\r
689 }\r
690 \r
691 \r
692 /***************************************************************************//**\r
693  * Setups the link between PHY and MAC and returns the status of connection.\r
694  *\r
695  * @return              the logical OR of the following values:\r
696  *      #MSS_MAC_LINK_STATUS_LINK    - Link up/down\r
697  *      #MSS_MAC_LINK_STATUS_100MB   - Connection is 100Mb/10Mb\r
698  *      #MSS_MAC_LINK_STATUS_FDX     - Connection is full/half duplex\r
699  * @see   MAC_link_status()\r
700  */\r
701 int32_t\r
702 MSS_MAC_auto_setup_link\r
703 (\r
704     void\r
705 )\r
706 {\r
707         int32_t link;\r
708 \r
709     PHY_auto_negotiate();\r
710 \r
711     link = MSS_MAC_link_status();\r
712 \r
713     if( (link & MSS_MAC_LINK_STATUS_LINK) != 0u ) {\r
714         int32_t ret;\r
715             ret = MAC_stop_transmission();\r
716             MAC_CHECK( ret == MAC_OK, ret );\r
717 \r
718             ret = MAC_stop_receiving();\r
719             MAC_CHECK( ret == MAC_OK, ret );\r
720         MAC_BITBAND->CSR6_TTM = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_100MB) != 0u) ? 1u : 0u );\r
721         MAC_BITBAND->CSR6_FD = (uint32_t)((((uint32_t)link & MSS_MAC_LINK_STATUS_FDX) != 0u) ? 1u : 1u );\r
722             MAC_start_transmission();\r
723             MAC_start_receiving();\r
724     }\r
725 \r
726     return link;\r
727 }\r
728 \r
729 \r
730 /***************************************************************************//**\r
731  * Sets mac address. New address must be unicast.\r
732  *\r
733  * @param new_address   Pointer to a MAC_instance_t structure\r
734  * @see   MAC_get_mac_address()\r
735  */\r
736 void\r
737 MSS_MAC_set_mac_address\r
738 (\r
739     const uint8_t *new_address\r
740 )\r
741 {\r
742     /* Check if the new address is unicast */\r
743     configASSERT( (new_address[0]&1) == 0 );\r
744 \r
745         MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );\r
746 \r
747         if((g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
748                 int32_t a;\r
749                 /* set unused filters to the new mac address */\r
750                 for( a=14*6; a>=0; a-=6 ) {\r
751                         if( (g_mss_mac.mac_filter_data[a] & 1u) != 0u ) {\r
752                                 /* Filters with multicast addresses are used */\r
753                                 a = -1;\r
754                         } else {\r
755                                 MAC_memcpy( &(g_mss_mac.mac_filter_data[a]),\r
756                                         g_mss_mac.mac_address, 6u );\r
757                         }\r
758                 }\r
759         }\r
760 \r
761         MAC_send_setup_frame();\r
762 }\r
763 \r
764 \r
765 /***************************************************************************//**\r
766  * Returns mac address.\r
767  *\r
768  * @param address       Pointer to receive the MAC address\r
769  * @see   MAC_set_mac_address()\r
770  */\r
771 void\r
772 MSS_MAC_get_mac_address\r
773 (\r
774     uint8_t *address\r
775 )\r
776 {\r
777         MAC_memcpy( address, g_mss_mac.mac_address, 6u );\r
778 }\r
779 \r
780 \r
781 /***************************************************************************//**\r
782  * Sets mac address filters. Addresses must be multicast.\r
783  *\r
784  * @param filter_count  number of addresses\r
785  * @param filters       Pointer to addresses to be filtered\r
786  */\r
787 void\r
788 MSS_MAC_set_mac_filters\r
789 (\r
790         uint16_t filter_count,\r
791         const uint8_t *filters\r
792 )\r
793 {\r
794     configASSERT( (filter_count==0) || (filters != NULL_buffer) );\r
795     /* Check if the mac addresses is multicast */\r
796     {\r
797         int32_t a;\r
798         for( a = 0u; a < filter_count; a++ ) {\r
799                 configASSERT( (filters[a*6]&1) == 1 );\r
800         }\r
801     }\r
802 \r
803     if( filter_count <= 15 ){\r
804         int32_t a;\r
805         g_mss_mac.flags |= FLAG_PERFECT_FILTERING;\r
806 \r
807         /* copy new filters */\r
808         MAC_memcpy( g_mss_mac.mac_filter_data, filters, (uint32_t)(filter_count*6));\r
809 \r
810         /* set unused filters to our mac address */\r
811         for( a=filter_count; a<15; a++ ) {\r
812                         MAC_memcpy( &(g_mss_mac.mac_filter_data[a*6]),\r
813                                 g_mss_mac.mac_address, 6 );\r
814         }\r
815     } else {\r
816         int32_t a,b;\r
817         uint32_t hash;\r
818 \r
819         g_mss_mac.flags &= ~FLAG_PERFECT_FILTERING;\r
820 \r
821         /* reset hash table */\r
822         MAC_memset( g_mss_mac.mac_filter_data, 0u, 64u );\r
823 \r
824         for( a=0, b=0; a<filter_count; a++, b+=6 ) {\r
825                 hash = mss_ethernet_crc( &(filters[b]), 6 ) & 0x1FF;\r
826                 g_mss_mac.mac_filter_data[ hash / 8 ] |= 1 << (hash & 0x7);\r
827         }\r
828     }\r
829 \r
830     MAC_send_setup_frame();\r
831 }\r
832 \r
833 \r
834 /***************************************************************************//**\r
835  * MAC interrupt service routine.\r
836  *\r
837  * @param instance      Pointer to a MAC_instance_t structure\r
838  * @see   MAC_set_callback()\r
839  */\r
840 #if defined(__GNUC__)\r
841 __attribute__((__interrupt__)) void EthernetMAC_IRQHandler( void )\r
842 #else\r
843 void EthernetMAC_IRQHandler( void )\r
844 #endif\r
845 {\r
846     uint32_t events;\r
847     uint32_t intr_status;\r
848 \r
849     events = 0u;\r
850     intr_status = MAC->CSR5;\r
851 \r
852     if( (intr_status & CSR5_NIS_MASK) != 0u ) {\r
853         if( (intr_status & CSR5_TI_MASK) != 0u ) { /* Transmit */\r
854                 g_mss_mac.statistics.tx_interrupts++;\r
855                 events |= MSS_MAC_EVENT_PACKET_SEND;\r
856         }\r
857 \r
858         if( (intr_status & CSR5_RI_MASK) != 0u ) { /* Receive */\r
859                 g_mss_mac.statistics.rx_interrupts++;\r
860                 events |= MSS_MAC_EVENT_PACKET_RECEIVED;\r
861         }\r
862     }\r
863 \r
864     /* Clear interrupts */\r
865     MAC->CSR5 = CSR5_INT_BITS;\r
866 \r
867     if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {\r
868         g_mss_mac.listener( events );\r
869     }\r
870 }\r
871 \r
872 \r
873 /***************************************************************************//**\r
874  * Sets MAC event listener.\r
875  * Sets the given event listener function to be triggered inside MAC_isr().\r
876  * Assigning NULL pointer as the listener function will disable it.\r
877  *\r
878  * @param instance      Pointer to a MAC_instance_t structure\r
879  * @param listener      function pointer to a MAC_callback_t function\r
880  * @return              #MAC_OK if everything is OK\r
881  *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
882  *                                              initialized.\r
883  * @see   MAC_isr()\r
884  */\r
885 void\r
886 MSS_MAC_set_callback\r
887 (\r
888     MSS_MAC_callback_t listener\r
889 )\r
890 {\r
891         /* disable tx and rx interrupts */\r
892     MAC_BITBAND->CSR7_RIE = 0u;\r
893     MAC_BITBAND->CSR7_TIE = 0u;\r
894 \r
895     g_mss_mac.listener = listener;\r
896 \r
897         if( listener != NULL_callback ) {\r
898                 /* enable tx and rx interrupts */\r
899         MAC_BITBAND->CSR7_RIE = 1u;\r
900         MAC_BITBAND->CSR7_TIE = 1u;\r
901         }\r
902 }\r
903 \r
904 \r
905 /***************************************************************************//**\r
906  * Returns description of last error.\r
907  *\r
908  * @param instance      Pointer to a MAC_instance_t structure\r
909  * @return              A string describing the error. This string must not be\r
910  *                                              modified by the application.\r
911  *                      #MAC_WRONG_PARAMETER if instance is null or hasn't been\r
912  *                      initialized.\r
913  */\r
914 const int8_t*\r
915 MSS_MAC_last_error\r
916 (\r
917     void\r
918 )\r
919 {\r
920         int8_t error_msg_nb;\r
921     const int8_t* returnvalue;\r
922 \r
923         error_msg_nb = -(g_mss_mac.last_error);\r
924         if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {\r
925                 returnvalue = unknown_error;\r
926         } else {\r
927                 returnvalue = ErrorMessages[error_msg_nb];\r
928         }\r
929         return returnvalue;\r
930 }\r
931 \r
932 \r
933 /***************************************************************************//**\r
934  * Returns statistics counter of stat_id identifier.\r
935  *\r
936  * @param instance      Pointer to a MAC_instance_t structure\r
937  * @param stat_id               Identifier of statistics counter.\r
938  * @return                              Statistics counter of stat_id identifier.\r
939  *                                              On error returns 0.\r
940  */\r
941 uint32_t\r
942 MSS_MAC_get_statistics\r
943 (\r
944     mss_mac_statistics_id_t stat_id\r
945 )\r
946 {\r
947     uint32_t returnval = 0u;\r
948 \r
949         switch( stat_id ) {\r
950         case MSS_MAC_RX_INTERRUPTS:\r
951                 returnval = g_mss_mac.statistics.rx_interrupts;\r
952         break;\r
953         case MSS_MAC_RX_FILTERING_FAIL:\r
954                 returnval = g_mss_mac.statistics.rx_filtering_fail;\r
955         break;\r
956         case MSS_MAC_RX_DESCRIPTOR_ERROR:\r
957                 returnval = g_mss_mac.statistics.rx_descriptor_error;\r
958         break;\r
959         case MSS_MAC_RX_RUNT_FRAME:\r
960                 returnval = g_mss_mac.statistics.rx_runt_frame;\r
961         break;\r
962         case MSS_MAC_RX_NOT_FIRST:\r
963                 returnval = g_mss_mac.statistics.rx_not_first;\r
964         break;\r
965         case MSS_MAC_RX_NOT_LAST:\r
966                 returnval = g_mss_mac.statistics.rx_not_last;\r
967         break;\r
968         case MSS_MAC_RX_FRAME_TOO_LONG:\r
969                 returnval = g_mss_mac.statistics.rx_frame_too_long;\r
970         break;\r
971         case MSS_MAC_RX_COLLISION_SEEN:\r
972                 returnval = g_mss_mac.statistics.rx_collision_seen;\r
973         break;\r
974         case MSS_MAC_RX_CRC_ERROR:\r
975                 returnval = g_mss_mac.statistics.rx_crc_error;\r
976         break;\r
977         case MSS_MAC_RX_FIFO_OVERFLOW:\r
978                 returnval = g_mss_mac.statistics.rx_fifo_overflow;\r
979         break;\r
980         case MSS_MAC_RX_MISSED_FRAME:\r
981                 returnval = g_mss_mac.statistics.rx_missed_frame;\r
982         break;\r
983         case MSS_MAC_TX_INTERRUPTS:\r
984                 returnval = g_mss_mac.statistics.tx_interrupts;\r
985         break;\r
986         case MSS_MAC_TX_LOSS_OF_CARRIER:\r
987                 returnval = g_mss_mac.statistics.tx_loss_of_carrier;\r
988         break;\r
989         case MSS_MAC_TX_NO_CARRIER:\r
990                 returnval = g_mss_mac.statistics.tx_no_carrier;\r
991         break;\r
992         case MSS_MAC_TX_LATE_COLLISION:\r
993                 returnval = g_mss_mac.statistics.tx_late_collision;\r
994         break;\r
995         case MSS_MAC_TX_EXCESSIVE_COLLISION:\r
996                 returnval = g_mss_mac.statistics.tx_excessive_collision;\r
997         break;\r
998         case MSS_MAC_TX_COLLISION_COUNT:\r
999                 returnval = g_mss_mac.statistics.tx_collision_count;\r
1000         break;\r
1001         case MSS_MAC_TX_UNDERFLOW_ERROR:\r
1002                 returnval = g_mss_mac.statistics.tx_underflow_error;\r
1003         break;\r
1004     default:\r
1005         break;\r
1006         }\r
1007 \r
1008         return returnval;\r
1009 }\r
1010 \r
1011 \r
1012 /**************************** INTERNAL FUNCTIONS ******************************/\r
1013 \r
1014 \r
1015 /***************************************************************************//**\r
1016  * Prepares current rx descriptor for receiving.\r
1017  */\r
1018 void\r
1019 MSS_MAC_prepare_rx_descriptor\r
1020 (\r
1021     void\r
1022 )\r
1023 {\r
1024         uint32_t desc;\r
1025 \r
1026         /* update counters */\r
1027         desc = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0;\r
1028         if( (desc & RDES0_FF) != 0u ) {\r
1029                 g_mss_mac.statistics.rx_filtering_fail++;\r
1030         }\r
1031         if( (desc & RDES0_DE) != 0u ) {\r
1032                 g_mss_mac.statistics.rx_descriptor_error++;\r
1033         }\r
1034         if( (desc & RDES0_RF) != 0u ) {\r
1035                 g_mss_mac.statistics.rx_runt_frame++;\r
1036         }\r
1037         if( (desc & RDES0_FS) == 0u ) {\r
1038                 g_mss_mac.statistics.rx_not_first++;\r
1039         }\r
1040         if( (desc & RDES0_LS) == 0u ) {\r
1041                 g_mss_mac.statistics.rx_not_last++;\r
1042         }\r
1043         if( (desc & RDES0_TL) != 0u ) {\r
1044                 g_mss_mac.statistics.rx_frame_too_long++;\r
1045         }\r
1046         if( (desc & RDES0_CS) != 0u ) {\r
1047                 g_mss_mac.statistics.rx_collision_seen++;\r
1048         }\r
1049         if( (desc & RDES0_CE) != 0u ) {\r
1050                 g_mss_mac.statistics.rx_crc_error++;\r
1051         }\r
1052 \r
1053         desc = MAC->CSR8;\r
1054         g_mss_mac.statistics.rx_fifo_overflow +=\r
1055                 (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;\r
1056         g_mss_mac.statistics.rx_missed_frame +=\r
1057                 (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));\r
1058 \r
1059         /* Give ownership of descriptor to the MAC */\r
1060         g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =\r
1061                 RDES0_OWN;\r
1062         g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;\r
1063 \r
1064         /* Start receive */\r
1065     MAC_start_receiving();\r
1066 }\r
1067 \r
1068 \r
1069 /***************************************************************************//**\r
1070  * Prepares a setup frame and sends it to MAC.\r
1071  * This function is blocking.\r
1072  * @return              #MAC_OK if everything is ok.\r
1073  *                              #MAC_TIME_OUT if timed out before packet send.\r
1074  */\r
1075 static int32_t\r
1076 MAC_send_setup_frame\r
1077 (\r
1078     void\r
1079 )\r
1080 {\r
1081         volatile MAC_descriptor_t descriptor;\r
1082         uint8_t frame_data[192];\r
1083         uint8_t *data;\r
1084         int32_t a,b,c,d;\r
1085         int32_t ret;\r
1086 \r
1087     /* prepare descriptor */\r
1088         descriptor.descriptor_0 = TDES0_OWN;\r
1089         descriptor.descriptor_1 = TDES1_SET | TDES1_TER |\r
1090                 (sizeof(frame_data) << TDES1_TBS1_OFFSET);\r
1091 \r
1092         if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) == 0u ) {\r
1093                 descriptor.descriptor_1 |= TDES1_FT0;\r
1094         }\r
1095 \r
1096         descriptor.buffer_1 = (uint32_t)frame_data;\r
1097         descriptor.buffer_2 = 0u;\r
1098 \r
1099     /* prepare frame */\r
1100     if( (g_mss_mac.flags & FLAG_PERFECT_FILTERING) != 0u ) {\r
1101         b = 0;\r
1102         d = 12;\r
1103         c = 90;\r
1104     } else {\r
1105         b = 156;\r
1106         d = 0;\r
1107         c = 64;\r
1108     }\r
1109 \r
1110         data = g_mss_mac.mac_address;\r
1111         frame_data[b] = data[0];\r
1112         frame_data[b+1] = data[1];\r
1113         frame_data[b+4] = data[2];\r
1114         frame_data[b+5] = data[3];\r
1115         frame_data[b+8] = data[4];\r
1116         frame_data[b+9] = data[5];\r
1117 \r
1118         data = g_mss_mac.mac_filter_data;\r
1119     for( a = 0; a < c; ) {\r
1120                 frame_data[d] = data[a++];\r
1121                 frame_data[d+1] = data[a++];\r
1122                 frame_data[d+4] = data[a++];\r
1123                 frame_data[d+5] = data[a++];\r
1124                 frame_data[d+8] = data[a++];\r
1125                 frame_data[d+9] = data[a++];\r
1126                 d += 12;\r
1127         }\r
1128 \r
1129         /* Stop transmission */\r
1130     ret = MAC_stop_transmission();\r
1131     configASSERT( ret == MAC_OK );\r
1132 \r
1133     ret = MAC_stop_receiving();\r
1134     configASSERT( ret == MAC_OK );\r
1135 \r
1136     /* Set descriptor */\r
1137     MAC->CSR4 = (uint32_t)&descriptor;\r
1138 \r
1139         /* Start transmission */\r
1140     MAC_start_transmission();\r
1141 \r
1142     /* Wait until transmission over */\r
1143     ret = MAC_OK;\r
1144     MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );\r
1145 \r
1146     while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
1147         CSR5_TS_SUSPENDED) && (MAC_OK == ret) )\r
1148     {\r
1149         /* transmit poll demand */\r
1150         MAC->CSR1 = 1u;\r
1151         if( MAC_get_time_out() == 0u ) {\r
1152                 ret = MAC_TIME_OUT;\r
1153         }\r
1154     }\r
1155 \r
1156         MAC_CHECK( MAC_stop_transmission() == MAC_OK, MAC_FAIL );\r
1157 \r
1158     /* Set tx descriptor */\r
1159     MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;\r
1160 \r
1161     /* Start receiving and transmission */\r
1162     MAC_start_receiving();\r
1163     MAC_start_transmission();\r
1164 \r
1165     return ret;\r
1166 }\r
1167 \r
1168 \r
1169 /***************************************************************************//**\r
1170  * Stops transmission.\r
1171  * Function will wait until transmit operation enters stop state.\r
1172  *\r
1173  * @return                      #MAC_OK if everything is ok.\r
1174  *                                      #MAC_TIME_OUT if timed out.\r
1175  */\r
1176 static int32_t\r
1177 MAC_stop_transmission\r
1178 (\r
1179     void\r
1180 )\r
1181 {\r
1182     int32_t retval = MAC_OK;\r
1183     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1184 \r
1185         while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=\r
1186                 CSR5_TS_STOPPED) && (retval == MAC_OK) )\r
1187         {\r
1188         MAC_BITBAND->CSR6_ST = 0u;\r
1189         if( MAC_get_time_out() == 0u ) {\r
1190                 retval = MAC_TIME_OUT;\r
1191         }\r
1192         }\r
1193         return retval;\r
1194 }\r
1195 \r
1196 \r
1197 /***************************************************************************//**\r
1198  * Starts transmission.\r
1199  */\r
1200 static void\r
1201 MAC_start_transmission\r
1202 (\r
1203     void\r
1204 )\r
1205 {\r
1206     MAC_BITBAND->CSR6_ST = 1u;\r
1207 }\r
1208 \r
1209 \r
1210 /***************************************************************************//**\r
1211  * Stops transmission.\r
1212  * Function will wait until transmit operation enters stop state.\r
1213  *\r
1214  * @return                      #MAC_OK if everything is ok.\r
1215  *                                      #MAC_TIME_OUT if timed out.\r
1216  */\r
1217 static int32_t\r
1218 MAC_stop_receiving\r
1219 (\r
1220     void\r
1221 )\r
1222 {\r
1223     int32_t retval = MAC_OK;\r
1224     MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );\r
1225 \r
1226         while( (((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED)\r
1227             && (retval == MAC_OK) )\r
1228         {\r
1229         MAC_BITBAND->CSR6_SR = 0u;\r
1230         if( MAC_get_time_out() == 0u ) {\r
1231                 retval = MAC_TIME_OUT;\r
1232         }\r
1233         }\r
1234 \r
1235         return retval;\r
1236 }\r
1237 \r
1238 \r
1239 /***************************************************************************//**\r
1240  * Starts transmission.\r
1241  */\r
1242 static void\r
1243 MAC_start_receiving\r
1244 (\r
1245     void\r
1246 )\r
1247 {\r
1248     MAC_BITBAND->CSR6_SR = 1u;\r
1249 }\r
1250 \r
1251 \r
1252 /***************************************************************************//**\r
1253  * Dismisses bad frames.\r
1254  *\r
1255  * @return              dismissed frame count.\r
1256  */\r
1257 static int32_t\r
1258 MAC_dismiss_bad_frames\r
1259 (\r
1260     void\r
1261 )\r
1262 {\r
1263         int32_t dc = 0;\r
1264         int8_t cont = 1;\r
1265 \r
1266         if( MAC_BITBAND->CSR6_PB != 0u ) {\r
1267                 /* User wants bad frames too, don't dismiss anything */\r
1268                 cont = 0;\r
1269         }\r
1270 \r
1271         while( ( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
1272             RDES0_OWN) == 0u) && (cont == 1) ) /* Host owns this descriptor */\r
1273     {\r
1274         /* check error summary */\r
1275         if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
1276                 (RDES0_ES | RDES0_LS | RDES0_FS)) != (RDES0_LS | RDES0_FS) )\r
1277         {\r
1278                 MSS_MAC_prepare_rx_descriptor();\r
1279                 dc++;\r
1280         }\r
1281         else\r
1282         {\r
1283                 cont = 0;\r
1284         }\r
1285     }\r
1286 \r
1287         return dc;\r
1288 }\r
1289 \r
1290 /***************************************************************************//**\r
1291  * Sets time out value.\r
1292  * #MAC_get_time_out must be called frequently to make time out value updated.\r
1293  * Because of user may not be using ISR, we can not update time out in ISR.\r
1294  *\r
1295  * @time_out    time out value in milli seconds.\r
1296  *                              Must be smaller than 0x01000000.\r
1297  */\r
1298 static void\r
1299 MAC_set_time_out\r
1300 (\r
1301     uint32_t time_out\r
1302 )\r
1303 {\r
1304         g_mss_mac.time_out_value = (time_out * 122u) / 10u;\r
1305 \r
1306         g_mss_mac.last_timer_value = (uint16_t)( MAC->CSR11 & CSR11_TIM_MASK );\r
1307 }\r
1308 \r
1309 /***************************************************************************//**\r
1310  * Returns time out value.\r
1311  *\r
1312  * @return              timer out value in milli seconds.\r
1313  */\r
1314 static uint32_t\r
1315 MAC_get_time_out\r
1316 (\r
1317     void\r
1318 )\r
1319 {\r
1320         uint32_t timer;\r
1321         uint32_t time = 0u;\r
1322 \r
1323         timer = ( MAC->CSR11 & CSR11_TIM_MASK );\r
1324 \r
1325         if( timer > g_mss_mac.last_timer_value ) {\r
1326                 time = 0x0000ffffUL;\r
1327         }\r
1328         time += g_mss_mac.last_timer_value - timer;\r
1329 \r
1330         if( MAC_BITBAND->CSR6_TTM == 0u ) {\r
1331                 time *= 10u;\r
1332         }\r
1333         if( g_mss_mac.time_out_value <= time ){\r
1334                 g_mss_mac.time_out_value = 0u;\r
1335         } else {\r
1336                 g_mss_mac.time_out_value -= time;\r
1337         }\r
1338 \r
1339         g_mss_mac.last_timer_value = (uint16_t)timer;\r
1340 \r
1341         return ((g_mss_mac.time_out_value * 10u) / 122u);\r
1342 }\r
1343 \r
1344 /***************************************************************************//**\r
1345  * Fills the first n bytes of the memory area pointed to by s with the constant\r
1346  * byte c.\r
1347  */\r
1348 static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n)\r
1349 {\r
1350     uint8_t *sb = s;\r
1351 \r
1352     while( n > 0u ) {\r
1353         n--;\r
1354         sb[n] = c;\r
1355     }\r
1356 }\r
1357 \r
1358 /***************************************************************************//**\r
1359  * Fills all fields of MAC_instance_t with c.\r
1360  *\r
1361  * @return          a pointer to the given MAC_instance_t s.\r
1362  */\r
1363 static void MAC_memset_All(MAC_instance_t *s, uint32_t c)\r
1364 {\r
1365     int32_t count;\r
1366     s->base_address = (addr_t)c;\r
1367     s->flags = (uint8_t)c;\r
1368     s->last_error = (int8_t)c;\r
1369     s->last_timer_value = (uint16_t)c;\r
1370     s->listener = NULL_callback;\r
1371         MAC_memset( s->mac_address, (uint8_t)c, 6u );\r
1372         MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );\r
1373     s->phy_address = (uint8_t)c;\r
1374     s->rx_desc_index =c;\r
1375     for(count = 0; count<RX_RING_SIZE ;count++)\r
1376     {\r
1377         s->rx_descriptors[count].buffer_1 = c;\r
1378         s->rx_descriptors[count].buffer_2 = c;\r
1379         s->rx_descriptors[count].descriptor_0 = c;\r
1380         s->rx_descriptors[count].descriptor_1 = c;\r
1381     }\r
1382     s->statistics.rx_collision_seen =c;\r
1383     s->statistics.rx_crc_error = c;\r
1384     s->statistics.rx_descriptor_error = c;\r
1385     s->statistics.rx_fifo_overflow = c;\r
1386     s->statistics.rx_filtering_fail = c;\r
1387     s->statistics.rx_frame_too_long = c;\r
1388     s->statistics.rx_interrupts = c;\r
1389     s->statistics.rx_missed_frame = c;\r
1390     s->statistics.rx_not_first = c;\r
1391     s->statistics.rx_not_last = c;\r
1392     s->statistics.rx_runt_frame = c;\r
1393     s->statistics.tx_collision_count = c;\r
1394     s->statistics.tx_excessive_collision = c;\r
1395     s->statistics.tx_interrupts = c;\r
1396     s->statistics.tx_late_collision = c;\r
1397     s->statistics.tx_loss_of_carrier = c;\r
1398     s->statistics.tx_no_carrier = c;\r
1399     s->statistics.tx_underflow_error = c;\r
1400     s->time_out_value = c;\r
1401     s->tx_desc_index = c;\r
1402     for(count = 0; count < TX_RING_SIZE ;count++)\r
1403     {\r
1404         s->tx_descriptors[count].buffer_1 = c;\r
1405         s->tx_descriptors[count].buffer_2 = c;\r
1406         s->tx_descriptors[count].descriptor_0 = c;\r
1407         s->tx_descriptors[count].descriptor_1 = c;\r
1408     }\r
1409 }\r
1410 \r
1411 /***************************************************************************//**\r
1412  * Copies n bytes from memory area src to memory area dest.\r
1413  * The memory areas should not overlap.\r
1414  *\r
1415  * @return          a pointer to the memory area dest.\r
1416  */\r
1417 static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)\r
1418 {\r
1419     uint8_t *d = dest;\r
1420 \r
1421     while( n > 0u ) {\r
1422         n--;\r
1423         d[n] = src[n];\r
1424     }\r
1425 }\r
1426 \r
1427 /***************************************************************************//**\r
1428  * Tx has completed, mark the buffers that were assigned to the Tx descriptors\r
1429  * as free again.\r
1430  *\r
1431  */\r
1432 void MSS_MAC_FreeTxBuffers( void )\r
1433 {\r
1434         if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )\r
1435         {\r
1436                 MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );\r
1437                 MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1 );\r
1438         }\r
1439 }\r
1440 \r
1441 /***************************************************************************//**\r
1442  * Look through the array of buffers until one is found that is free for use -\r
1443  * that is, not currently assigned to an Rx or a Tx descriptor.  Mark the buffer\r
1444  * as in use, then return its address.\r
1445  *\r
1446  * @return          a pointer to a free buffer.\r
1447  */\r
1448 unsigned char *MAC_obtain_buffer( void )\r
1449 {\r
1450 long lIndex;\r
1451 unsigned char *pcReturn = NULL;\r
1452 \r
1453         /* Find and return the address of a buffer that is not being used.  Mark\r
1454         the buffer as now in use. */\r
1455         for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
1456         {\r
1457                 if( ucMACBufferInUse[ lIndex ] == pdFALSE )\r
1458                 {\r
1459                         pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
1460                         ucMACBufferInUse[ lIndex ] = pdTRUE;\r
1461                         break;\r
1462                 }\r
1463         }\r
1464         \r
1465         configASSERT( pcReturn );\r
1466         return pcReturn;\r
1467 }\r
1468 \r
1469 /***************************************************************************//**\r
1470  * Return a buffer to the list of free buffers, it was in use, but is not now.\r
1471  *\r
1472  */\r
1473 void MAC_release_buffer( unsigned char *pucBufferToRelease )\r
1474 {\r
1475 long lIndex;\r
1476 \r
1477         /* uip_buf is going to point to a different buffer - first ensure the buffer\r
1478         it is currently pointing to is marked as being free again. */\r
1479         for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
1480         {\r
1481                 if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )\r
1482                 {\r
1483                         /* This is the buffer in use, mark it as being free. */\r
1484                         ucMACBufferInUse[ lIndex ] = pdFALSE;\r
1485                         break;\r
1486                 }\r
1487         }\r
1488         \r
1489         configASSERT( lIndex < macNUM_BUFFERS );\r
1490 }\r
1491 \r
1492 \r
1493 \r
1494 #ifdef __cplusplus\r
1495 }\r
1496 #endif\r
1497 \r
1498 /******************************** END OF FILE *********************************/\r
1499 \r