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