www.pudn.com > zlIP-8051-rtl8019as.zip > etherif.c


/* 
 * Copyright (c) 2003 Electric Application Laboratory of NAN KAI University 
 * 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: Li Zhanglin  
 * 
 */ 
 
#include "..\GloblDef\GloblDef.h" 
#include "..\TCPIP\TCPIPmem.h" 
#include "..\TCPIP\IP.h" 
#include "..\Netif\etherif.h" 
#include "..\Netif\ARP.h" 
#include "..\TCPIP\Netif.h" 
 
 
/* call output to put a packet from IP layer to device. After 
	Ip layer selected a device, it use output to send this packet. 
	MemHead contain a packet and Netif tell dirver which netif it  
	is. NOTE:MemHead->pStart point to pIPHead 
return: 
	TRUE: send successfuly.*/ 
BOOL EtherOutput(struct SMemHead DT_XDATA *MemHead,struct SNetIf DT_XDATA* NetIf,  
		IP_ADDR DestIP) REENTRANT_SIG 
{ 
	DWORD NextIP;	/* next host to receive the packet in rout */ 
	struct SEtherHead DT_XDATA * pEtherHead; 
	struct SMemHead DT_XDATA *p; 
	 
	pEtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart - sizeof(struct SEtherHead)); 
		 
	/* if DestIP in this subnet ... */ 
	if((NetIf->NetMask & NetIf->IPAddr) == (NetIf->NetMask & DestIP)) 
		NextIP = DestIP; 
	else 
		NextIP = NetIf->GateWay; 
 
	/* find Ether addr of NextIP */ 
	if(ARPFind(pEtherHead->DestAddr,NextIP) == FALSE) 
	{ 
		/* send a arp query */ 
		if((p = ARPQuery(NetIf,NextIP)) != NULL) 
		{	 
			((struct SEtherDevice DT_XDATA *)(NetIf->Info))->send( 
				p->pStart,sizeof(struct SARPPacket) +  
				sizeof(struct SEtherHead)); 
 
			MemFree(p); 
		} 
	} 
	else 
	{ 
		/* fill ehter header, DestAddr already filled in ARPFind */ 
		MemCopy(pEtherHead->ScrAddr, 
			((struct SEtherDevice DT_XDATA *)(NetIf->Info))->Addr,ETHER_ADDR_LEN); 
 
		pEtherHead->type = htons(ETHER_TYPE_IP);	 
 
		/* send the packet. packet lenth is less than MemHead size */ 
		return ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->send( 
			pEtherHead,(WORD)(MemHead->pEnd - (BYTE DT_XDATA *)pEtherHead)); 
	} 
	return FALSE; 
	/* free MemHead when it is acked in tcp model */ 
} 
 
/* this function is called periodically.Get a packet from specific 
device. If there is a packet, call NetIf->Input to do more */ 
void EtherInput(struct SNetIf DT_XDATA * NetIf) REENTRANT_SIG 
{ 
	struct SMemHead DT_XDATA *MemHead; 
	struct SEtherHead DT_XDATA *pEtherHead; 
	struct SMemHead DT_XDATA *p; 
 
	/* if there is a packet to deal with */ 
	while((MemHead = ((struct SEtherDevice DT_XDATA *)(NetIf->Info))->recv()) 
		!= NULL) 
	{ 
		/* Note, pStart point to EtherHead */ 
		pEtherHead = (struct SEtherHead DT_XDATA *)(MemHead->pStart); 
		 
		/* which packet type */ 
		switch(ntohs(pEtherHead->type)) 
		{ 
		case ETHER_TYPE_IP: 
			/* before pass to IP layer, let MemHead->pStart point 
			to IP header */ 
			MemHead->pStart += sizeof(struct SEtherHead); 
 
			/* pass to IP layer for more dealing */ 
			IPInput(MemHead); 
			break; 
 
		case ETHER_TYPE_ARP: 
			if((p = ARPInput(MemHead,NetIf)) != NULL) 
			{ 
				/* a arp reply need to be send */ 
				((struct SEtherDevice DT_XDATA *)(NetIf->Info))->send( 
					p->pStart,sizeof(struct SARPPacket)  
					+ sizeof(struct SEtherHead)); 
 
				MemFree(p); 
			} 
			/* 'MemHead' is freed in ARPInput() */ 
			break; 
		default: 
 
			/* unknown packet type free */ 
			MemFree(MemHead); 
		} 
	} 
} 
/* ethernet device init */ 
void EtherDevInit(struct SEtherDevice DT_XDATA * pDevice, BYTE EtherAddr[], 
				  BOOL (DT_CODE * send)(void DT_XDATA *buf, WORD size)  REENTRANT_SIG, 
				  struct SMemHead DT_XDATA *(DT_CODE * recv)()  REENTRANT_SIG) REENTRANT_MUL 
{ 
	MemCopy(pDevice->Addr,EtherAddr,ETHER_ADDR_LEN); 
	pDevice->recv = recv; 
	pDevice->send = send; 
}