]> git.sur5r.net Git - freertos/blob - Demo/ColdFire_MCF52233_Eclipse/RTOSDemo/webserver/FEC.c
New Eclipse demo added - working but not yet completed.
[freertos] / Demo / ColdFire_MCF52233_Eclipse / RTOSDemo / webserver / FEC.c
1 /*\r
2         FreeRTOS.org V5.1.0 - Copyright (C) 2003-2008 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section\r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license\r
28         and contact details.  Please ensure to read the configuration and relevant\r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 /* Kernel includes. */\r
34 #include "FreeRTOS.h"\r
35 #include "semphr.h"\r
36 #include "task.h"\r
37 \r
38 /* Demo includes. */\r
39 #include "fecbd.h"\r
40 #include "mii.h"\r
41 #include "eth_phy.h"\r
42 #include "eth.h"\r
43 \r
44 /* uIP includes. */\r
45 #include "uip.h"\r
46 #include "uip_arp.h"\r
47 \r
48 #define MCF_FEC_MSCR_MII_SPEED(x)               (((x)&0x3F)<<0x1)\r
49 #define MCF_FEC_RCR_MAX_FL(x)                   (((x)&0x7FF)<<0x10)\r
50 \r
51 /* Delay between polling the PHY to see if a link has been established. */\r
52 #define fecLINK_DELAY                                                   ( 500 / portTICK_RATE_MS )\r
53 \r
54 /* Delay to wait for an MII access. */\r
55 #define fecMII_DELAY                                                    ( 10 / portTICK_RATE_MS )\r
56 #define fecMAX_POLLS                                                    ( 20 )\r
57 \r
58 /* Delay between looking for incoming packets.  In ideal world this would be\r
59 infinite. */\r
60 #define netifBLOCK_TIME_WAITING_FOR_INPUT               fecLINK_DELAY\r
61 \r
62 /* Constants used to delay while waiting for a tx descriptor to be free. */\r
63 #define fecMAX_TX_WAIT_ATTEMPTS                                 4\r
64 #define fecTX_BUFFER_WAIT                                               ( 10 / portTICK_RATE_MS )\r
65 \r
66 /*-----------------------------------------------------------*/\r
67 \r
68 /* The semaphore used to wake the uIP task when data arrives. */\r
69 xSemaphoreHandle xFECSemaphore = NULL;\r
70 \r
71 /* The buffer used by the uIP stack.  In this case the pointer is used to\r
72 point to one of the Rx buffers. */\r
73 unsigned portCHAR *uip_buf;\r
74 \r
75 /* The DMA descriptors.  This is a char array to allow us to align it correctly. */\r
76 static unsigned portCHAR xFECTxDescriptors_unaligned[ ( configNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
77 static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
78 static FECBD *xFECTxDescriptors;\r
79 static FECBD *xFECRxDescriptors;\r
80 \r
81 /* The DMA buffers.  These are char arrays to allow them to be alligned correctly. */\r
82 static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
83 static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxNextTxBuffer = 0, uxIndexToBufferOwner = 0;\r
84 \r
85 /*-----------------------------------------------------------*/\r
86 \r
87 static void prvEnableFECInterrupts( void );\r
88 \r
89 /********************************************************************/\r
90 /*\r
91  * Write a value to a PHY's MII register.\r
92  *\r
93  * Parameters:\r
94  *  ch          FEC channel\r
95  *  phy_addr    Address of the PHY.\r
96  *  reg_addr    Address of the register in the PHY.\r
97  *  data        Data to be written to the PHY register.\r
98  *\r
99  * Return Values:\r
100  *  0 on failure\r
101  *  1 on success.\r
102  *\r
103  * Please refer to your PHY manual for registers and their meanings.\r
104  * mii_write() polls for the FEC's MII interrupt event and clears it.\r
105  * If after a suitable amount of time the event isn't triggered, a\r
106  * value of 0 is returned.\r
107  */\r
108 static int fec_mii_write( int phy_addr, int reg_addr, int data )\r
109 {\r
110 int timeout, iReturn;\r
111 uint32 eimr;\r
112 \r
113     /* Clear the MII interrupt bit */\r
114     MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
115 \r
116     /* Mask the MII interrupt */\r
117     eimr = MCF_FEC_EIMR;\r
118     MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;\r
119 \r
120     /* Write to the MII Management Frame Register to kick-off the MII write */\r
121     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
122 \r
123     /* Poll for the MII interrupt (interrupt should be masked) */\r
124     for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )\r
125     {\r
126         if( MCF_FEC_EIR & MCF_FEC_EIR_MII )\r
127         {\r
128                         break;\r
129         }\r
130         else\r
131         {\r
132                 vTaskDelay( fecMII_DELAY );\r
133         }\r
134     }\r
135 \r
136     if( timeout == fecMAX_POLLS )\r
137     {\r
138         iReturn = 0;\r
139     }\r
140     else\r
141     {\r
142                 iReturn = 1;\r
143     }\r
144 \r
145         /* Clear the MII interrupt bit */\r
146         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
147 \r
148         /* Restore the EIMR */\r
149         MCF_FEC_EIMR = eimr;\r
150 \r
151     return iReturn;\r
152 }\r
153 \r
154 /********************************************************************/\r
155 /*\r
156  * Read a value from a PHY's MII register.\r
157  *\r
158  * Parameters:\r
159  *  ch          FEC channel\r
160  *  phy_addr    Address of the PHY.\r
161  *  reg_addr    Address of the register in the PHY.\r
162  *  data        Pointer to storage for the Data to be read\r
163  *              from the PHY register (passed by reference)\r
164  *\r
165  * Return Values:\r
166  *  0 on failure\r
167  *  1 on success.\r
168  *\r
169  * Please refer to your PHY manual for registers and their meanings.\r
170  * mii_read() polls for the FEC's MII interrupt event and clears it.\r
171  * If after a suitable amount of time the event isn't triggered, a\r
172  * value of 0 is returned.\r
173  */\r
174 static int fec_mii_read( int phy_addr, int reg_addr, unsigned portSHORT* data )\r
175 {\r
176 int timeout, iReturn;\r
177 uint32 eimr;\r
178 \r
179     /* Clear the MII interrupt bit */\r
180     MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
181 \r
182     /* Mask the MII interrupt */\r
183     eimr = MCF_FEC_EIMR;\r
184     MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;\r
185 \r
186     /* Write to the MII Management Frame Register to kick-off the MII read */\r
187     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
188 \r
189     /* Poll for the MII interrupt (interrupt should be masked) */\r
190     for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )\r
191     {\r
192         if (MCF_FEC_EIR & MCF_FEC_EIR_MII)\r
193         {\r
194             break;\r
195         }\r
196         else\r
197         {\r
198                 vTaskDelay( fecMII_DELAY );\r
199         }\r
200     }\r
201 \r
202     if( timeout == fecMAX_POLLS )\r
203     {\r
204         iReturn = 0;\r
205     }\r
206     else\r
207     {\r
208                 *data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF);\r
209                 iReturn = 1;\r
210     }\r
211 \r
212         /* Clear the MII interrupt bit */\r
213         MCF_FEC_EIR = MCF_FEC_EIR_MII;\r
214 \r
215         /* Restore the EIMR */\r
216         MCF_FEC_EIMR = eimr;\r
217 \r
218     return iReturn;\r
219 }\r
220 \r
221 \r
222 /********************************************************************/\r
223 /*\r
224  * Generate the hash table settings for the given address\r
225  *\r
226  * Parameters:\r
227  *  addr    48-bit (6 byte) Address to generate the hash for\r
228  *\r
229  * Return Value:\r
230  *  The 6 most significant bits of the 32-bit CRC result\r
231  */\r
232 static unsigned portCHAR fec_hash_address( const unsigned portCHAR* addr )\r
233 {\r
234 unsigned portLONG crc;\r
235 unsigned portCHAR byte;\r
236 int i, j;\r
237 \r
238         crc = 0xFFFFFFFF;\r
239         for(i=0; i<6; ++i)\r
240         {\r
241                 byte = addr[i];\r
242                 for(j=0; j<8; ++j)\r
243                 {\r
244                         if((byte & 0x01)^(crc & 0x01))\r
245                         {\r
246                                 crc >>= 1;\r
247                                 crc = crc ^ 0xEDB88320;\r
248                         }\r
249                         else\r
250                         {\r
251                                 crc >>= 1;\r
252                         }\r
253 \r
254                         byte >>= 1;\r
255                 }\r
256         }\r
257 \r
258         return (unsigned portCHAR)(crc >> 26);\r
259 }\r
260 \r
261 /********************************************************************/\r
262 /*\r
263  * Set the Physical (Hardware) Address and the Individual Address\r
264  * Hash in the selected FEC\r
265  *\r
266  * Parameters:\r
267  *  ch  FEC channel\r
268  *  pa  Physical (Hardware) Address for the selected FEC\r
269  */\r
270 static void fec_set_address( const unsigned portCHAR *pa )\r
271 {\r
272         unsigned portCHAR crc;\r
273 \r
274         /*\r
275         * Set the Physical Address\r
276         */\r
277         /* Set the source address for the controller */\r
278         MCF_FEC_PALR = ( pa[ 0 ] << 24 ) | ( pa[ 1 ] << 16 ) | ( pa[ 2 ] << 8 ) | ( pa[ 3 ] << 0 );\r
279         MCF_FEC_PAUR = ( pa[ 4 ] << 24 ) | ( pa[ 5 ] << 16 );\r
280 \r
281         /*\r
282         * Calculate and set the hash for given Physical Address\r
283         * in the  Individual Address Hash registers\r
284         */\r
285         crc = fec_hash_address( pa );\r
286         if( crc >= 32 )\r
287         {\r
288                 MCF_FEC_IAUR |= (unsigned portLONG)(1 << (crc - 32));\r
289         }\r
290         else\r
291         {\r
292                 MCF_FEC_IALR |= (unsigned portLONG)(1 << crc);\r
293         }\r
294 }\r
295 /*-----------------------------------------------------------*/\r
296 \r
297 static void prvInitialiseFECBuffers( void )\r
298 {\r
299 unsigned portBASE_TYPE ux;\r
300 unsigned portCHAR *pcBufPointer;\r
301 \r
302         pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );\r
303         while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
304         {\r
305                 pcBufPointer++;\r
306         }\r
307 \r
308         xFECTxDescriptors = ( FECBD * ) pcBufPointer;\r
309 \r
310         pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );\r
311         while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
312         {\r
313                 pcBufPointer++;\r
314         }\r
315 \r
316         xFECRxDescriptors = ( FECBD * ) pcBufPointer;\r
317 \r
318 \r
319         /* Setup the buffers and descriptors.  The data member does not point\r
320         anywhere yet as there is not yet anything to send and a zero copy policy\r
321         is used. */
322         for( ux = 0; ux < configNUM_FEC_TX_BUFFERS; ux++ )\r
323         {\r
324                 xFECTxDescriptors[ ux ].status = TX_BD_TC;\r
325                 xFECTxDescriptors[ ux ].data = NULL;\r
326                 xFECTxDescriptors[ ux ].length = 0;\r
327         }\r
328 \r
329         pcBufPointer = &( ucFECRxBuffers[ 0 ] );\r
330         while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
331         {\r
332                 pcBufPointer++;\r
333         }\r
334 \r
335         for( ux = 0; ux < configNUM_FEC_RX_BUFFERS; ux++ )\r
336         {\r
337             xFECRxDescriptors[ ux ].status = RX_BD_E;\r
338             xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;\r
339             xFECRxDescriptors[ ux ].data = pcBufPointer;\r
340             pcBufPointer += configFEC_BUFFER_SIZE;\r
341         }\r
342 \r
343         /* Set the wrap bit in the last descriptors to form a ring. */\r
344         xFECTxDescriptors[ configNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;\r
345         xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;\r
346 \r
347         uxNextRxBuffer = 0;\r
348         uxNextTxBuffer = 0;\r
349 }\r
350 /*-----------------------------------------------------------*/\r
351 \r
352 void vInitFEC( void )\r
353 {\r
354 unsigned portSHORT usData;\r
355 struct uip_eth_addr xAddr;\r
356 const unsigned portCHAR ucMACAddress[6] =\r
357 {\r
358         configMAC_0, configMAC_1,configMAC_2, configMAC_3, configMAC_4, configMAC_5\r
359 };\r
360 \r
361         /* Create the semaphore used by the ISR to wake the uIP task. */\r
362         vSemaphoreCreateBinary( xFECSemaphore );\r
363 \r
364         prvInitialiseFECBuffers();\r
365 \r
366         for( usData = 0; usData < 6; usData++ )\r
367         {\r
368                 xAddr.addr[ usData ] = ucMACAddress[ usData ];\r
369         }\r
370         uip_setethaddr( xAddr );\r
371 \r
372         /* Set the Reset bit and clear the Enable bit */\r
373         MCF_FEC_ECR = MCF_FEC_ECR_RESET;\r
374 \r
375         /* Wait at least 8 clock cycles */\r
376         for( usData = 0; usData < 10; usData++ )\r
377         {\r
378                 asm( "NOP" );\r
379         }\r
380 \r
381         /* Set MII speed to 2.5MHz. */\r
382         MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 ) );\r
383 \r
384         /* Initialize PLDPAR to enable Ethernet LEDs. */\r
385         MCF_GPIO_PLDPAR =  MCF_GPIO_PLDPAR_ACTLED_ACTLED | MCF_GPIO_PLDPAR_LINKLED_LINKLED | MCF_GPIO_PLDPAR_SPDLED_SPDLED\r
386                                          | MCF_GPIO_PLDPAR_DUPLED_DUPLED | MCF_GPIO_PLDPAR_COLLED_COLLED | MCF_GPIO_PLDPAR_RXLED_RXLED\r
387                                          | MCF_GPIO_PLDPAR_TXLED_TXLED;\r
388 \r
389         /* Initialize Port TA to enable Axcel control. */\r
390         MCF_GPIO_PTAPAR = 0x00;\r
391         MCF_GPIO_DDRTA  = 0x0F;\r
392         MCF_GPIO_PORTTA = 0x04;\r
393 \r
394         /* Set phy address to zero. */\r
395         MCF_EPHY_EPHYCTL1 = MCF_EPHY_EPHYCTL1_PHYADD( 0 );\r
396 \r
397         /* Enable EPHY module with PHY clocks disabled.  Do not turn on PHY clocks\r
398         until both FEC and EPHY are completely setup (see Below). */\r
399         MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10);\r
400 \r
401         /* Enable auto_neg at start-up */\r
402         MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & (MCF_EPHY_EPHYCTL0_ANDIS));\r
403 \r
404         /* Enable EPHY module. */\r
405         MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_EPHYEN | MCF_EPHY_EPHYCTL0);\r
406 \r
407         /* Let PHY PLLs be determined by PHY. */\r
408         MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0  & ~(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10));\r
409 \r
410         /* Settle. */\r
411         vTaskDelay( fecLINK_DELAY );\r
412 \r
413         /* Can we talk to the PHY? */\r
414         do\r
415         {\r
416                 vTaskDelay( fecLINK_DELAY );\r
417                 usData = 0;\r
418                 fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );\r
419 \r
420         } while( usData == 0xffff );\r
421 \r
422         do\r
423         {\r
424                 /* Start auto negotiate. */\r
425                 fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
426 \r
427                 /* Wait for auto negotiate to complete. */\r
428                 do\r
429                 {\r
430                         vTaskDelay( fecLINK_DELAY );\r
431                         fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );\r
432 \r
433                 } while( !( usData & PHY_BMSR_AN_COMPLETE ) );\r
434 \r
435         } while( 0 ); //while( !( usData & PHY_BMSR_LINK ) );\r
436 \r
437         /* When we get here we have a link - find out what has been negotiated. */\r
438         fec_mii_read( configPHY_ADDRESS, PHY_ANLPAR, &usData );\r
439 \r
440         if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_100BTX ) )\r
441         {\r
442                 /* Speed is 100. */\r
443         }\r
444         else\r
445         {\r
446                 /* Speed is 10. */\r
447         }\r
448 \r
449         if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_10BTX_FDX ) )\r
450         {\r
451                 MCF_FEC_RCR &= (unsigned portLONG)~MCF_FEC_RCR_DRT;\r
452                 MCF_FEC_TCR |= MCF_FEC_TCR_FDEN;\r
453         }\r
454         else\r
455         {\r
456                 MCF_FEC_RCR |= MCF_FEC_RCR_DRT;\r
457                 MCF_FEC_TCR &= (unsigned portLONG)~MCF_FEC_TCR_FDEN;\r
458         }\r
459 \r
460         /* Clear the Individual and Group Address Hash registers */\r
461         MCF_FEC_IALR = 0;\r
462         MCF_FEC_IAUR = 0;\r
463         MCF_FEC_GALR = 0;\r
464         MCF_FEC_GAUR = 0;\r
465 \r
466         /* Set the Physical Address for the selected FEC */\r
467         fec_set_address( ucMACAddress );\r
468 \r
469         /* Set Rx Buffer Size */\r
470         MCF_FEC_EMRBR = (unsigned portSHORT)configFEC_BUFFER_SIZE;\r
471 \r
472         /* Point to the start of the circular Rx buffer descriptor queue */\r
473         MCF_FEC_ERDSR = ( volatile unsigned portLONG ) &( xFECRxDescriptors[ 0 ] );\r
474 \r
475         /* Point to the start of the circular Tx buffer descriptor queue */\r
476         MCF_FEC_ETSDR = ( volatile unsigned portLONG ) &( xFECTxDescriptors[ 0 ] );\r
477 \r
478         /* Mask all FEC interrupts */\r
479         MCF_FEC_EIMR = ( unsigned portLONG ) -1;\r
480 \r
481         /* Clear all FEC interrupt events */\r
482         MCF_FEC_EIR = ( unsigned portLONG ) -1;\r
483 \r
484         /* Initialize the Receive Control Register */\r
485         MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_FCE;\r
486 \r
487         MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;\r
488 \r
489         #if( configUSE_PROMISCUOUS_MODE == 1 )\r
490         {\r
491                 MCF_FEC_RCR |= MCF_FEC_RCR_PROM;\r
492         }\r
493         #endif\r
494 \r
495         prvEnableFECInterrupts();\r
496 \r
497         MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;\r
498         MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
499 }\r
500 /*-----------------------------------------------------------*/\r
501 \r
502 static void prvEnableFECInterrupts( void )\r
503 {\r
504 const unsigned portBASE_TYPE uxFirstFECVector = 23, uxLastFECVector = 35;\r
505 unsigned portBASE_TYPE ux;\r
506 \r
507 #if configFEC_INTERRUPT_PRIORITY > configMAX_SYSCALL_INTERRUPT_PRIORITY\r
508         #error configFEC_INTERRUPT_PRIORITY must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY\r
509 #endif\r
510 \r
511         for( ux = uxFirstFECVector; ux <= uxLastFECVector; ux++ )\r
512         {\r
513                 MCF_INTC0_ICR( ux ) = MCF_INTC_ICR_IL( configFEC_INTERRUPT_PRIORITY );\r
514         }\r
515 \r
516         /* Enable the FEC interrupts in the mask register */\r
517         MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );\r
518         MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27\r
519                                                 | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30\r
520                                                 | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL );\r
521 \r
522         /* Clear any pending FEC interrupt events */\r
523         MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;\r
524 \r
525         /* Unmask all FEC interrupts */\r
526         MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;\r
527 }\r
528 /*-----------------------------------------------------------*/\r
529 \r
530 unsigned short usGetFECRxData( void )\r
531 {\r
532 unsigned portSHORT usLen;\r
533 \r
534         /* Obtain the size of the packet and put it into the "len" variable. */\r
535         usLen = xFECRxDescriptors[ uxNextRxBuffer ].length;\r
536 \r
537         if( ( usLen != 0 ) && ( ( xFECRxDescriptors[ uxNextRxBuffer ].status & RX_BD_E ) == 0 ) )\r
538         {\r
539                 uip_buf = xFECRxDescriptors[ uxNextRxBuffer ].data;\r
540         }\r
541         else\r
542         {\r
543                 usLen = 0;\r
544         }\r
545 \r
546         return usLen;\r
547 }\r
548 /*-----------------------------------------------------------*/\r
549 \r
550 void vDiscardRxData( void )\r
551 {\r
552         /* Free the descriptor as the buffer it points to is no longer in use. */\r
553         xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;\r
554         MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
555         uxNextRxBuffer++;\r
556         if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )\r
557         {\r
558                 uxNextRxBuffer = 0;\r
559         }\r
560 }\r
561 /*-----------------------------------------------------------*/\r
562 \r
563 void vSendBufferToFEC( void )\r
564 {\r
565 portLONG l;\r
566 \r
567         /* Get a DMA buffer into which we can write the data to send. */\r
568         for( l = 0; l < fecMAX_TX_WAIT_ATTEMPTS; l++ )\r
569         {\r
570                 if( xFECTxDescriptors[ uxNextTxBuffer ].status & TX_BD_R )\r
571                 {\r
572                         /* Wait for the buffer to become available. */\r
573                         vTaskDelay( fecTX_BUFFER_WAIT );\r
574                 }\r
575                 else\r
576                 {\r
577                         /* Setup the buffer descriptor for transmission.  The data being\r
578                         sent is actually stored in one of the Rx descripter buffers,\r
579                         pointed to by uip_buf. */\r
580                         xFECTxDescriptors[ uxNextTxBuffer ].length = uip_len;\r
581                         xFECTxDescriptors[ uxNextTxBuffer ].status |= (TX_BD_R | TX_BD_L);\r
582                         xFECTxDescriptors[ uxNextTxBuffer ].data = uip_buf;\r
583 \r
584                         /* Continue the Tx DMA (in case it was waiting for a new TxBD) */\r
585                         MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;\r
586 \r
587                         /* Remember which Rx descriptor owns the buffer we are sending. */\r
588                         uxIndexToBufferOwner = uxNextRxBuffer;\r
589 \r
590                         uxNextTxBuffer++;\r
591                         if( uxNextTxBuffer >= configNUM_FEC_TX_BUFFERS )\r
592                         {\r
593                                 uxNextTxBuffer = 0;\r
594                         }\r
595 \r
596                         /* We have finished with this Rx descriptor now. */\r
597                         uxNextRxBuffer++;\r
598                         if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )\r
599                         {\r
600                                 uxNextRxBuffer = 0;\r
601                         }\r
602 \r
603                         break;\r
604                 }\r
605         }\r
606 }\r
607 /*-----------------------------------------------------------*/\r
608 \r
609 void vFEC_ISR( void )\r
610 {\r
611 unsigned portLONG ulEvent;\r
612 portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;\r
613 \r
614         ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;\r
615         MCF_FEC_EIR = ulEvent;\r
616 \r
617         if( ( ulEvent & MCF_FEC_EIR_RXB ) || ( ulEvent & MCF_FEC_EIR_RXF ) )\r
618         {\r
619                 /* A packet has been received.  Wake the handler task. */\r
620                 xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );\r
621         }\r
622 \r
623         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
624         {\r
625                 /* Sledge hammer error handling. */\r
626                 prvInitialiseFECBuffers();\r
627                 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
628         }\r
629 \r
630         if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )\r
631         {\r
632                 /* The buffer being sent is pointed to by an Rx descriptor, now the\r
633                 buffer has been sent we can mark the Rx descriptor as free again. */\r
634                 xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;\r
635                 MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
636         }\r
637 \r
638         portEND_SWITCHING_ISR( xHighPriorityTaskWoken );\r
639 }\r
640 /*-----------------------------------------------------------*/\r
641 \r
642 void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }\r
643 void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }\r
644 void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }\r
645 void __attribute__ ((interrupt)) __cs3_isr_interrupt_91( void ) { vFEC_ISR(); }\r
646 void __attribute__ ((interrupt)) __cs3_isr_interrupt_92( void ) { vFEC_ISR(); }\r
647 void __attribute__ ((interrupt)) __cs3_isr_interrupt_93( void ) { vFEC_ISR(); }\r
648 void __attribute__ ((interrupt)) __cs3_isr_interrupt_94( void ) { vFEC_ISR(); }\r
649 void __attribute__ ((interrupt)) __cs3_isr_interrupt_95( void ) { vFEC_ISR(); }\r
650 void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }\r
651 void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }\r
652 void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }\r
653 void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }\r
654 void __attribute__ ((interrupt)) __cs3_isr_interrupt_100( void ) { vFEC_ISR(); }\r
655 \r