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