]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ColdFire_MCF51CN128_CodeWarrior/Sources/FEC.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / ColdFire_MCF51CN128_CodeWarrior / Sources / FEC.c
1 /* Kernel includes. */\r
2 #include "FreeRTOS.h"\r
3 #include "semphr.h"\r
4 #include "task.h"\r
5 \r
6 /* Demo includes. */\r
7 #include "FEC.h"\r
8 #include "fecbd.h"\r
9 #include "mii.h"\r
10 #include "eth_phy.h"\r
11 #include "eth.h"\r
12 \r
13 /* uIP includes. */\r
14 #include "uip.h"\r
15 #include "uip_arp.h"\r
16 \r
17 /*-----------------------------------------------------------*/\r
18 \r
19 /* FEC hardware specifics. */\r
20 #define MCF_FEC_MSCR_MII_SPEED(x)                       (((x)&0x3F)<<0x1)\r
21 #define MCF_FEC_RDAR_R_DES_ACTIVE           ( 0x1000000 )\r
22 #define MCF_FEC_TDAR_X_DES_ACTIVE           ( 0x1000000 )\r
23 \r
24 /* PHY hardware specifics. */\r
25 #define PHY_STATUS                                                      ( 16 )\r
26 #define PHY_DUPLEX_STATUS                                       ( 4 )\r
27 \r
28 /* Delay between polling the PHY to see if a link has been established. */\r
29 #define fecLINK_DELAY                                           ( 500 / portTICK_PERIOD_MS )\r
30 \r
31 /* Very short delay to use when waiting for the Tx to finish with a buffer if\r
32 we run out of Rx buffers. */\r
33 #define fecMINIMAL_DELAY                                        ( 3 / portTICK_PERIOD_MS )\r
34 \r
35 /* Don't block to wait for a buffer more than this many times. */\r
36 #define uipBUFFER_WAIT_ATTEMPTS ( 30 )\r
37 \r
38 /* The Tx re-uses the Rx buffers and only has one descriptor. */\r
39 #define fecNUM_TX_DESCRIPTORS                           ( 1 )\r
40 \r
41 /* The total number of buffers available, which should be greater than the\r
42 number of Rx descriptors. */\r
43 #define fecNUM_BUFFERS                                          ( configNUM_FEC_RX_DESCRIPTORS + 2 )\r
44 \r
45 /*-----------------------------------------------------------*/\r
46 \r
47 /*\r
48  * Return an unused buffer to the pool of free buffers.\r
49  */\r
50 static void prvReturnBuffer( unsigned char *pucBuffer );\r
51 \r
52 /*\r
53  * Find and return the next buffer that is not in use by anything else.\r
54  */\r
55 static unsigned char *prvGetFreeBuffer( void );\r
56 /*-----------------------------------------------------------*/\r
57 \r
58 /* The semaphore used to wake the uIP task when data arrives. */\r
59 SemaphoreHandle_t xFECSemaphore = NULL;\r
60 \r
61 /* The buffer used by the uIP stack.  In this case the pointer is used to\r
62 point to one of the Rx buffers to avoid having to copy the Rx buffer into\r
63 the uIP buffer. */\r
64 unsigned char *uip_buf;\r
65 \r
66 /* The DMA descriptors.  These are char arrays to allow us to align them\r
67 correctly. */\r
68 static unsigned char xFECTxDescriptors_unaligned[ ( fecNUM_TX_DESCRIPTORS * sizeof( FECBD ) ) + 16 ];\r
69 static unsigned char xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_DESCRIPTORS * sizeof( FECBD ) ) + 16 ];\r
70 static FECBD *pxFECTxDescriptor;\r
71 static FECBD *xFECRxDescriptors;\r
72 \r
73 /* The DMA buffer.  This is a char arrays to allow it to be aligned correctly. */\r
74 static unsigned char ucFECRxBuffers[ ( fecNUM_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
75 \r
76 /* Index to the next descriptor to be inspected for received data. */\r
77 static unsigned long ulNextRxDescriptor = 0;\r
78 \r
79 /* Contains the start address of each Rx buffer, after it has been correctly\r
80 aligned. */\r
81 static unsigned char *pucAlignedBufferStartAddresses[ fecNUM_BUFFERS ] = { 0 };\r
82 \r
83 /* Each ucBufferInUse index corresponds to a position in the same index in the\r
84 pucAlignedBufferStartAddresses array.  If the index contains a 1 then the\r
85 buffer within pucAlignedBufferStartAddresses is in use, if it contains a 0 then\r
86 the buffer is free. */\r
87 static unsigned char ucBufferInUse[ fecNUM_BUFFERS ] = { 0 };\r
88 \r
89 /*-----------------------------------------------------------*/\r
90 \r
91 /********************************************************************/\r
92 /*\r
93  * Write a value to a PHY's MII register.\r
94  *\r
95  * Parameters:\r
96  *  ch          FEC channel\r
97  *  phy_addr    Address of the PHY.\r
98  *  reg_addr    Address of the register in the PHY.\r
99  *  data        Data to be written to the PHY register.\r
100  *\r
101  * Return Values:\r
102  *  0 on failure\r
103  *  1 on success.\r
104  *\r
105  * Please refer to your PHY manual for registers and their meanings.\r
106  * mii_write() polls for the FEC's MII interrupt event and clears it.\r
107  * If after a suitable amount of time the event isn't triggered, a\r
108  * value of 0 is returned.\r
109  */\r
110 static int fec_mii_write( int phy_addr, int reg_addr, int data )\r
111 {\r
112 int timeout;\r
113 unsigned long eimr;\r
114 \r
115         /* Clear the MII interrupt bit */\r
116         EIR = EIR_MII;\r
117 \r
118         /* Mask the MII interrupt */\r
119         eimr = EIMR;\r
120         EIMR &= ~EIMR_MII;\r
121 \r
122         /* Write to the MII Management Frame Register to kick-off the MII write */\r
123         MMFR = ( unsigned long ) ( FEC_MMFR_ST_01 | FEC_MMFR_OP_WRITE | FEC_MMFR_PA(phy_addr) | FEC_MMFR_RA(reg_addr) | FEC_MMFR_TA_10 | FEC_MMFR_DATA( data ) );\r
124 \r
125         /* Poll for the MII interrupt (interrupt should be masked) */\r
126         for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)\r
127         {\r
128                 if( EIR & EIR_MII)\r
129                 {\r
130                         break;\r
131                 }\r
132         }\r
133 \r
134         if( timeout == FEC_MII_TIMEOUT )\r
135         {\r
136                 return 0;\r
137         }\r
138 \r
139         /* Clear the MII interrupt bit */\r
140         EIR = EIR_MII;\r
141 \r
142         /* Restore the EIMR */\r
143         EIMR = eimr;\r
144 \r
145         return 1;\r
146 }\r
147 \r
148 /********************************************************************/\r
149 /*\r
150  * Read a value from a PHY's MII register.\r
151  *\r
152  * Parameters:\r
153  *  ch          FEC channel\r
154  *  phy_addr    Address of the PHY.\r
155  *  reg_addr    Address of the register in the PHY.\r
156  *  data        Pointer to storage for the Data to be read\r
157  *              from the PHY register (passed by reference)\r
158  *\r
159  * Return Values:\r
160  *  0 on failure\r
161  *  1 on success.\r
162  *\r
163  * Please refer to your PHY manual for registers and their meanings.\r
164  * mii_read() polls for the FEC's MII interrupt event and clears it.\r
165  * If after a suitable amount of time the event isn't triggered, a\r
166  * value of 0 is returned.\r
167  */\r
168 static int fec_mii_read( int phy_addr, int reg_addr, unsigned short* data )\r
169 {\r
170 int timeout;\r
171 unsigned long eimr;\r
172 \r
173         /* Clear the MII interrupt bit */\r
174         EIR = 0xffffffff;\r
175 \r
176         /* Mask the MII interrupt */\r
177         eimr = EIMR;\r
178         EIMR &= ~EIMR_MII;\r
179 \r
180         /* Write to the MII Management Frame Register to kick-off the MII read */\r
181         MMFR = ( unsigned long ) ( FEC_MMFR_ST_01 | FEC_MMFR_OP_READ | FEC_MMFR_PA(phy_addr) | FEC_MMFR_RA(reg_addr) | FEC_MMFR_TA_10 );\r
182 \r
183         /* Poll for the MII interrupt (interrupt should be masked) */\r
184         for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)\r
185         {\r
186                 if (EIR)\r
187                 {\r
188                         break;\r
189                 }\r
190         }\r
191 \r
192         if(timeout == FEC_MII_TIMEOUT)\r
193         {\r
194                 return 0;\r
195         }\r
196 \r
197         /* Clear the MII interrupt bit */\r
198         EIR = EIR_MII;\r
199 \r
200         /* Restore the EIMR */\r
201         EIMR = eimr;\r
202 \r
203         *data = (unsigned short)(MMFR & 0x0000FFFF);\r
204 \r
205         return 1;\r
206 }\r
207 \r
208 \r
209 /********************************************************************/\r
210 /*\r
211  * Generate the hash table settings for the given address\r
212  *\r
213  * Parameters:\r
214  *  addr    48-bit (6 byte) Address to generate the hash for\r
215  *\r
216  * Return Value:\r
217  *  The 6 most significant bits of the 32-bit CRC result\r
218  */\r
219 static unsigned char fec_hash_address( const unsigned char* addr )\r
220 {\r
221 unsigned long crc;\r
222 unsigned char byte;\r
223 int i, j;\r
224 \r
225         crc = 0xFFFFFFFF;\r
226         for(i=0; i<6; ++i)\r
227         {\r
228                 byte = addr[i];\r
229                 for(j=0; j<8; ++j)\r
230                 {\r
231                         if((byte & 0x01)^(crc & 0x01))\r
232                         {\r
233                                 crc >>= 1;\r
234                                 crc = crc ^ 0xEDB88320;\r
235                         }\r
236                         else\r
237                         {\r
238                                 crc >>= 1;\r
239                         }\r
240 \r
241                         byte >>= 1;\r
242                 }\r
243         }\r
244 \r
245         return (unsigned char)(crc >> 26);\r
246 }\r
247 \r
248 /********************************************************************/\r
249 /*\r
250  * Set the Physical (Hardware) Address and the Individual Address\r
251  * Hash in the selected FEC\r
252  *\r
253  * Parameters:\r
254  *  ch  FEC channel\r
255  *  pa  Physical (Hardware) Address for the selected FEC\r
256  */\r
257 static void fec_set_address( const unsigned char *pa )\r
258 {\r
259         unsigned char crc;\r
260 \r
261         /*\r
262         * Set the Physical Address\r
263         */\r
264         PALR = (unsigned long)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);\r
265         PAUR = (unsigned long)((pa[4]<<24) | (pa[5]<<16));\r
266 \r
267         /*\r
268         * Calculate and set the hash for given Physical Address\r
269         * in the  Individual Address Hash registers\r
270         */\r
271         crc = fec_hash_address(pa);\r
272         if(crc >= 32)\r
273         {\r
274                 IAUR |= (unsigned long)(1 << (crc - 32));\r
275         }\r
276         else\r
277         {\r
278                 IALR |= (unsigned long)(1 << crc);\r
279         }\r
280 }\r
281 /*-----------------------------------------------------------*/\r
282 \r
283 static void prvInitialiseFECBuffers( void )\r
284 {\r
285 unsigned portBASE_TYPE ux;\r
286 unsigned char *pcBufPointer;\r
287 \r
288         /* Set the pointer to a correctly aligned address. */\r
289         pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );\r
290         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
291         {\r
292                 pcBufPointer++;\r
293         }\r
294 \r
295         pxFECTxDescriptor = ( FECBD * ) pcBufPointer;\r
296 \r
297         /* Likewise the pointer to the Rx descriptor. */\r
298         pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );\r
299         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
300         {\r
301                 pcBufPointer++;\r
302         }\r
303 \r
304         xFECRxDescriptors = ( FECBD * ) pcBufPointer;\r
305 \r
306         /* There is no Tx buffer as the Rx buffer is reused. */\r
307         pxFECTxDescriptor->length = 0;\r
308         pxFECTxDescriptor->status = 0;\r
309 \r
310         /* Align the Rx buffers. */\r
311         pcBufPointer = &( ucFECRxBuffers[ 0 ] );\r
312         while( ( ( unsigned long ) pcBufPointer & 0x0fUL ) != 0 )\r
313         {\r
314                 pcBufPointer++;\r
315         }\r
316 \r
317         /* Then fill in the Rx descriptors. */\r
318         for( ux = 0; ux < configNUM_FEC_RX_DESCRIPTORS; ux++ )\r
319         {\r
320             xFECRxDescriptors[ ux ].status = RX_BD_E;\r
321             xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;\r
322             xFECRxDescriptors[ ux ].data = pcBufPointer;\r
323 \r
324                 /* Note the start address of the buffer now that it is correctly\r
325                 aligned. */\r
326                 pucAlignedBufferStartAddresses[ ux ] = pcBufPointer;\r
327 \r
328                 /* The buffer is in use by the descriptor. */\r
329                 ucBufferInUse[ ux ] = pdTRUE;\r
330 \r
331             pcBufPointer += configFEC_BUFFER_SIZE;\r
332         }\r
333 \r
334         /* Note the start address of the last buffer as one more buffer is\r
335         allocated than there are Rx descriptors. */\r
336         pucAlignedBufferStartAddresses[ ux ] = pcBufPointer;\r
337 \r
338         /* Set uip_buf to point to the last buffer. */\r
339         uip_buf = pcBufPointer;\r
340         ucBufferInUse[ ux ] = pdTRUE;\r
341 \r
342         /* Set the wrap bit in the last descriptors to form a ring. */\r
343         xFECRxDescriptors[ configNUM_FEC_RX_DESCRIPTORS - 1 ].status |= RX_BD_W;\r
344 \r
345         /* We start with descriptor 0. */\r
346         ulNextRxDescriptor = 0;\r
347 }\r
348 /*-----------------------------------------------------------*/\r
349 \r
350 void vInitFEC( void )\r
351 {\r
352 unsigned short usData;\r
353 struct uip_eth_addr xAddr;\r
354 const unsigned char ucMACAddress[6] =\r
355 {\r
356         configMAC_0, configMAC_1,configMAC_2,configMAC_3,configMAC_4,configMAC_5\r
357 };\r
358 \r
359         prvInitialiseFECBuffers();\r
360 \r
361         /* Create the semaphore used to wake the uIP task when data arrives. */\r
362         vSemaphoreCreateBinary( xFECSemaphore );\r
363 \r
364         /* Set the MAC address within the stack. */\r
365         for( usData = 0; usData < 6; usData++ )\r
366         {\r
367                 xAddr.addr[ usData ] = ucMACAddress[ usData ];\r
368         }\r
369         uip_setethaddr( xAddr );\r
370 \r
371         /* Set the Reset bit and clear the Enable bit */\r
372         ECR_RESET = 1;\r
373 \r
374         /* Enable the clock. */\r
375         SCGC4 |= SCGC4_FEC_MASK;\r
376 \r
377         /* Wait at least 8 clock cycles */\r
378         for( usData = 0; usData < 10; usData++ )\r
379         {\r
380                 asm( "NOP" );\r
381         }\r
382 \r
383         /* Set MII speed to 2.5MHz. */\r
384         MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 );\r
385 \r
386         /*\r
387          * Make sure the external interface signals are enabled\r
388          */\r
389     PTCPF2_C0 = 1;\r
390     PTCPF2_C1 = 1;\r
391     PTCPF2_C2 = 1;\r
392     PTAPF1 = 0x55;\r
393     PTAPF2 = 0x55;\r
394     PTBPF1 = 0x55;\r
395     PTBPF2 = 0x55;\r
396 \r
397     /* Set all pins to full drive with no filter. */\r
398     PTADS = 0x06;\r
399     PTAIFE = 0x06;\r
400     PTBDS = 0xf4;\r
401     PTBIFE = 0xf4;\r
402     PTCDS = 0;\r
403     PTCIFE = 0;\r
404 \r
405 \r
406         /* Can we talk to the PHY? */\r
407         do\r
408         {\r
409                 vTaskDelay( fecLINK_DELAY );\r
410                 usData = 0xffff;\r
411                 fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );\r
412 \r
413         } while( usData == 0xffff );\r
414 \r
415         /* Start auto negotiate. */\r
416         fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );\r
417 \r
418         /* Wait for auto negotiate to complete. */\r
419         do\r
420         {\r
421                 vTaskDelay( fecLINK_DELAY );\r
422                 fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );\r
423 \r
424         } while( !( usData & PHY_BMSR_AN_COMPLETE ) );\r
425 \r
426         /* When we get here we have a link - find out what has been negotiated. */\r
427         usData = 0;\r
428         fec_mii_read( configPHY_ADDRESS, PHY_STATUS, &usData );\r
429 \r
430         /* Setup half or full duplex. */\r
431         if( usData & PHY_DUPLEX_STATUS )\r
432         {\r
433                 RCR &= (unsigned long)~RCR_DRT;\r
434                 TCR |= TCR_FDEN;\r
435         }\r
436         else\r
437         {\r
438                 RCR |= RCR_DRT;\r
439                 TCR &= (unsigned long)~TCR_FDEN;\r
440         }\r
441 \r
442         /* Clear the Individual and Group Address Hash registers */\r
443         IALR = 0;\r
444         IAUR = 0;\r
445         GALR = 0;\r
446         GAUR = 0;\r
447 \r
448         /* Set the Physical Address for the selected FEC */\r
449         fec_set_address( ucMACAddress );\r
450 \r
451         /* Set Rx Buffer Size */\r
452         EMRBR = (unsigned short) configFEC_BUFFER_SIZE;\r
453 \r
454         /* Point to the start of the circular Rx buffer descriptor queue */\r
455         ERDSR = ( volatile unsigned long ) &( xFECRxDescriptors[ 0 ] );\r
456 \r
457         /* Point to the start of the circular Tx buffer descriptor queue */\r
458         ETSDR = ( volatile unsigned long ) pxFECTxDescriptor;\r
459 \r
460         /* Clear all FEC interrupt events */\r
461         EIR = ( unsigned long ) -1;\r
462 \r
463         /* Various mode/status setup. */\r
464         RCR = 0;\r
465         RCR_MAX_FL = configFEC_BUFFER_SIZE;\r
466         RCR_MII_MODE = 1;\r
467 \r
468         #if( configUSE_PROMISCUOUS_MODE == 1 )\r
469         {\r
470                 RCR |= RCR_PROM;\r
471         }\r
472         #endif\r
473 \r
474         /* Enable interrupts. */\r
475         EIMR = EIR_TXF_MASK | EIMR_RXF_MASK | EIMR_RXB_MASK | EIMR_UN_MASK | EIMR_RL_MASK | EIMR_LC_MASK | EIMR_BABT_MASK | EIMR_BABR_MASK | EIMR_HBERR_MASK;\r
476 \r
477         /* Enable the MAC itself. */\r
478     ECR = ECR_ETHER_EN_MASK;\r
479 \r
480     /* Indicate that there have been empty receive buffers produced */\r
481     RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
482 }\r
483 /*-----------------------------------------------------------*/\r
484 \r
485 unsigned long ulFECRx( void )\r
486 {\r
487 unsigned long ulLen = 0UL;\r
488 \r
489         /* Is a buffer ready? */\r
490         if( ( xFECRxDescriptors[ ulNextRxDescriptor ].status & RX_BD_E ) == 0 )\r
491         {\r
492                 /* uip_buf is about to be set to a new buffer, so return the buffer it\r
493                 is already pointing to. */\r
494                 prvReturnBuffer( uip_buf );\r
495 \r
496                 /* Obtain the size of the packet and put it into the "len" variable. */\r
497                 ulLen = xFECRxDescriptors[ ulNextRxDescriptor ].length;\r
498                 uip_buf = xFECRxDescriptors[ ulNextRxDescriptor ].data;\r
499 \r
500                 /* The buffer that this descriptor was using is now in use by the\r
501                 TCP/IP stack, so allocate it a new buffer. */\r
502                 xFECRxDescriptors[ ulNextRxDescriptor ].data = prvGetFreeBuffer();\r
503 \r
504                 /* Doing this here could cause corruption! */\r
505                 xFECRxDescriptors[ ulNextRxDescriptor ].status |= RX_BD_E;\r
506 \r
507                 portENTER_CRITICAL();\r
508                 {\r
509                         ulNextRxDescriptor++;\r
510                         if( ulNextRxDescriptor >= configNUM_FEC_RX_DESCRIPTORS )\r
511                         {\r
512                                 ulNextRxDescriptor = 0;\r
513                         }\r
514                 }\r
515                 portEXIT_CRITICAL();\r
516 \r
517                 /* Tell the DMA a new buffer is available. */\r
518                 RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
519         }\r
520 \r
521     return ulLen;\r
522 }\r
523 /*-----------------------------------------------------------*/\r
524 \r
525 void vFECTx( void )\r
526 {\r
527         /* When we get here the Tx descriptor should show as having completed. */\r
528         while( pxFECTxDescriptor->status & TX_BD_R )\r
529         {\r
530                 vTaskDelay( fecMINIMAL_DELAY );\r
531         }\r
532 \r
533         portENTER_CRITICAL();\r
534         {\r
535                 /* To maintain the zero copy implementation, point the Tx descriptor\r
536                 to the data from the Rx buffer. */\r
537                 pxFECTxDescriptor->data = uip_buf;\r
538 \r
539                 /* Setup the buffer descriptor for transmission */\r
540                 pxFECTxDescriptor->length = uip_len;\r
541 \r
542                 /* NB this assumes only one Tx descriptor! */\r
543                 pxFECTxDescriptor->status = ( TX_BD_R | TX_BD_L | TX_BD_TC | TX_BD_W );\r
544         }\r
545         portEXIT_CRITICAL();\r
546 \r
547         /* Continue the Tx DMA task (in case it was waiting for a new TxBD) */\r
548         TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;\r
549 \r
550         /* uip_buf is being used by the Tx descriptor.  Allocate a new buffer to\r
551         uip_buf. */\r
552         uip_buf = prvGetFreeBuffer();\r
553 }\r
554 /*-----------------------------------------------------------*/\r
555 \r
556 static void prvReturnBuffer( unsigned char *pucBuffer )\r
557 {\r
558 unsigned long ul;\r
559 \r
560         /* Mark a buffer as free for use. */\r
561         for( ul = 0; ul < fecNUM_BUFFERS; ul++ )\r
562         {\r
563                 if( pucAlignedBufferStartAddresses[ ul ] == pucBuffer )\r
564                 {\r
565                         ucBufferInUse[ ul ] = pdFALSE;\r
566                         break;\r
567                 }\r
568         }\r
569 }\r
570 /*-----------------------------------------------------------*/\r
571 \r
572 static unsigned char *prvGetFreeBuffer( void )\r
573 {\r
574 portBASE_TYPE x;\r
575 unsigned char *pucReturn = NULL;\r
576 unsigned long ulAttempts = 0;\r
577 \r
578         while( pucReturn == NULL )\r
579         {\r
580                 /* Look through the buffers to find one that is not in use by\r
581                 anything else. */\r
582                 for( x = 0; x < fecNUM_BUFFERS; x++ )\r
583                 {\r
584                         if( ucBufferInUse[ x ] == pdFALSE )\r
585                         {\r
586                                 ucBufferInUse[ x ] = pdTRUE;\r
587                                 pucReturn = pucAlignedBufferStartAddresses[ x ];\r
588                                 break;\r
589                         }\r
590                 }\r
591 \r
592                 /* Was a buffer found? */\r
593                 if( pucReturn == NULL )\r
594                 {\r
595                         ulAttempts++;\r
596 \r
597                         if( ulAttempts >= uipBUFFER_WAIT_ATTEMPTS )\r
598                         {\r
599                                 break;\r
600                         }\r
601 \r
602                         /* Wait then look again. */\r
603                         vTaskDelay( fecMINIMAL_DELAY );\r
604                 }\r
605         }\r
606 \r
607         return pucReturn;\r
608 }\r
609 /*-----------------------------------------------------------*/\r
610 \r
611 void interrupt 86 vFECISRHandler( void )\r
612 {\r
613 unsigned long ulEvent;\r
614 portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;\r
615 \r
616         /* Determine the cause of the interrupt. */\r
617         ulEvent = EIR & EIMR;\r
618         EIR = ulEvent;\r
619 \r
620         if( ulEvent & EIR_RXF_MASK )\r
621         {\r
622                 /* A packet has been received.  Wake the handler task in case it is\r
623                 blocked. */\r
624                 xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );\r
625         }\r
626 \r
627         if( ulEvent & EIR_TXF_MASK )\r
628         {\r
629                 /* The Tx has completed.  Mark the buffer it was using as free again. */\r
630                 prvReturnBuffer( pxFECTxDescriptor->data );\r
631                 pxFECTxDescriptor->data = NULL;\r
632         }\r
633 \r
634         if (ulEvent & ( EIR_UN_MASK | EIR_RL_MASK | EIR_LC_MASK | EIR_EBERR_MASK | EIR_BABT_MASK | EIR_BABR_MASK | EIR_HBERR_MASK ) )\r
635         {\r
636                 /* Sledge hammer error handling. */\r
637                 prvInitialiseFECBuffers();\r
638                 RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
639         }\r
640 \r
641         portEND_SWITCHING_ISR( xHighPriorityTaskWoken );\r
642 }\r