📄 ethernetif.c
字号:
/* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * 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. * * This file is part of the lwIP TCP/IP stack. * * Author: Adam Dunkels <adam@sics.se> * *//* * This file is a skeleton for developing Ethernet network interface * drivers for lwIP. Add code to the low_level functions and do a * search-and-replace for the word "ethernetif" to replace it with * something that better describes your network interface. */#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 "netif/etharp.h"#include "AT91SAM7X256.h"#include "lib_AT91SAM7X256.h"#include <string.h>#include "Emac.h"#include "ethernetif.h"static void low_level_init(struct netif *netif){ /* set MAC hardware address length */ netif->hwaddr_len = 6; //xNetIf = NULL; ulNextRxBuffer = 0; /* set MAC hardware address */ netif->hwaddr[0] = EMAC1; netif->hwaddr[1] = EMAC2; netif->hwaddr[2] = EMAC3; netif->hwaddr[3] = EMAC4; netif->hwaddr[4] = EMAC5; netif->hwaddr[5] = EMAC6; /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability */ netif->flags = NETIF_FLAG_BROADCAST; xNetIf = netif; /* Do whatever else is needed to initialize interface. */ LanInitialize(); AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_EMAC, AT91C_AIC_PRIOR_HIGHEST, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, vEMACISR); AT91C_BASE_EMAC->EMAC_IDR = 0x3fff; AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_EMAC); AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP | AT91C_EMAC_TXUBR; OSTaskCreateExt(ethernetif_input, (void *)1, &INPOUTTaskStk[INPUTTASK_STK_SIZE - 1], INPUT_TASK_PRIO, INPUT_TASK_PRIO, &INPOUTTaskStk[0], INPUTTASK_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);}/*-----------------------------------------------------------*//* See the header file for descriptions of public functions. */unsigned int ulEMACInputLength( void ){ register unsigned int ulIndex, ulLength = 0; /* Skip any fragments. We are looking for the first buffer that contains data and has the SOF (start of frame) bit set. */ while( ( RxtdList[ ulNextRxBuffer ].addr & AT91C_OWNERSHIP_BIT ) && !( RxtdList[ ulNextRxBuffer ].U_Status.status & AT91C_SOF ) ) { /* Ignoring this buffer. Mark it as free again. */ RxtdList[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT ); ulNextRxBuffer++; if( ulNextRxBuffer >= NB_RX_BUFFERS ) { ulNextRxBuffer = 0; } } /* We are going to walk through the descriptors that make up this frame, but don't want to alter ulNextRxBuffer as this would prevent vEMACRead() from finding the data. Therefore use a copy of ulNextRxBuffer instead. */ ulIndex = ulNextRxBuffer; /* Walk through the descriptors until we find the last buffer for this frame. The last buffer will give us the length of the entire frame. */ while( ( RxtdList[ ulIndex ].addr & AT91C_OWNERSHIP_BIT ) && !ulLength ) { ulLength = RxtdList[ ulIndex ].U_Status.status & AT91C_LENGTH_FRAME; /* Increment to the next buffer, wrapping if necessary. */ ulIndex++; if( ulIndex >= NB_RX_BUFFERS ) { ulIndex = 0; } } return ulLength;}/* * Function : SendPacket * Description : Send ethernet frame function * Input : frame data pointer, frame length * Output : transmit ok(1) or error(0) */int SendPacket( unsigned char* Data,int Size, int EndOfFrame){ unsigned int DataBuffered = 0, DataRemainingToSend, LengthToSend, LastBuffer; int wait = 0; int sndrtn = 0; //send return char *pcBuffer; INT8U err; OSSemPend(lwip_output, 0, &err); while(DataBuffered < Size){ // Is a buffer available? * while(!(TxtdList[TxBuffIndex].U_Status.status & AT91C_TRANSMIT_OK)){ // There is no room to write the Tx data to the Tx buffer. Wait a //short while, then try again. wait++; if(wait > Emac_MAX_WAIT){ // Give up. sndrtn = 1; break; } else{ ; } } // lReturn will only be 0 if a buffer is available. if(sndrtn == 0){ //Get the address of the buffer from the descriptor, then copy // the data into the buffer. pcBuffer = (char *) TxtdList[TxBuffIndex].addr; // How much can we write to the buffer? DataRemainingToSend = Size - DataBuffered; if(DataRemainingToSend <= ETH_TX_BUFFER_SIZE){ // We can write all the remaining bytes. LengthToSend = DataRemainingToSend; } else{ // We can not write more than ETH_TX_BUFFER_SIZE in one go. * LengthToSend = ETH_TX_BUFFER_SIZE; } // Copy the data into the buffer. * memcpy( ( void * ) pcBuffer, ( void * ) &( Data[ DataBuffered ] ), LengthToSend ); DataBuffered += LengthToSend; // Is this the last data for the frame? * if( EndOfFrame && ( DataBuffered >= Size ) ){ // No more data remains for this frame so we can start the //transmission. * LastBuffer = AT91C_LAST_BUFFER; } else{ // More data to come for this frame. * LastBuffer = 0; } // Fill out the necessary in the descriptor to get the data sent, // then move to the next descriptor, wrapping if necessary. * if( TxBuffIndex >= ( NB_TX_BUFFERS - 1 ) ){ TxtdList[ TxBuffIndex ].U_Status.status = ( LengthToSend & ( unsigned int ) AT91C_LENGTH_FRAME ) | LastBuffer | AT91C_TRANSMIT_WRAP; TxBuffIndex = 0; } else{ TxtdList[ TxBuffIndex ].U_Status.status = ( LengthToSend & ( unsigned int ) AT91C_LENGTH_FRAME ) | LastBuffer; TxBuffIndex++; } // If this is the last buffer to be sent for this frame we can // start the transmission. * if( LastBuffer ){ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART; } } else{ break; } } OSSemPost(lwip_output); return sndrtn;}/* * low_level_output(): * * Should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf * might be chained. * */static err_t low_level_output(struct netif *netif, struct pbuf *p){ struct pbuf *q; u8_t *pFrameData,*tmp ; u32_t FrameLength ; pFrameData = mem_malloc(p->tot_len); if (pFrameData == NULL)return ERR_MEM; FrameLength = p->tot_len; tmp = pFrameData; #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */#endif for(q = p; q != NULL; q = q->next) { /* Send the data from the pbuf to the interface, one pbuf at a time. The size of the data in each pbuf is kept in the ->len variable. */ //send data from(q->payload, q->len); SendPacket(q->payload, q->len, (q->next == NULL)); } mem_free(pFrameData);#if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */#endif #if LINK_STATS lwip_stats.link.xmit++;#endif /* LINK_STATS */ return ERR_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -