📄 fec.c
字号:
/* * Copyright (c) 2006 Christian Walter * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Christian Walter <wolti@sil.at> * * TODO: * - Introduce another task create function in the sys_arch layer which allows * for passing the stack size. * - Avoid copying the buffers - this requires changeing the nbuf driver code * to use the lwIP pbuf buffer implementation. * * File: $Id: fec.c,v 1.1 2006/08/30 23:18:07 wolti Exp $ *//* ------------------------ System includes ------------------------------- */#include <stdlib.h>/* ------------------------ Platform includes ----------------------------- */#include "mcf5xxx.h"#include "mcf523x.h"#include "nbuf.h"/* ------------------------ lwIP includes --------------------------------- */#include "lwip/opt.h"#include "lwip/def.h"#include "lwip/mem.h"#include "lwip/pbuf.h"#include "lwip/sys.h"#include "lwip/stats.h"#include "lwip/debug.h"#include "netif/etharp.h"/* ------------------------ Defines --------------------------------------- */#ifdef FEC_DEBUG#define FEC_DEBUG_INIT \ do \ { \ MCF_GPIO_PDDR_FECI2C = ( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 | \ MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 ); \ } while( 0 )#define FEC_DEBUG_RX_TIMING( x ) \ do \ { \ if( x ) \ MCF_GPIO_PPDSDR_FECI2C = MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0; \ else \ MCF_GPIO_PCLRR_FECI2C = ~( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 ); \ } while( 0 )#define FEC_DEBUG_TX_TIMING( x ) \ do \ { \ if( x ) \ MCF_GPIO_PPDSDR_FECI2C = MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1; \ else \ MCF_GPIO_PCLRR_FECI2C = ~( MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 ); \ } while( 0 )#else#define FEC_DEBUG DBG_OFF#define FEC_DEBUG_INIT#define FEC_DEBUG_RX_TIMING( x )#define FEC_DEBUG_TX_TIMING( x )#endif#define MCF_FEC_INT_LEVEL ( 6 )#define MCF_FEC_INT_PRIORITY ( 0 )#define MCF_FEC_VEC_RXF ( 64 + 27 )#define MCF_FEC_MTU ( 1518 )#define ETH_ADDR_LEN ( 6 )#define TASK_PRIORITY ( configMAX_PRIORITIES - 1 )/* ------------------------ Type definitions ------------------------------ */typedef struct{ struct netif *netif; /* lwIP network interface. */ struct eth_addr *self; /* MAC address of FEC interface. */ sys_sem_t tx_sem; /* Control access to transmitter. */ sys_sem_t rx_sem; /* Semaphore to signal receive thread. */} mcf523xfec_if_t;/* ------------------------ Static variables ------------------------------ */static mcf523xfec_if_t *fecif_g;/* ------------------------ Static functions ------------------------------ */static err_t mcf523xfec_output( struct netif *, struct pbuf *, struct ip_addr * );static err_t mcf523xfec_output_raw( struct netif *, struct pbuf * );static void mcf523xfec_reset( mcf523xfec_if_t * fecif );static void mcf523xfec_enable( mcf523xfec_if_t * fecif );static void mcf523xfec_disable( mcf523xfec_if_t * fecif );static void mcf523xfec_get_mac( mcf523xfec_if_t * fecif, struct eth_addr *mac );static void mcf523xfec_rx_irq( void );static void mcf523xfec_rx_task( void *arg );static void arp_timer( void *arg );static void eth_input( struct netif *netif, struct pbuf *p );/* ------------------------ Start implementation -------------------------- */static voidarp_timer( void *arg ){ ( void )arg; etharp_tmr( ); sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL );}err_tmcf523xfec_output_raw( struct netif *netif, struct pbuf *p ){ err_t res; nbuf_t *pNBuf; mcf523xfec_if_t *fecif = netif->state; int i; struct pbuf *q;#if ETH_PAD_SIZE pbuf_header( p, -ETH_PAD_SIZE ); /* drop the padding word */#endif /* Test if we can handle such big frames. If not drop it. */ if( p->tot_len > MCF_FEC_MTU ) {#if LINK_STATS lwip_stats.link.lenerr++;#endif res = ERR_BUF; } /* Test if our network buffer scheme can handle a packet of this size. If * not drop it and return a memory error. */ else if( p->tot_len > TX_BUFFER_SIZE ) {#ifdef LINK_STATS lwip_stats.link.memerr++;#endif res = ERR_MEM; } /* Allocate a transmit buffer. If no buffer is available drop the frame. */ else if( ( pNBuf = nbuf_tx_allocate( ) ) == NULL ) { LWIP_ASSERT( "mcf523xfec_output_raw: pNBuf != NULL\n", pNBuf != NULL );#ifdef LINK_STATS lwip_stats.link.memerr++;#endif res = ERR_MEM; } else { q = p; i = 0; do { memcpy( &pNBuf->data[i], q->payload, q->len ); i += q->len; } while( ( q = q->next ) != NULL ); pNBuf->length = p->tot_len; /* Set Frame ready for transmission. */ pNBuf->status |= TX_BD_R; /* Mark the buffer as not in use so the FEC can take it. */ nbuf_tx_release( pNBuf ); /* Indicate that a new transmit buffer has been produced. */ MCF_FEC_TDAR = 1;#if LINK_STATS lwip_stats.link.xmit++;#endif res = ERR_OK; } sys_sem_signal( fecif->tx_sem );#if ETH_PAD_SIZE buf_header( p, ETH_PAD_SIZE );#endif return res;}/* This function is called by the TCP/IP stack when an IP packet should be * sent. It uses the ethernet ARP module provided by lwIP to resolve the * destination MAC address. The ARP module will later call our low level * output function mcf523xfec_output_raw. */err_tmcf523xfec_output( struct netif * netif, struct pbuf * p, struct ip_addr * ipaddr ){ err_t res; mcf523xfec_if_t *fecif = netif->state; FEC_DEBUG_TX_TIMING( 1 ); /* Make sure only one thread is in this function. */ sys_sem_wait( fecif->tx_sem ); res = etharp_output( netif, ipaddr, p ); FEC_DEBUG_TX_TIMING( 0 ); return res;}voidmcf523xfec_rx_task( void *arg ){ mcf523xfec_if_t *fecif = arg; struct pbuf *p, *q; nbuf_t *pNBuf; uint8 *pPayLoad; do { sys_sem_wait( fecif->rx_sem ); while( nbuf_rx_next_ready( ) ) { pNBuf = nbuf_rx_allocate( ); if( pNBuf != NULL ) { LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->status & RX_BD_L ", pNBuf->status & RX_BD_L ); /* This flags indicate that the frame has been damaged. In * this case we must update the link stats if enabled and * remove the frame from the FEC. */ if( pNBuf->status & ( RX_BD_LG | RX_BD_NO | RX_BD_CR | RX_BD_OV ) ) {#ifdef LINK_STATS lwip_stats.link.drop++; if( pNBuf->status & RX_BD_LG ) { lwip_stats.link.lenerr++; } else if( pNBuf->status & ( RX_BD_NO | RX_BD_OV ) ) { lwip_stats.link.err++; } else { lwip_stats.link.chkerr++; }#endif } else { /* The frame must no be valid. Perform some checks to see if the FEC * driver is working correctly. */ LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->length != 0", pNBuf->length != 0 ); p = pbuf_alloc( PBUF_RAW, pNBuf->length, PBUF_POOL ); if( p != NULL ) {#if ETH_PAD_SIZE pbuf_header( p, -ETH_PAD_SIZE );#endif pPayLoad = pNBuf->data; for( q = p; q != NULL; q = q->next ) { memcpy( q->payload, pPayLoad, q->len ); pPayLoad += q->len; }#if ETH_PAD_SIZE pbuf_header( p, ETH_PAD_SIZE );#endif /* Ethernet frame received. Handling it is not device * dependent and therefore done in another function. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -