ethernetif.c
来自「不带操作系统的LWIP栈」· C语言 代码 · 共 447 行
C
447 行
/*
* 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 "stoe.h"
#include "dma.h"
#include "reg80390.h"
#include "netif/etharp.h"
#include "netif/ethernetif.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
#define RECEIVE_THREAD_PRIO 11
#define PACKET_TYPE_POS (MAC_TX_RX_HEADER+MAC_ADDRESS_LEN*2)
struct ethernetif stoeif;
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
extern const U8_T ipaddr1, ipaddr2, ipaddr3, ipaddr4;
extern const U8_T gateaddr1, gateaddr2, gateaddr3, gateaddr4;
extern const U8_T submask1, submask2, submask3, submask4;
/* Forward declarations. */
u8_t ethernetif_input(struct netif *netif) ;
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)KCREENTRANT;
static void arp_timer(void *arg);
void ETH_RcvHandle(U8_T XDATA* pbuf, U16_T length, U8_T protocol);
static void
low_level_init(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
/* set MAC hardware address length */
netif->hwaddr_len = 6;
/* set MAC hardware address */
netif->hwaddr[0] = PNetStation->CurrStaAddr[0];
netif->hwaddr[1] = PNetStation->CurrStaAddr[1];
netif->hwaddr[2] = PNetStation->CurrStaAddr[2];
netif->hwaddr[3] = PNetStation->CurrStaAddr[3];
netif->hwaddr[4] = PNetStation->CurrStaAddr[4];
netif->hwaddr[5] = PNetStation->CurrStaAddr[5];
/* maximum transfer unit */
netif->mtu = 1500;
/* broadcast capability */
netif->flags = NETIF_FLAG_BROADCAST;
/* Do whatever else is needed to initialize interface. */
}
/*
* 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) KCREENTRANT
{
struct ethernetif *whateverif = netif->state;
struct pbuf *q;
U8_T XDATA *pBuf, *pdest;
U16_T length=0, leftlen;
LWIP_PLATFORM_DIAG(("low_level_output ::Allocate buffer %04d\n\r", p->tot_len + MAC_TX_RX_HEADER));
/* allocate mac memory*/
pBuf = STOE_AssignSendBuf(p->tot_len + MAC_TX_RX_HEADER);
if (!pBuf) {
if (P2 & 2)
P2 &= ~2;
else
P2 |= 2;
LWIP_PLATFORM_DIAG(("low_level_output ::Allocate buffer Failed %04d\n\r", p->tot_len + MAC_TX_RX_HEADER));
return ERR_OK;
}
PBDP->STOE_TxInform.PBuf = pBuf;
PBDP->STOE_TxInform.TotalLen = p->tot_len;
LWIP_PLATFORM_DIAG(("low_level_output ::total leng = %04x\n\r", p->tot_len));
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
pdest = pBuf + MAC_TX_RX_HEADER;
leftlen = p->tot_len;
q = p;
while(leftlen > 0) {
LWIP_ASSERT("low_level_output ::pbuf == NULL", q == NULL);
length = q->len;
if(length <=0) {
goto again;
}
if (q->flags == PBUF_FLAG_ROM) {
pdest = STOE_CopyCode2TPBR(pdest, q->payload, length);
} else {
pdest = DMA_GrantXdata(pdest, q->payload, length);
if (!pdest) {
LWIP_PLATFORM_DIAG(("low_level_output ::DMA Error occurred.!!\n\r"));
return ERR_OK;
}
}
leftlen -= length;
again:
q = q->next;
} /* end of while(leftlen) */
#if (STOE_TRANSPARENT)
# if (STOE_CHECKSUM_OFFLOAD)
if ((*(pBuf + PACKET_TYPE_POS) == 8) && (*(pBuf + PACKET_TYPE_POS + 1) == 0)) {
PBDP->STOE_TxInform.Protocol = *(pBuf + MAC_TX_RX_HEADER + 14 + 9);
}
else {
PBDP->STOE_TxInform.Protocol = 0xff;
}
# else
PBDP->STOE_TxInform.Protocol = 0xff;
# endif
#else /* (!STOE_TRANSPARENT) */
PBDP->STOE_TxInform.Protocol = *(pBuf + MAC_TX_RX_HEADER + 9);
#endif /* (STOE_TRANSPARENT) */
LWIP_PLATFORM_DIAG(("low_level_output ::send %04d\n\r",p->tot_len));
STOE_Send(pBuf, PBDP->STOE_TxInform.TotalLen, PBDP->STOE_TxInform.Protocol);
#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;
}
/*
* low_level_input():
*
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
*/
static
struct pbuf *low_level_input(struct netif *netif)
{
U8_T XDATA *pSour;
struct ethernetif *whateverif = netif->state;
struct pbuf *p, *q;
u16_t len, left_len;
#if (!STOE_TRANSPARENT)
u8_t protocol;
#endif
/* Obtain the size of the packet and put it into the "len" variable. */
len = PBDP->STOE_RxInform.TotalLen;
left_len = len;
LWIP_PLATFORM_DIAG(("low_level_input ::total leng = %04d\n\r", left_len));
pSour = PBDP->STOE_RxInform.PBuf;
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
#if (STOE_TRANSPARENT)
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
#else
protocol = PBDP->STOE_RxInform.Protocol;
if (protocol == 0xff)
{
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
}
else
{
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct eth_hdr), PBUF_POOL);
}
#endif /* (STOE_TRANSPARENT) */
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
q = p;
#if (!STOE_TRANSPARENT)
if (protocol != 0xff)
pbuf_header(p, -sizeof(struct eth_hdr));
#endif
while (left_len)
{
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf. */
LWIP_PLATFORM_DIAG(("low_level_input ::left_len = %04d\n\r", left_len));
if (left_len > q->len)
{
if(!DMA_GrantXdata((U8_T XDATA*)q->payload, pSour, q->len)) {
LWIP_PLATFORM_DIAG(("DMA Error occurred.!!\n\r"));
pbuf_free(p);
p = NULL;
return p;
}
left_len -= q->len;
pSour += q->len;
}
else
{
if(!DMA_GrantXdata((U8_T XDATA*)q->payload, pSour, left_len)) {
LWIP_PLATFORM_DIAG(("DMA Error occurred.!!\n\r"));
pbuf_free(p);
p = NULL;
return p;
}
break;
}
q = q->next;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
} else { /* (p == NULL) */
LWIP_PLATFORM_DIAG(("pbuf_alloc failed!!!\n"));
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
} /* if (p != NULL) */
return p;
}
/*
* ethernetif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actual transmission of the packet.
*
*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) KCREENTRANT
{
/* resolve hardware address, then send (or queue) packet */
#if (STOE_TRANSPARENT)
return etharp_output(netif, ipaddr, p);
#else
return low_level_output(netif, p);
#endif
}
/*
* ethernetif_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*/
u8_t
ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
ethernetif = netif->state;
LWIP_PLATFORM_DIAG(("ethernetif_input start...\n\r"));
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p == NULL)
{
if (P2 & 0x40)
P2 &= ~0x40;
else
P2 |= 0x40;
LWIP_PLATFORM_DIAG(("p = NULL return!!\n\r"));
return 0;
}
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
if (P2 & 0x20)
P2 &= ~0x20;
else
P2 |= 0x20;
LWIP_PLATFORM_DIAG(("ethernetif_input : Packet from low_level_input %d\n\r", p->tot_len));
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
#if (STOE_TRANSPARENT)
LWIP_PLATFORM_DIAG(("ethernet type : %x\n\r", ethhdr->type));
switch (htons(ethhdr->type)) {
/* IP packet? */
case ETHTYPE_IP:
/* update ARP table */
etharp_ip_input(netif, p);
/* skip Ethernet header */
pbuf_header(p, -sizeof(struct eth_hdr));
/* pass to network layer */
ip_input(p, netif);
break;
case ETHTYPE_ARP:
/* pass p to ARP module */
etharp_arp_input(netif, ethernetif->ethaddr, p);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
#else
switch (PBDP->STOE_RxInform.Protocol) {
case 0xff:
LWIP_PLATFORM_DIAG(("ethernetif_input:: protocol %x\n\r", PBDP->STOE_RxInform.Protocol));
pbuf_free(p);
p = NULL;
break;
default:
ip_input(p, netif);
break;
}
#endif
return 1;
}
/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
err_t
ethernetif_init(struct netif *netif)
{
netif->state = &stoeif;
netif->name[0] = 'e';
netif->name[1] = 'n';
netif->output = ethernetif_output;
netif->linkoutput = low_level_output;
stoeif.ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
stoeif.netif = netif;
STOE_Init(0);
STOE_SetIPAddr(INT_TO_IPADDR(ipaddr1, ipaddr2, ipaddr3, ipaddr4));
STOE_SetSubnetMask(INT_TO_IPADDR(submask1, submask2, submask3, submask4));
STOE_SetGateway(INT_TO_IPADDR(gateaddr1, gateaddr2, gateaddr3, gateaddr4));
low_level_init(netif);
STOE_RcvCallback = ETH_RcvHandle;
STOE_Start();
return ERR_OK;
}
/*
* ----------------------------------------------------------------------------
* Function Name: ETH_RcvHandle
* Purpose:
* Params:
* Returns:
* Note:
* ----------------------------------------------------------------------------
*/
void
ETH_RcvHandle(U8_T XDATA* pbuf, U16_T length, U8_T protocol)
{
ethernetif_input(stoeif.netif);
} /* End of ETH_RcvHandle */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?