OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [ColdFire_MCF52233_Eclipse/] [RTOSDemo/] [webserver/] [FEC.c] - Blame information for rev 578

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
/* Kernel includes. */
55
#include "FreeRTOS.h"
56
#include "semphr.h"
57
#include "task.h"
58
 
59
/* Hardware includes. */
60
#include "fecbd.h"
61
#include "mii.h"
62
#include "eth_phy.h"
63
#include "eth.h"
64
 
65
/* uIP includes. */
66
#include "uip.h"
67
#include "uip_arp.h"
68
 
69
/* Delay between polling the PHY to see if a link has been established. */
70
#define fecLINK_DELAY                                                   ( 500 / portTICK_RATE_MS )
71
 
72
/* Delay to wait for an MII access. */
73
#define fecMII_DELAY                                                    ( 10 / portTICK_RATE_MS )
74
#define fecMAX_POLLS                                                    ( 20 )
75
 
76
/* Constants used to delay while waiting for a tx descriptor to be free. */
77
#define fecMAX_WAIT_FOR_TX_BUFFER                                               ( 200 / portTICK_RATE_MS )
78
 
79
/* We only use a single Tx descriptor which can lead to Txed packets being sent
80
twice (due to a bug in the FEC silicon).  However, in this case the bug is used
81
to our advantage in that it means the uip-split mechanism is not required. */
82
#define fecNUM_FEC_TX_BUFFERS                                   ( 1 )
83
#define fecTX_BUFFER_TO_USE                                             ( 0 )
84
/*-----------------------------------------------------------*/
85
 
86
/* The semaphore used to wake the uIP task when data arrives. */
87
xSemaphoreHandle xFECSemaphore = NULL, xTxSemaphore = NULL;
88
 
89
/* The buffer used by the uIP stack.  In this case the pointer is used to
90
point to one of the Rx buffers to effect a zero copy policy. */
91
unsigned portCHAR *uip_buf;
92
 
93
/* The DMA descriptors.  This is a char array to allow us to align it correctly. */
94
static unsigned portCHAR xFECTxDescriptors_unaligned[ ( fecNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];
95
static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];
96
static FECBD *xFECTxDescriptors;
97
static FECBD *xFECRxDescriptors;
98
 
99
/* The DMA buffers.  These are char arrays to allow them to be aligned correctly. */
100
static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];
101
static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxIndexToBufferOwner = 0;
102
 
103
/*-----------------------------------------------------------*/
104
 
105
/*
106
 * Enable all the required interrupts in the FEC and in the interrupt controller.
107
 */
108
static void prvEnableFECInterrupts( void );
109
 
110
/*
111
 * Reset the FEC if we get into an unrecoverable state.
112
 */
113
static void prvResetFEC( portBASE_TYPE xCalledFromISR );
114
 
115
/********************************************************************/
116
 
117
/*
118
 * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE
119
 *
120
 * Write a value to a PHY's MII register.
121
 *
122
 * Parameters:
123
 *  ch          FEC channel
124
 *  phy_addr    Address of the PHY.
125
 *  reg_addr    Address of the register in the PHY.
126
 *  data        Data to be written to the PHY register.
127
 *
128
 * Return Values:
129
 *  0 on failure
130
 *  1 on success.
131
 *
132
 * Please refer to your PHY manual for registers and their meanings.
133
 * mii_write() polls for the FEC's MII interrupt event and clears it.
134
 * If after a suitable amount of time the event isn't triggered, a
135
 * value of 0 is returned.
136
 */
137
static int fec_mii_write( int phy_addr, int reg_addr, int data )
138
{
139
int timeout, iReturn;
140
uint32 eimr;
141
 
142
    /* Clear the MII interrupt bit */
143
    MCF_FEC_EIR = MCF_FEC_EIR_MII;
144
 
145
    /* Mask the MII interrupt */
146
    eimr = MCF_FEC_EIMR;
147
    MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
148
 
149
    /* Write to the MII Management Frame Register to kick-off the MII write */
150
    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 );
151
 
152
    /* Poll for the MII interrupt (interrupt should be masked) */
153
    for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
154
    {
155
        if( MCF_FEC_EIR & MCF_FEC_EIR_MII )
156
        {
157
                        break;
158
        }
159
        else
160
        {
161
                vTaskDelay( fecMII_DELAY );
162
        }
163
    }
164
 
165
    if( timeout == fecMAX_POLLS )
166
    {
167
        iReturn = 0;
168
    }
169
    else
170
    {
171
                iReturn = 1;
172
    }
173
 
174
        /* Clear the MII interrupt bit */
175
        MCF_FEC_EIR = MCF_FEC_EIR_MII;
176
 
177
        /* Restore the EIMR */
178
        MCF_FEC_EIMR = eimr;
179
 
180
    return iReturn;
181
}
182
 
183
/********************************************************************/
184
/*
185
 * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE
186
 *
187
 * Read a value from a PHY's MII register.
188
 *
189
 * Parameters:
190
 *  ch          FEC channel
191
 *  phy_addr    Address of the PHY.
192
 *  reg_addr    Address of the register in the PHY.
193
 *  data        Pointer to storage for the Data to be read
194
 *              from the PHY register (passed by reference)
195
 *
196
 * Return Values:
197
 *  0 on failure
198
 *  1 on success.
199
 *
200
 * Please refer to your PHY manual for registers and their meanings.
201
 * mii_read() polls for the FEC's MII interrupt event and clears it.
202
 * If after a suitable amount of time the event isn't triggered, a
203
 * value of 0 is returned.
204
 */
205
static int fec_mii_read( int phy_addr, int reg_addr, unsigned portSHORT* data )
206
{
207
int timeout, iReturn;
208
uint32 eimr;
209
 
210
    /* Clear the MII interrupt bit */
211
    MCF_FEC_EIR = MCF_FEC_EIR_MII;
212
 
213
    /* Mask the MII interrupt */
214
    eimr = MCF_FEC_EIMR;
215
    MCF_FEC_EIMR &= ~MCF_FEC_EIMR_MII;
216
 
217
    /* Write to the MII Management Frame Register to kick-off the MII read */
218
    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;
219
 
220
    /* Poll for the MII interrupt (interrupt should be masked) */
221
    for( timeout = 0; timeout < fecMAX_POLLS; timeout++ )
222
    {
223
        if (MCF_FEC_EIR & MCF_FEC_EIR_MII)
224
        {
225
            break;
226
        }
227
        else
228
        {
229
                vTaskDelay( fecMII_DELAY );
230
        }
231
    }
232
 
233
    if( timeout == fecMAX_POLLS )
234
    {
235
        iReturn = 0;
236
    }
237
    else
238
    {
239
                *data = (uint16)(MCF_FEC_MMFR & 0x0000FFFF);
240
                iReturn = 1;
241
    }
242
 
243
        /* Clear the MII interrupt bit */
244
        MCF_FEC_EIR = MCF_FEC_EIR_MII;
245
 
246
        /* Restore the EIMR */
247
        MCF_FEC_EIMR = eimr;
248
 
249
    return iReturn;
250
}
251
 
252
 
253
/********************************************************************/
254
/*
255
 * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE
256
 *
257
 * Generate the hash table settings for the given address
258
 *
259
 * Parameters:
260
 *  addr    48-bit (6 byte) Address to generate the hash for
261
 *
262
 * Return Value:
263
 *  The 6 most significant bits of the 32-bit CRC result
264
 */
265
static unsigned portCHAR fec_hash_address( const unsigned portCHAR* addr )
266
{
267
unsigned portLONG crc;
268
unsigned portCHAR byte;
269
int i, j;
270
 
271
        crc = 0xFFFFFFFF;
272
        for(i=0; i<6; ++i)
273
        {
274
                byte = addr[i];
275
                for(j=0; j<8; ++j)
276
                {
277
                        if((byte & 0x01)^(crc & 0x01))
278
                        {
279
                                crc >>= 1;
280
                                crc = crc ^ 0xEDB88320;
281
                        }
282
                        else
283
                        {
284
                                crc >>= 1;
285
                        }
286
 
287
                        byte >>= 1;
288
                }
289
        }
290
 
291
        return (unsigned portCHAR)(crc >> 26);
292
}
293
 
294
/********************************************************************/
295
/*
296
 * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE
297
 *
298
 * Set the Physical (Hardware) Address and the Individual Address
299
 * Hash in the selected FEC
300
 *
301
 * Parameters:
302
 *  ch  FEC channel
303
 *  pa  Physical (Hardware) Address for the selected FEC
304
 */
305
static void fec_set_address( const unsigned portCHAR *pa )
306
{
307
        unsigned portCHAR crc;
308
 
309
        /*
310
        * Set the Physical Address
311
        */
312
        /* Set the source address for the controller */
313
        MCF_FEC_PALR = ( pa[ 0 ] << 24 ) | ( pa[ 1 ] << 16 ) | ( pa[ 2 ] << 8 ) | ( pa[ 3 ] << 0 );
314
        MCF_FEC_PAUR = ( pa[ 4 ] << 24 ) | ( pa[ 5 ] << 16 );
315
 
316
        /*
317
        * Calculate and set the hash for given Physical Address
318
        * in the  Individual Address Hash registers
319
        */
320
        crc = fec_hash_address( pa );
321
        if( crc >= 32 )
322
        {
323
                MCF_FEC_IAUR |= (unsigned portLONG)(1 << (crc - 32));
324
        }
325
        else
326
        {
327
                MCF_FEC_IALR |= (unsigned portLONG)(1 << crc);
328
        }
329
}
330
/*-----------------------------------------------------------*/
331
 
332
static void prvInitialiseFECBuffers( void )
333
{
334
unsigned portBASE_TYPE ux;
335
unsigned portCHAR *pcBufPointer;
336
 
337
        /* Correctly align the Tx descriptor pointer. */
338
        pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );
339
        while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
340
        {
341
                pcBufPointer++;
342
        }
343
 
344
        xFECTxDescriptors = ( FECBD * ) pcBufPointer;
345
 
346
        /* Likewise the Rx descriptor pointer. */
347
        pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );
348
        while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
349
        {
350
                pcBufPointer++;
351
        }
352
 
353
        xFECRxDescriptors = ( FECBD * ) pcBufPointer;
354
 
355
 
356
        /* Setup the Tx buffers and descriptors.  There is no separate Tx buffer
357
        to point to (the Rx buffers are actually used) so the data member is
358
        set to NULL for now. */
359
        for( ux = 0; ux < fecNUM_FEC_TX_BUFFERS; ux++ )
360
        {
361
                xFECTxDescriptors[ ux ].status = TX_BD_TC;
362
                xFECTxDescriptors[ ux ].data = NULL;
363
                xFECTxDescriptors[ ux ].length = 0;
364
        }
365
 
366
        /* Setup the Rx buffers and descriptors, having first ensured correct
367
        alignment. */
368
        pcBufPointer = &( ucFECRxBuffers[ 0 ] );
369
        while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
370
        {
371
                pcBufPointer++;
372
        }
373
 
374
        for( ux = 0; ux < configNUM_FEC_RX_BUFFERS; ux++ )
375
        {
376
            xFECRxDescriptors[ ux ].status = RX_BD_E;
377
            xFECRxDescriptors[ ux ].length = configFEC_BUFFER_SIZE;
378
            xFECRxDescriptors[ ux ].data = pcBufPointer;
379
            pcBufPointer += configFEC_BUFFER_SIZE;
380
        }
381
 
382
        /* Set the wrap bit in the last descriptors to form a ring. */
383
        xFECTxDescriptors[ fecNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;
384
        xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;
385
 
386
        uxNextRxBuffer = 0;
387
}
388
/*-----------------------------------------------------------*/
389
 
390
void vFECInit( void )
391
{
392
unsigned portSHORT usData;
393
struct uip_eth_addr xAddr;
394
unsigned portBASE_TYPE ux;
395
 
396
/* The MAC address is set at the foot of FreeRTOSConfig.h. */
397
const unsigned portCHAR ucMACAddress[6] =
398
{
399
        configMAC_0, configMAC_1,configMAC_2, configMAC_3, configMAC_4, configMAC_5
400
};
401
 
402
        /* Create the semaphore used by the ISR to wake the uIP task. */
403
        vSemaphoreCreateBinary( xFECSemaphore );
404
 
405
        /* Create the semaphore used to unblock any tasks that might be waiting
406
        for a Tx descriptor. */
407
        vSemaphoreCreateBinary( xTxSemaphore );
408
 
409
        /* Initialise all the buffers and descriptors used by the DMA. */
410
        prvInitialiseFECBuffers();
411
 
412
        for( usData = 0; usData < 6; usData++ )
413
        {
414
                xAddr.addr[ usData ] = ucMACAddress[ usData ];
415
        }
416
        uip_setethaddr( xAddr );
417
 
418
        /* Set the Reset bit and clear the Enable bit */
419
        MCF_FEC_ECR = MCF_FEC_ECR_RESET;
420
 
421
        /* Wait at least 8 clock cycles */
422
        for( usData = 0; usData < 10; usData++ )
423
        {
424
                asm( "NOP" );
425
        }
426
 
427
        /* Set MII speed to 2.5MHz. */
428
        MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( ( ( ( configCPU_CLOCK_HZ / 1000000 ) / 5 ) + 1 ) );
429
 
430
        /* Initialize PLDPAR to enable Ethernet LEDs. */
431
        MCF_GPIO_PLDPAR =  MCF_GPIO_PLDPAR_ACTLED_ACTLED | MCF_GPIO_PLDPAR_LINKLED_LINKLED | MCF_GPIO_PLDPAR_SPDLED_SPDLED
432
                                         | MCF_GPIO_PLDPAR_DUPLED_DUPLED | MCF_GPIO_PLDPAR_COLLED_COLLED | MCF_GPIO_PLDPAR_RXLED_RXLED
433
                                         | MCF_GPIO_PLDPAR_TXLED_TXLED;
434
 
435
        /* Initialize Port TA to enable Axcel control. */
436
        MCF_GPIO_PTAPAR = 0x00;
437
        MCF_GPIO_DDRTA  = 0x0F;
438
        MCF_GPIO_PORTTA = 0x04;
439
 
440
        /* Set phy address to zero. */
441
        MCF_EPHY_EPHYCTL1 = MCF_EPHY_EPHYCTL1_PHYADD( 0 );
442
 
443
        /* Enable EPHY module with PHY clocks disabled.  Do not turn on PHY clocks
444
        until both FEC and EPHY are completely setup (see Below). */
445
        MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10);
446
 
447
        /* Enable auto_neg at start-up */
448
        MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0 & (MCF_EPHY_EPHYCTL0_ANDIS));
449
 
450
        /* Enable EPHY module. */
451
        MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0_EPHYEN | MCF_EPHY_EPHYCTL0);
452
 
453
        /* Let PHY PLLs be determined by PHY. */
454
        MCF_EPHY_EPHYCTL0 = (uint8)(MCF_EPHY_EPHYCTL0  & ~(MCF_EPHY_EPHYCTL0_DIS100 | MCF_EPHY_EPHYCTL0_DIS10));
455
 
456
        /* Settle. */
457
        vTaskDelay( fecLINK_DELAY );
458
 
459
        /* Can we talk to the PHY? */
460
        do
461
        {
462
                vTaskDelay( fecLINK_DELAY );
463
                usData = 0;
464
                fec_mii_read( configPHY_ADDRESS, PHY_PHYIDR1, &usData );
465
 
466
        } while( usData == 0xffff );
467
 
468
        do
469
        {
470
                /* Start auto negotiate. */
471
                fec_mii_write( configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
472
 
473
                /* Wait for auto negotiate to complete. */
474
                do
475
                {
476
                        ux++;
477
                        if( ux > 10 )
478
                        {
479
                                /* Hardware bug workaround!  Force 100Mbps half duplex. */
480
                                while( !fec_mii_read( configPHY_ADDRESS, 0, &usData ) ){};
481
                                usData &= ~0x2000;                                                      /* 10Mbps */
482
                                usData &= ~0x0100;                                                      /* Half Duplex */
483
                                usData &= ~0x1000;                                                      /* Manual Mode */
484
                                while( !fec_mii_write( configPHY_ADDRESS, 0, usData ) ){};
485
                                while( !fec_mii_write( configPHY_ADDRESS, 0, (usData|0x0200) )){}; /* Force re-negotiate */
486
                                break;
487
                        }
488
                        vTaskDelay( fecLINK_DELAY );
489
                        fec_mii_read( configPHY_ADDRESS, PHY_BMSR, &usData );
490
 
491
                } while( !( usData & PHY_BMSR_AN_COMPLETE ) );
492
 
493
        } while( 0 ); //while( !( usData & PHY_BMSR_LINK ) );
494
 
495
        /* When we get here we have a link - find out what has been negotiated. */
496
        fec_mii_read( configPHY_ADDRESS, PHY_ANLPAR, &usData );
497
 
498
        if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_100BTX ) )
499
        {
500
                /* Speed is 100. */
501
        }
502
        else
503
        {
504
                /* Speed is 10. */
505
        }
506
 
507
        if( ( usData & PHY_ANLPAR_100BTX_FDX ) || ( usData & PHY_ANLPAR_10BTX_FDX ) )
508
        {
509
                MCF_FEC_RCR &= (unsigned portLONG)~MCF_FEC_RCR_DRT;
510
                MCF_FEC_TCR |= MCF_FEC_TCR_FDEN;
511
        }
512
        else
513
        {
514
                MCF_FEC_RCR |= MCF_FEC_RCR_DRT;
515
                MCF_FEC_TCR &= (unsigned portLONG)~MCF_FEC_TCR_FDEN;
516
        }
517
 
518
        /* Clear the Individual and Group Address Hash registers */
519
        MCF_FEC_IALR = 0;
520
        MCF_FEC_IAUR = 0;
521
        MCF_FEC_GALR = 0;
522
        MCF_FEC_GAUR = 0;
523
 
524
        /* Set the Physical Address for the selected FEC */
525
        fec_set_address( ucMACAddress );
526
 
527
        /* Set Rx Buffer Size */
528
        MCF_FEC_EMRBR = (unsigned portSHORT)configFEC_BUFFER_SIZE;
529
 
530
        /* Point to the start of the circular Rx buffer descriptor queue */
531
        MCF_FEC_ERDSR = ( volatile unsigned portLONG ) &( xFECRxDescriptors[ 0 ] );
532
 
533
        /* Point to the start of the circular Tx buffer descriptor queue */
534
        MCF_FEC_ETSDR = ( volatile unsigned portLONG ) &( xFECTxDescriptors[ 0 ] );
535
 
536
        /* Mask all FEC interrupts */
537
        MCF_FEC_EIMR = ( unsigned portLONG ) -1;
538
 
539
        /* Clear all FEC interrupt events */
540
        MCF_FEC_EIR = ( unsigned portLONG ) -1;
541
 
542
        /* Initialize the Receive Control Register */
543
        MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM) | MCF_FEC_RCR_FCE;
544
 
545
        MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;
546
 
547
        #if( configUSE_PROMISCUOUS_MODE == 1 )
548
        {
549
                MCF_FEC_RCR |= MCF_FEC_RCR_PROM;
550
        }
551
        #endif
552
 
553
        prvEnableFECInterrupts();
554
 
555
        /* Finally... enable. */
556
        MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
557
        MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
558
}
559
/*-----------------------------------------------------------*/
560
 
561
static void prvEnableFECInterrupts( void )
562
{
563
const unsigned portBASE_TYPE uxFirstFECVector = 23, uxLastFECVector = 35;
564
unsigned portBASE_TYPE ux;
565
 
566
#if configFEC_INTERRUPT_PRIORITY > configMAX_SYSCALL_INTERRUPT_PRIORITY
567
        #error configFEC_INTERRUPT_PRIORITY must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY
568
#endif
569
 
570
        /* Set the priority of each of the FEC interrupts. */
571
        for( ux = uxFirstFECVector; ux <= uxLastFECVector; ux++ )
572
        {
573
                MCF_INTC0_ICR( ux ) = MCF_INTC_ICR_IL( configFEC_INTERRUPT_PRIORITY );
574
        }
575
 
576
        /* Enable the FEC interrupts in the mask register */
577
        MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );
578
        MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27
579
                                                | MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30
580
                                                | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24
581
                                                | MCF_INTC_IMRL_MASKALL );
582
 
583
        /* Clear any pending FEC interrupt events */
584
        MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;
585
 
586
        /* Unmask all FEC interrupts */
587
        MCF_FEC_EIMR = MCF_FEC_EIMR_UNMASK_ALL;
588
}
589
/*-----------------------------------------------------------*/
590
 
591
static void prvResetFEC( portBASE_TYPE xCalledFromISR )
592
{
593
portBASE_TYPE x;
594
 
595
        /* A critical section is used unless this function is being called from
596
        an ISR. */
597
        if( xCalledFromISR == pdFALSE )
598
        {
599
                taskENTER_CRITICAL();
600
        }
601
 
602
        {
603
                /* Reset all buffers and descriptors. */
604
                prvInitialiseFECBuffers();
605
 
606
                /* Set the Reset bit and clear the Enable bit */
607
                MCF_FEC_ECR = MCF_FEC_ECR_RESET;
608
 
609
                /* Wait at least 8 clock cycles */
610
                for( x = 0; x < 10; x++ )
611
                {
612
                        asm( "NOP" );
613
                }
614
 
615
                /* Re-enable. */
616
                MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
617
                MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
618
        }
619
 
620
        if( xCalledFromISR == pdFALSE )
621
        {
622
                taskEXIT_CRITICAL();
623
        }
624
}
625
/*-----------------------------------------------------------*/
626
 
627
unsigned short usFECGetRxedData( void )
628
{
629
unsigned portSHORT usLen;
630
 
631
        /* Obtain the size of the packet and put it into the "len" variable. */
632
        usLen = xFECRxDescriptors[ uxNextRxBuffer ].length;
633
 
634
        if( ( usLen != 0 ) && ( ( xFECRxDescriptors[ uxNextRxBuffer ].status & RX_BD_E ) == 0 ) )
635
        {
636
                uip_buf = xFECRxDescriptors[ uxNextRxBuffer ].data;
637
        }
638
        else
639
        {
640
                usLen = 0;
641
        }
642
 
643
        return usLen;
644
}
645
/*-----------------------------------------------------------*/
646
 
647
void vFECRxProcessingCompleted( void )
648
{
649
        /* Free the descriptor as the buffer it points to is no longer in use. */
650
        xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;
651
        MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
652
        uxNextRxBuffer++;
653
        if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
654
        {
655
                uxNextRxBuffer = 0;
656
        }
657
}
658
/*-----------------------------------------------------------*/
659
 
660
void vFECSendData( void )
661
{
662
        /* Ensure no Tx frames are outstanding. */
663
        if( xSemaphoreTake( xTxSemaphore, fecMAX_WAIT_FOR_TX_BUFFER ) == pdPASS )
664
        {
665
                /* Get a DMA buffer into which we can write the data to send. */
666
                if( xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status & TX_BD_R )
667
                {
668
                        /*** ERROR didn't expect this.  Sledge hammer error handling. ***/
669
                        prvResetFEC( pdFALSE );
670
 
671
                        /* Make sure we leave the semaphore in the expected state as nothing
672
                        is being transmitted this will not happen in the Tx ISR. */
673
                        xSemaphoreGive( xTxSemaphore );
674
                }
675
                else
676
                {
677
                        /* Setup the buffer descriptor for transmission.  The data being
678
                        sent is actually stored in one of the Rx descriptor buffers,
679
                        pointed to by uip_buf. */
680
                        xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].length = uip_len;
681
                        xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status |= ( TX_BD_R | TX_BD_L );
682
                        xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].data = uip_buf;
683
 
684
                        /* Remember which Rx descriptor owns the buffer we are sending. */
685
                        uxIndexToBufferOwner = uxNextRxBuffer;
686
 
687
                        /* We have finished with this Rx descriptor now. */
688
                        uxNextRxBuffer++;
689
                        if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
690
                        {
691
                                uxNextRxBuffer = 0;
692
                        }
693
 
694
                        /* Continue the Tx DMA (in case it was waiting for a new TxBD) */
695
                        MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
696
                }
697
        }
698
        else
699
        {
700
                /* Gave up waiting.  Free the buffer back to the DMA. */
701
                vFECRxProcessingCompleted();
702
        }
703
}
704
/*-----------------------------------------------------------*/
705
 
706
void vFEC_ISR( void )
707
{
708
unsigned portLONG ulEvent;
709
portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
710
 
711
        /* This handler is called in response to any of the many separate FEC
712
        interrupt. */
713
 
714
        /* Find the cause of the interrupt, then clear the interrupt. */
715
        ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;
716
        MCF_FEC_EIR = ulEvent;
717
 
718
        if( ( ulEvent & MCF_FEC_EIR_RXB ) || ( ulEvent & MCF_FEC_EIR_RXF ) )
719
        {
720
                /* A packet has been received.  Wake the handler task. */
721
                xSemaphoreGiveFromISR( xFECSemaphore, &xHighPriorityTaskWoken );
722
        }
723
 
724
        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 ) )
725
        {
726
                /* Sledge hammer error handling. */
727
                prvResetFEC( pdTRUE );
728
        }
729
 
730
        if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )
731
        {
732
                /* The buffer being sent is pointed to by an Rx descriptor, now the
733
                buffer has been sent we can mark the Rx descriptor as free again. */
734
                xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;
735
                MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
736
                xSemaphoreGiveFromISR( xTxSemaphore, &xHighPriorityTaskWoken );
737
        }
738
 
739
        portEND_SWITCHING_ISR( xHighPriorityTaskWoken );
740
}
741
/*-----------------------------------------------------------*/
742
 
743
/* Install the many different interrupt vectors, all of which call the same
744
handler function. */
745
void __attribute__ ((interrupt)) __cs3_isr_interrupt_87( void ) { vFEC_ISR(); }
746
void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }
747
void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }
748
void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }
749
void __attribute__ ((interrupt)) __cs3_isr_interrupt_91( void ) { vFEC_ISR(); }
750
void __attribute__ ((interrupt)) __cs3_isr_interrupt_92( void ) { vFEC_ISR(); }
751
void __attribute__ ((interrupt)) __cs3_isr_interrupt_93( void ) { vFEC_ISR(); }
752
void __attribute__ ((interrupt)) __cs3_isr_interrupt_94( void ) { vFEC_ISR(); }
753
void __attribute__ ((interrupt)) __cs3_isr_interrupt_95( void ) { vFEC_ISR(); }
754
void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }
755
void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }
756
void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }
757
void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }
758
 
759
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.