]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ethernet/lwIP_130/contrib/port/FreeRTOS/ColdFire/MCF5225x_ethernetif.c
Start to remove unnecessary 'signed char *' casts from strings that are now just...
[freertos] / FreeRTOS / Demo / Common / ethernet / lwIP_130 / contrib / port / FreeRTOS / ColdFire / MCF5225x_ethernetif.c
1 /*\r
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without modification,\r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission.\r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  *\r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 /* Standard library includes. */\r
34 #include <stdio.h>\r
35 #include <string.h>\r
36 \r
37 /* FreeRTOS includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 \r
41 xTaskHandle xEthIntTask;\r
42 \r
43 /* lwIP includes. */\r
44 #include "lwip/def.h"\r
45 #include "lwip/mem.h"\r
46 #include "lwip/pbuf.h"\r
47 #include "lwip/sys.h"\r
48 #include "lwip/stats.h"\r
49 #include "lwip/snmp.h"\r
50 #include "netif/etharp.h"\r
51 \r
52 /* Hardware includes. */\r
53 #include "fec.h"\r
54 \r
55 /* Delay to wait for a DMA buffer to become available if one is not already\r
56 available. */\r
57 #define netifBUFFER_WAIT_ATTEMPTS                                       10\r
58 #define netifBUFFER_WAIT_DELAY                                          (10 / portTICK_RATE_MS)\r
59 \r
60 /* Delay between polling the PHY to see if a link has been established. */\r
61 #define netifLINK_DELAY                                                         ( 500 / portTICK_RATE_MS )\r
62 \r
63 /* Delay between looking for incoming packets.  In ideal world this would be\r
64 infinite. */\r
65 #define netifBLOCK_TIME_WAITING_FOR_INPUT                       netifLINK_DELAY\r
66 \r
67 /* Name for the netif. */\r
68 #define IFNAME0 'e'\r
69 #define IFNAME1 'n'\r
70 \r
71 /* Hardware specific. */\r
72 #define netifFIRST_FEC_VECTOR                                           23\r
73 \r
74 /*-----------------------------------------------------------*/\r
75 \r
76 /* The DMA descriptors.  This is a char array to allow us to align it correctly. */\r
77 static unsigned char xFECTxDescriptors_unaligned[ ( configNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
78 static unsigned char xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
79 static FECBD *xFECTxDescriptors;\r
80 static FECBD *xFECRxDescriptors;\r
81 \r
82 /* The DMA buffers.  These are char arrays to allow them to be alligned correctly. */\r
83 static unsigned char ucFECTxBuffers[ ( configNUM_FEC_TX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
84 static unsigned char ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
85 static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxNextTxBuffer = 0;\r
86 \r
87 /* Semaphore used by the FEC interrupt handler to wake the handler task. */\r
88 static xSemaphoreHandle xFecSemaphore;\r
89 \r
90 #pragma options align= packed\r
91 struct ethernetif\r
92 {\r
93   struct eth_addr *ethaddr;\r
94   /* Add whatever per-interface state that is needed here. */\r
95 };\r
96 \r
97 /*-----------------------------------------------------------*/\r
98 \r
99 /* Standard lwIP netif handlers. */\r
100 static void prvInitialiseFECBuffers( void );\r
101 static void low_level_init( struct netif *netif );\r
102 static err_t low_level_output(struct netif *netif, struct pbuf *p);\r
103 static struct pbuf *low_level_input(struct netif *netif);\r
104 static void ethernetif_input( void *pParams );\r
105 \r
106 /* Functions adapted from Freescale provided code. */\r
107 static int fec_mii_write( int phy_addr, int reg_addr, int data );\r
108 static int fec_mii_read( int phy_addr, int reg_addr, uint16* data );\r
109 static uint8 fec_hash_address( const uint8* addr );\r
110 static void fec_set_address( const uint8 *pa );\r
111 static void fec_irq_enable( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /********************************************************************/\r
116 /*\r
117  * Write a value to a PHY's MII register.\r
118  *\r
119  * Parameters:\r
120  *  ch          FEC channel\r
121  *  phy_addr    Address of the PHY.\r
122  *  reg_addr    Address of the register in the PHY.\r
123  *  data        Data to be written to the PHY register.\r
124  *\r
125  * Return Values:\r
126  *  0 on failure\r
127  *  1 on success.\r
128  *\r
129  * Please refer to your PHY manual for registers and their meanings.\r
130  * mii_write() polls for the FEC's MII interrupt event and clears it. \r
131  * If after a suitable amount of time the event isn't triggered, a \r
132  * value of 0 is returned.\r
133  */\r
134 static int fec_mii_write( int phy_addr, int reg_addr, int data )\r
135 {\r
136 int timeout;\r
137 uint32 eimr;\r
138 \r
139         /* Clear the MII interrupt bit */\r
140         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
141 \r
142         /* Mask the MII interrupt */\r
143         eimr = MCF_FEC_EIMR;\r
144         MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;\r
145 \r
146         /* Write to the MII Management Frame Register to kick-off the MII write */\r
147         MCF_FEC_MMFR = MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_WRITE | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10 | MCF_FEC_MMFR_DATA( data );\r
148 \r
149         /* Poll for the MII interrupt (interrupt should be masked) */\r
150         for (timeout = 0; timeout < MII_TIMEOUT; timeout++)\r
151         {\r
152                 if (MCF_FEC_EIR & MCF_FEC_EIR_MII)\r
153                 {\r
154                         break;\r
155                 }\r
156         }\r
157 \r
158         if( timeout == MII_TIMEOUT )\r
159         {\r
160                 return 0;\r
161         }\r
162 \r
163         /* Clear the MII interrupt bit */\r
164         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
165 \r
166         /* Restore the EIMR */\r
167         MCF_FEC_EIMR = eimr;\r
168 \r
169         return 1;\r
170 }\r
171 \r
172 /********************************************************************/\r
173 /*\r
174  * Read a value from a PHY's MII register.\r
175  *\r
176  * Parameters:\r
177  *  ch          FEC channel\r
178  *  phy_addr    Address of the PHY.\r
179  *  reg_addr    Address of the register in the PHY.\r
180  *  data        Pointer to storage for the Data to be read\r
181  *              from the PHY register (passed by reference)\r
182  *\r
183  * Return Values:\r
184  *  0 on failure\r
185  *  1 on success.\r
186  *\r
187  * Please refer to your PHY manual for registers and their meanings.\r
188  * mii_read() polls for the FEC's MII interrupt event and clears it. \r
189  * If after a suitable amount of time the event isn't triggered, a \r
190  * value of 0 is returned.\r
191  */\r
192 static int fec_mii_read( int phy_addr, int reg_addr, uint16* data )\r
193 {\r
194 int timeout;\r
195 uint32 eimr;\r
196 \r
197         /* Clear the MII interrupt bit */\r
198         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
199 \r
200         /* Mask the MII interrupt */\r
201         eimr = MCF_FEC_EIMR;\r
202         MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;\r
203 \r
204         /* Write to the MII Management Frame Register to kick-off the MII read */\r
205         MCF_FEC_MMFR = MCF_FEC_MMFR_ST_01 | MCF_FEC_MMFR_OP_READ | MCF_FEC_MMFR_PA(phy_addr) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10;\r
206 \r
207         /* Poll for the MII interrupt (interrupt should be masked) */\r
208         for (timeout = 0; timeout < MII_TIMEOUT; timeout++)\r
209         {\r
210                 if (MCF_FEC_EIR & MCF_FEC_EIR_MII)\r
211                 {\r
212                         break;\r
213                 }\r
214         }\r
215 \r
216         if(timeout == MII_TIMEOUT)\r
217         {\r
218                 return 0;\r
219         }\r
220 \r
221         /* Clear the MII interrupt bit */\r
222         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
223 \r
224         /* Restore the EIMR */\r
225         MCF_FEC_EIMR = eimr;\r
226 \r
227         *data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF);\r
228 \r
229         return 1;\r
230 }\r
231 \r
232 \r
233 /********************************************************************/\r
234 /*\r
235  * Generate the hash table settings for the given address\r
236  *\r
237  * Parameters:\r
238  *  addr    48-bit (6 byte) Address to generate the hash for\r
239  *\r
240  * Return Value:\r
241  *  The 6 most significant bits of the 32-bit CRC result\r
242  */\r
243 static uint8 fec_hash_address( const uint8* addr )\r
244 {\r
245 uint32 crc;\r
246 uint8 byte;\r
247 int i, j;\r
248 \r
249         crc = 0xFFFFFFFF;\r
250         for(i=0; i<6; ++i)\r
251         {\r
252                 byte = addr[i];\r
253                 for(j=0; j<8; ++j)\r
254                 {\r
255                         if((byte & 0x01)^(crc & 0x01))\r
256                         {\r
257                                 crc >>= 1;\r
258                                 crc = crc ^ 0xEDB88320;\r
259                         }\r
260                         else\r
261                         {\r
262                                 crc >>= 1;\r
263                         }\r
264 \r
265                         byte >>= 1;\r
266                 }\r
267         }\r
268 \r
269         return (uint8)(crc >> 26);\r
270 }\r
271 \r
272 /********************************************************************/\r
273 /*\r
274  * Set the Physical (Hardware) Address and the Individual Address\r
275  * Hash in the selected FEC\r
276  *\r
277  * Parameters:\r
278  *  ch  FEC channel\r
279  *  pa  Physical (Hardware) Address for the selected FEC\r
280  */\r
281 static void fec_set_address( const uint8 *pa )\r
282 {\r
283         uint8 crc;\r
284 \r
285         /*\r
286         * Set the Physical Address\r
287         */\r
288         MCF_FEC_PALR = (uint32)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);\r
289         MCF_FEC_PAUR = (uint32)((pa[4]<<24) | (pa[5]<<16));\r
290 \r
291         /*\r
292         * Calculate and set the hash for given Physical Address\r
293         * in the  Individual Address Hash registers\r
294         */\r
295         crc = fec_hash_address(pa);\r
296         if(crc >= 32)\r
297         {\r
298                 MCF_FEC_IAUR |= (uint32)(1 << (crc - 32));\r
299         }\r
300         else\r
301         {\r
302                 MCF_FEC_IALR |= (uint32)(1 << crc);\r
303         }\r
304 }\r
305 \r
306 \r
307 /********************************************************************/\r
308 /*\r
309  * Enable interrupts on the selected FEC\r
310  *\r
311  */\r
312 static void fec_irq_enable( void )\r
313 {\r
314 int fec_vbase;\r
315 \r
316 #if INTC_LVL_FEC > configMAX_SYSCALL_INTERRUPT_PRIORITY\r
317         #error INTC_LVL_FEC must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY\r
318 #endif\r
319 \r
320         fec_vbase = 64 + netifFIRST_FEC_VECTOR;\r
321     \r
322         /* Enable FEC interrupts to the ColdFire core \r
323          * Setup each ICR with a unique interrupt level combination */\r
324         fec_vbase -= 64;\r
325 \r
326         /* FEC Rx Frame */\r
327         MCF_INTC0_ICR(fec_vbase+4)  = MCF_INTC_ICR_IL(INTC_LVL_FEC);\r
328 \r
329         /* FEC Rx Buffer */                              \r
330         MCF_INTC0_ICR(fec_vbase+5)  = MCF_INTC_ICR_IL(INTC_LVL_FEC);\r
331 \r
332         /* FEC FIFO Underrun */                              \r
333         MCF_INTC0_ICR(fec_vbase+2)  = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
334 \r
335         /* FEC Collision Retry Limit */                              \r
336         MCF_INTC0_ICR(fec_vbase+3)  = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
337 \r
338         /* FEC Late Collision */                                 \r
339         MCF_INTC0_ICR(fec_vbase+7)  = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
340 \r
341         /* FEC Heartbeat Error */                                \r
342         MCF_INTC0_ICR(fec_vbase+8)  = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
343 \r
344         /* FEC Bus Error */                              \r
345         MCF_INTC0_ICR(fec_vbase+10) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
346 \r
347         /* FEC Babbling Transmit */                              \r
348         MCF_INTC0_ICR(fec_vbase+11) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
349 \r
350         /* FEC Babbling Receive */                               \r
351         MCF_INTC0_ICR(fec_vbase+12) = MCF_INTC_ICR_IL(INTC_LVL_FEC+1);\r
352                                  \r
353         /* Enable the FEC interrupts in the mask register */    \r
354         MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );\r
355         MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27 | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30 | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL );\r
356 \r
357     /* Clear any pending FEC interrupt events */\r
358     MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;\r
359 \r
360     /* Unmask all FEC interrupts */\r
361     MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;\r
362 }\r
363 \r
364 /**\r
365  * In this function, the hardware should be initialized.\r
366  * Called from ethernetif_init().\r
367  *\r
368  * @param netif the already initialized lwip network interface structure\r
369  *        for this ethernetif\r
370  */\r
371 static void low_level_init( struct netif *netif )\r
372 {\r
373 unsigned short usData;\r
374 const unsigned char ucMACAddress[6] = \r
375 {\r
376         configMAC_0, configMAC_1,configMAC_2,configMAC_3,configMAC_4,configMAC_5\r
377 };\r
378 \r
379         prvInitialiseFECBuffers();\r
380         vSemaphoreCreateBinary( xFecSemaphore );\r
381         \r
382         for( usData = 0; usData < 6; usData++ )\r
383         {\r
384                 netif->hwaddr[ usData ] = ucMACAddress[ usData ];\r
385         }\r
386 \r
387         /* Set the Reset bit and clear the Enable bit */\r
388         MCF_FEC_ECR = MCF_FEC_ECR_RESET;\r
389 \r
390         /* Wait at least 8 clock cycles */\r
391         for( usData = 0; usData < 10; usData++ )\r
392         {\r
393                 asm( "NOP" );\r
394         }\r
395 \r
396         /* Set MII speed to 2.5MHz. */\r
397         MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 );\r
398 \r
399         /*\r
400          * Make sure the external interface signals are enabled\r
401          */\r
402         MCF_GPIO_PNQPAR = MCF_GPIO_PNQPAR_IRQ3_FEC_MDIO | MCF_GPIO_PNQPAR_IRQ5_FEC_MDC;\r
403 \r
404 \r
405     MCF_GPIO_PTIPAR = MCF_GPIO_PTIPAR_FEC_COL_FEC_COL                   \r
406                                         | MCF_GPIO_PTIPAR_FEC_CRS_FEC_CRS                       \r
407                                         | MCF_GPIO_PTIPAR_FEC_RXCLK_FEC_RXCLK           \r
408                                         | MCF_GPIO_PTIPAR_FEC_RXD0_FEC_RXD0                     \r
409                                         | MCF_GPIO_PTIPAR_FEC_RXD1_FEC_RXD1                     \r
410                                         | MCF_GPIO_PTIPAR_FEC_RXD2_FEC_RXD2                     \r
411                                         | MCF_GPIO_PTIPAR_FEC_RXD3_FEC_RXD3                     \r
412                                         | MCF_GPIO_PTIPAR_FEC_RXDV_FEC_RXDV;            \r
413 \r
414         MCF_GPIO_PTJPAR = MCF_GPIO_PTJPAR_FEC_RXER_FEC_RXER                     \r
415                                         | MCF_GPIO_PTJPAR_FEC_TXCLK_FEC_TXCLK           \r
416                                         | MCF_GPIO_PTJPAR_FEC_TXD0_FEC_TXD0                     \r
417                                         | MCF_GPIO_PTJPAR_FEC_TXD1_FEC_TXD1                     \r
418                                         | MCF_GPIO_PTJPAR_FEC_TXD2_FEC_TXD2                     \r
419                                         | MCF_GPIO_PTJPAR_FEC_TXD3_FEC_TXD3                     \r
420                                         | MCF_GPIO_PTJPAR_FEC_TXEN_FEC_TXEN                     \r
421                                         | MCF_GPIO_PTJPAR_FEC_TXER_FEC_TXER;            \r
422 \r
423 \r
424         /* Can we talk to the PHY? */\r
425         do\r
426         {\r
427                 vTaskDelay( netifLINK_DELAY );\r
428                 usData = 0;\r
429                 fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );\r
430 \r
431         } while( ( usData == 0xffff ) || ( usData == 0 ) );\r
432 \r
433         /* Start auto negotiate. */\r
434         fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
435 \r
436         /* Wait for auto negotiate to complete. */\r
437         do\r
438         {\r
439                 vTaskDelay( netifLINK_DELAY );\r
440                 fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );\r
441 \r
442         } while( !( usData & PHY_BMSR_AN_COMPLETE ) );\r
443 \r
444         /* When we get here we have a link - find out what has been negotiated. */\r
445         fec_mii_read( configPHY_ADDRESS, PHY_ANLPAR, &usData );\r
446         \r
447         if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_100BTX ) )\r
448         {\r
449                 /* Speed is 100. */\r
450         }\r
451         else\r
452         {\r
453                 /* Speed is 10. */\r
454         }\r
455 \r
456         if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_10BTX_FDX ) )\r
457         {\r
458                 /* Full duplex. */\r
459                 MCF_FEC_RCR &= (uint32)~MCF_FEC_RCR_DRT;\r
460                 MCF_FEC_TCR |= MCF_FEC_TCR_FDEN;\r
461         }\r
462         else\r
463         {\r
464                 MCF_FEC_RCR |= MCF_FEC_RCR_DRT;\r
465                 MCF_FEC_TCR &= (uint32)~MCF_FEC_TCR_FDEN;\r
466         }\r
467         \r
468         /* Clear the Individual and Group Address Hash registers */\r
469         MCF_FEC_IALR = 0;\r
470         MCF_FEC_IAUR = 0;\r
471         MCF_FEC_GALR = 0;\r
472         MCF_FEC_GAUR = 0;\r
473 \r
474         /* Set the Physical Address for the selected FEC */\r
475         fec_set_address( ucMACAddress );\r
476 \r
477         /* Set Rx Buffer Size */\r
478         MCF_FEC_EMRBR = (uint16)configFEC_BUFFER_SIZE;\r
479 \r
480         /* Point to the start of the circular Rx buffer descriptor queue */\r
481         MCF_FEC_ERDSR = ( volatile unsigned long ) &( xFECRxDescriptors[ 0 ] );\r
482 \r
483         /* Point to the start of the circular Tx buffer descriptor queue */\r
484         MCF_FEC_ETSDR = ( volatile unsigned long ) &( xFECTxDescriptors[ 0 ] );\r
485 \r
486         /* Mask all FEC interrupts */\r
487         MCF_FEC_EIMR = MCF_FEC_EIMR_MASK_ALL;\r
488 \r
489         /* Clear all FEC interrupt events */\r
490         MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;\r
491 \r
492         /* Initialize the Receive Control Register */\r
493         MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_FCE;\r
494 \r
495         MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;\r
496 \r
497         #if( configUSE_PROMISCUOUS_MODE == 1 )\r
498         {\r
499                 MCF_FEC_RCR |= MCF_FEC_RCR_PROM;\r
500         }\r
501         #endif\r
502 \r
503         /* Create the task that handles the EMAC. */\r
504         xTaskCreate( ethernetif_input, "ETH_INT", configETHERNET_INPUT_TASK_STACK_SIZE, (void *)netif, configETHERNET_INPUT_TASK_PRIORITY, &xEthIntTask );\r
505         \r
506         fec_irq_enable();\r
507         MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;\r
508         MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;       \r
509 }\r
510 \r
511 /**\r
512  * This function should do the actual transmission of the packet. The packet is\r
513  * contained in the pbuf that is passed to the function. This pbuf\r
514  * might be chained.\r
515  *\r
516  * @param netif the lwip network interface structure for this ethernetif\r
517  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)\r
518  * @return ERR_OK if the packet could be sent\r
519  *         an err_t value if the packet couldn't be sent\r
520  *\r
521  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to\r
522  *       strange results. You might consider waiting for space in the DMA queue\r
523  *       to become availale since the stack doesn't retry to send a packet\r
524  *       dropped because of memory failure (except for the TCP timers).\r
525  */\r
526 static err_t low_level_output(struct netif *netif, struct pbuf *p)\r
527 {\r
528 struct pbuf *q;\r
529 u32_t l = 0;\r
530 unsigned char *pcTxData = NULL;\r
531 portBASE_TYPE i;\r
532 \r
533         ( void ) netif;\r
534 \r
535         #if ETH_PAD_SIZE\r
536           pbuf_header(p, -ETH_PAD_SIZE);                        /* drop the padding word */\r
537         #endif\r
538 \r
539         /* Get a DMA buffer into which we can write the data to send. */\r
540         for( i = 0; i < netifBUFFER_WAIT_ATTEMPTS; i++ )\r
541         {\r
542                 if( xFECTxDescriptors[ uxNextTxBuffer ].status & TX_BD_R )\r
543                 {\r
544                         /* Wait for the buffer to become available. */\r
545                         vTaskDelay( netifBUFFER_WAIT_DELAY );\r
546                 }\r
547                 else\r
548                 {\r
549                         pcTxData = xFECTxDescriptors[ uxNextTxBuffer ].data;\r
550                         break;\r
551                 }\r
552         }\r
553 \r
554         if( pcTxData == NULL ) \r
555         {\r
556                 /* For break point only. */\r
557                 portNOP();\r
558 \r
559                 return ERR_BUF;\r
560         }\r
561         else \r
562         {\r
563                 for( q = p; q != NULL; q = q->next ) \r
564                 {\r
565                         /* Send the data from the pbuf to the interface, one pbuf at a\r
566                         time. The size of the data in each pbuf is kept in the ->len\r
567                         variable. */\r
568                         memcpy( &pcTxData[l], (u8_t*)q->payload, q->len );\r
569                         l += q->len;\r
570                 }\r
571         }\r
572 \r
573         /* Setup the buffer descriptor for transmission */\r
574         xFECTxDescriptors[ uxNextTxBuffer ].length = l;//nbuf->length + ETH_HDR_LEN;\r
575         xFECTxDescriptors[ uxNextTxBuffer ].status |= (TX_BD_R | TX_BD_L);\r
576 \r
577         /* Continue the Tx DMA task (in case it was waiting for a new TxBD) */\r
578         MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;\r
579 \r
580         uxNextTxBuffer++;\r
581         if( uxNextTxBuffer >= configNUM_FEC_TX_BUFFERS )\r
582         {\r
583                 uxNextTxBuffer = 0;\r
584         }\r
585 \r
586         #if ETH_PAD_SIZE\r
587                 pbuf_header(p, ETH_PAD_SIZE);                   /* reclaim the padding word */\r
588         #endif\r
589 \r
590         LINK_STATS_INC(link.xmit);\r
591 \r
592         return ERR_OK;\r
593 }\r
594 \r
595 /**\r
596  * Should allocate a pbuf and transfer the bytes of the incoming\r
597  * packet from the interface into the pbuf.\r
598  *\r
599  * @param netif the lwip network interface structure for this ethernetif\r
600  * @return a pbuf filled with the received packet (including MAC header)\r
601  *         NULL on memory error\r
602  */\r
603 static struct pbuf *low_level_input(struct netif *netif)\r
604 {\r
605 struct pbuf *p, *q;\r
606 u16_t len, l;\r
607 \r
608         ( void ) netif;\r
609 \r
610         l = 0;\r
611         p = NULL;\r
612 \r
613         /* Obtain the size of the packet and put it into the "len" variable. */\r
614         len = xFECRxDescriptors[ uxNextRxBuffer ].length;\r
615 \r
616         if( ( len != 0 ) && ( ( xFECRxDescriptors[ uxNextRxBuffer ].status & RX_BD_E ) == 0 ) )\r
617         {\r
618                 #if ETH_PAD_SIZE\r
619                         len += ETH_PAD_SIZE;                                            /* allow room for Ethernet padding */\r
620                 #endif\r
621 \r
622                 /* We allocate a pbuf chain of pbufs from the pool. */\r
623                 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
624 \r
625                 if (p != NULL) \r
626                 {\r
627 \r
628                         #if ETH_PAD_SIZE\r
629                                         pbuf_header(p, -ETH_PAD_SIZE);                  /* drop the padding word */\r
630                         #endif\r
631 \r
632                         /* We iterate over the pbuf chain until we have read the entire\r
633                          * packet into the pbuf. */\r
634                         for(q = p; q != NULL; q = q->next) \r
635                         {\r
636                                 /* Read enough bytes to fill this pbuf in the chain. The\r
637                                  * available data in the pbuf is given by the q->len\r
638                                  * variable. */\r
639                                 memcpy((u8_t*)q->payload, &(xFECRxDescriptors[ uxNextRxBuffer ].data[l]), q->len);\r
640                                 l = l + q->len;\r
641                         }\r
642 \r
643 \r
644                         #if ETH_PAD_SIZE\r
645                                 pbuf_header(p, ETH_PAD_SIZE);                   /* reclaim the padding word */\r
646                         #endif\r
647 \r
648                         LINK_STATS_INC(link.recv);\r
649 \r
650                 } \r
651                 else \r
652                 {\r
653 \r
654                         LINK_STATS_INC(link.memerr);\r
655                         LINK_STATS_INC(link.drop);\r
656 \r
657                 } /* End else */\r
658                 \r
659                 \r
660                 /* Free the descriptor. */\r
661                 xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;\r
662                 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
663                 \r
664                 uxNextRxBuffer++;\r
665                 if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )\r
666                 {\r
667                         uxNextRxBuffer = 0;\r
668                 }               \r
669                 \r
670         } /* End if */\r
671 \r
672         return p;\r
673 }\r
674 \r
675 /**\r
676  * This function should be called when a packet is ready to be read\r
677  * from the interface. It uses the function low_level_input() that\r
678  * should handle the actual reception of bytes from the network\r
679  * interface.Then the type of the received packet is determined and\r
680  * the appropriate input function is called.\r
681  *\r
682  * @param netif the lwip network interface structure for this ethernetif\r
683  */\r
684 \r
685 static void ethernetif_input( void *pParams )\r
686 {\r
687 struct netif *netif;\r
688 struct ethernetif *ethernetif;\r
689 struct eth_hdr *ethhdr;\r
690 struct pbuf *p;\r
691 \r
692         netif = (struct netif*) pParams;\r
693         ethernetif = netif->state;\r
694 \r
695         for( ;; )\r
696         {\r
697                 do\r
698                 {\r
699 \r
700                         /* move received packet into a new pbuf */\r
701                         p = low_level_input( netif );\r
702 \r
703                         if( p == NULL )\r
704                         {\r
705                                 /* No packet could be read.  Wait a for an interrupt to tell us\r
706                                 there is more data available. */\r
707                                 xSemaphoreTake( xFecSemaphore, netifBLOCK_TIME_WAITING_FOR_INPUT );\r
708                         }\r
709 \r
710                 } while( p == NULL );\r
711 \r
712                 /* points to packet payload, which starts with an Ethernet header */\r
713                 ethhdr = p->payload;\r
714 \r
715                 switch (htons(ethhdr->type)) {\r
716                         /* IP or ARP packet? */\r
717 \r
718                 case ETHTYPE_IP:\r
719 \r
720                         pbuf_header( p, (s16_t)-sizeof(struct eth_hdr) );\r
721 \r
722                         /* full packet send to tcpip_thread to process */\r
723                         if (netif->input(p, netif) != ERR_OK)\r
724                         {\r
725                                 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));\r
726                                 pbuf_free(p);\r
727                                 p = NULL;\r
728                         }\r
729                         break;\r
730 \r
731                 case ETHTYPE_ARP:\r
732 \r
733                         #if ETHARP_TRUST_IP_MAC\r
734                                 etharp_ip_input(netif, p);\r
735                         #endif\r
736 \r
737                         etharp_arp_input(netif, ethernetif->ethaddr, p);\r
738                         break;\r
739 \r
740                 default:\r
741                         pbuf_free(p);\r
742                         p = NULL;\r
743                         break;\r
744                 }\r
745         }\r
746 }\r
747 \r
748 /**\r
749  * Should be called at the beginning of the program to set up the\r
750  * network interface. It calls the function low_level_init() to do the\r
751  * actual setup of the hardware.\r
752  *\r
753  * This function should be passed as a parameter to netif_add().\r
754  *\r
755  * @param netif the lwip network interface structure for this ethernetif\r
756  * @return ERR_OK if the loopif is initialized\r
757  *         ERR_MEM if private data couldn't be allocated\r
758  *         any other err_t on error\r
759  */\r
760 err_t ethernetif_init(struct netif *netif)\r
761 {\r
762         struct ethernetif *ethernetif;\r
763 \r
764         LWIP_ASSERT("netif != NULL", (netif != NULL));\r
765 \r
766         ethernetif = mem_malloc(sizeof(struct ethernetif));\r
767 \r
768         if (ethernetif == NULL)\r
769         {\r
770                 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));\r
771                 return ERR_MEM;\r
772         }\r
773 \r
774         #if LWIP_NETIF_HOSTNAME\r
775         /* Initialize interface hostname */\r
776         netif->hostname = "lwip";\r
777         #endif /* LWIP_NETIF_HOSTNAME */\r
778 \r
779         /*\r
780         * Initialize the snmp variables and counters inside the struct netif.\r
781         * The last argument should be replaced with your link speed, in units\r
782         * of bits per second.\r
783         */\r
784         NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100);\r
785 \r
786         netif->state = ethernetif;\r
787         netif->name[0] = IFNAME0;\r
788         netif->name[1] = IFNAME1;\r
789 \r
790         /* We directly use etharp_output() here to save a function call.\r
791         * You can instead declare your own function an call etharp_output()\r
792         * from it if you have to do some checks before sending (e.g. if link\r
793         * is available...)\r
794         */\r
795         netif->output = etharp_output;\r
796         netif->linkoutput = low_level_output;\r
797 \r
798         ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);\r
799 \r
800         low_level_init(netif);\r
801 \r
802         return ERR_OK;\r
803 }\r
804 /*-----------------------------------------------------------*/\r
805 \r
806 static void prvInitialiseFECBuffers( void )\r
807 {\r
808 unsigned portBASE_TYPE ux;\r
809 unsigned char *pcBufPointer;\r
810 \r
811         pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );\r
812         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
813         {\r
814                 pcBufPointer++;\r
815         }\r
816         \r
817         xFECTxDescriptors = ( FECBD * ) pcBufPointer;\r
818         \r
819         pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );\r
820         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
821         {\r
822                 pcBufPointer++;\r
823         }\r
824         \r
825         xFECRxDescriptors = ( FECBD * ) pcBufPointer;\r
826 \r
827 \r
828         /* Setup the buffers and descriptors. */\r
829         pcBufPointer = &( ucFECTxBuffers[ 0 ] );\r
830         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
831         {\r
832                 pcBufPointer++;\r
833         }\r
834 \r
835         for( ux = 0; ux < configNUM_FEC_TX_BUFFERS; ux++ )\r
836         {\r
837                 xFECTxDescriptors[ ux ].status = TX_BD_TC;\r
838                 xFECTxDescriptors[ ux ].data = pcBufPointer;\r
839                 pcBufPointer += configFEC_BUFFER_SIZE;\r
840                 xFECTxDescriptors[ ux ].length = 0;\r
841         }\r
842 \r
843         pcBufPointer = &( ucFECRxBuffers[ 0 ] );\r
844         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
845         {\r
846                 pcBufPointer++;\r
847         }\r
848         \r
849         for( ux = 0; ux < configNUM_FEC_RX_BUFFERS; ux++ )\r
850         {\r
851             xFECRxDescriptors[ ux ].status = RX_BD_E;\r
852             xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;\r
853             xFECRxDescriptors[ ux ].data = pcBufPointer;\r
854             pcBufPointer += configFEC_BUFFER_SIZE;\r
855         }\r
856 \r
857         /* Set the wrap bit in the last descriptors to form a ring. */\r
858         xFECTxDescriptors[ configNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;\r
859         xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;\r
860 \r
861         uxNextRxBuffer = 0;\r
862         uxNextTxBuffer = 0;\r
863 }\r
864 /*-----------------------------------------------------------*/\r
865 \r
866 __declspec(interrupt:0) void vFECISRHandler( void )\r
867 {\r
868 unsigned long ulEvent;\r
869 portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;\r
870    \r
871         ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;\r
872         MCF_FEC_EIR = ulEvent;\r
873 \r
874         if( ( ulEvent & MCF_FEC_EIR_RXB ) || ( ulEvent & MCF_FEC_EIR_RXF ) )\r
875         {\r
876                 /* A packet has been received.  Wake the handler task. */\r
877                 xSemaphoreGiveFromISR( xFecSemaphore, &xHighPriorityTaskWoken );\r
878         }\r
879 \r
880         if (ulEvent & ( MCF_FEC_EIR_UN | MCF_FEC_EIR_RL | MCF_FEC_EIR_LC | MCF_FEC_EIR_EBERR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_BABR | MCF_FEC_EIR_HBERR ) )\r
881         {\r
882                 /* Sledge hammer error handling. */\r
883                 prvInitialiseFECBuffers();\r
884                 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
885         }\r
886 \r
887         portEND_SWITCHING_ISR( xHighPriorityTaskWoken );\r
888 }\r