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