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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [contrib/] [port/] [FreeRTOS/] [ColdFire/] [MCF5225x_ethernetif.c] - Blame information for rev 606

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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