806 lines
21 KiB
C
806 lines
21 KiB
C
![]() |
/******************************************************************************
|
||
|
*
|
||
|
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* Use of the Software is limited solely to applications:
|
||
|
* (a) running on a Xilinx device, or
|
||
|
* (b) that interact with a Xilinx device through a bus or interconnect.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*
|
||
|
* Except as contained in this notice, the name of the Xilinx shall not be used
|
||
|
* in advertising or otherwise to promote the sale, use or other dealings in
|
||
|
* this Software without prior written authorization from Xilinx.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
* @file xemaclite_ping_req_example.c
|
||
|
*
|
||
|
* This file contains a EmacLite Ping request example in polled mode. This
|
||
|
* example will generate a ping request for the specified IP address.
|
||
|
*
|
||
|
* @note
|
||
|
*
|
||
|
* The local IP address is set to 172.16.63.121. User needs to update
|
||
|
* LocalIpAddr variable with a free IP address based on the network on which
|
||
|
* this example is to be run.
|
||
|
*
|
||
|
* The Destination IP address is set to 172.16.63.61. User needs to update
|
||
|
* DestIpAddress variable with any valid IP address based on the network on which
|
||
|
* this example is to be run.
|
||
|
*
|
||
|
* The local MAC address is set to 0x000A35030201. User can update LocalMacAddr
|
||
|
* variable with a valid MAC address. The first three bytes contains
|
||
|
* the manufacture ID. 0x000A35 is XILINX manufacture ID.
|
||
|
*
|
||
|
* This program will generate the specified number of ping request packets as
|
||
|
* defined in "NUM_OF_PING_REQ_PKTS".
|
||
|
*
|
||
|
* <pre>
|
||
|
* MODIFICATION HISTORY:
|
||
|
*
|
||
|
* Ver Who Date Changes
|
||
|
* ----- ---- -------- -----------------------------------------------
|
||
|
* 1.00a ktn 27/08/08 First release
|
||
|
* 3.00a ktn 10/22/09 Updated example to use the macros that have been changed
|
||
|
* in the driver to remove _m from the name of the macro.
|
||
|
* 3.01a ktn 08/06/10 Updated the example to support little endian MicroBlaze.
|
||
|
*
|
||
|
* </pre>
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
/***************************** Include Files *********************************/
|
||
|
|
||
|
#include "xparameters.h"
|
||
|
#include "xstatus.h"
|
||
|
#include "xemaclite.h"
|
||
|
#include "stdio.h"
|
||
|
#include "xil_io.h"
|
||
|
|
||
|
/************************** Constant Definitions *****************************/
|
||
|
|
||
|
/*
|
||
|
* The following constants map to the XPAR parameters created in the
|
||
|
* xparameters.h file. They are defined here such that a user can easily
|
||
|
* change all the needed parameters in one place.
|
||
|
*/
|
||
|
#define EMAC_DEVICE_ID XPAR_EMACLITE_0_DEVICE_ID
|
||
|
|
||
|
/*
|
||
|
* Change this parameter to limit the number of ping requests sent by this
|
||
|
* program.
|
||
|
*/
|
||
|
#define NUM_OF_PING_REQ_PKTS 100 /* Number of ping req it generates */
|
||
|
|
||
|
#define ECHO_REPLY 0x00 /* Echo reply */
|
||
|
#define HW_TYPE 0x01 /* Hardware type (10/100 Mbps) */
|
||
|
#define ARP_REQUEST 0x01 /* ARP Request bits in Rx packet */
|
||
|
#define ARP_REPLY 0x02 /* ARP status bits indicating reply */
|
||
|
#define IDEN_NUM 0x02 /* ICMP identifier number */
|
||
|
#define IP_VERSION 0x0604 /* IP version ipv4/ipv6 */
|
||
|
#define BROADCAST_ADDR 0xFFFF /* Broadcast Address */
|
||
|
#define CORRECT_CHECKSUM_VALUE 0xFFFF /* Correct checksum value */
|
||
|
#define ARP_REQ_PKT_SIZE 0x2A /* ARP request packet size */
|
||
|
#define ICMP_PKT_SIZE 0x4A /* ICMP packet length 74 Bytes
|
||
|
including Src and dest MAC Add */
|
||
|
#define IP_ADDR_SIZE 4 /* IP Address size in Bytes */
|
||
|
#define NUM_RX_PACK_CHECK_REQ 10 /* Max num of Rx pack to be checked
|
||
|
before sending another request */
|
||
|
#define NUM_PACK_CHECK_RX_PACK 100 /* Max number of pack to be checked
|
||
|
before to identify a Rx packet */
|
||
|
#define DELAY 5000000 /* Used to introduce delay */
|
||
|
|
||
|
/*
|
||
|
* Definitions for the locations and length of some of the fields in a
|
||
|
* IP packet. The lengths are defined in Half-Words (2 bytes).
|
||
|
*/
|
||
|
|
||
|
#define SRC_MAC_ADDR_LOC 3 /* Src MAC address location */
|
||
|
#define MAC_ADDR_LEN 3 /* MAC address length */
|
||
|
#define ETHER_PROTO_TYPE_LOC 6 /* Ethernet Proto type loc */
|
||
|
|
||
|
#define IP_ADDR_LEN 2 /* Size of IP address */
|
||
|
#define IP_START_LOC 7 /* IP header start location */
|
||
|
#define IP_HEADER_INFO_LEN 7 /* IP header information length */
|
||
|
#define IP_HEADER_LEN 10 /* IP header length */
|
||
|
#define IP_CHECKSUM_LOC 12 /* IP header checksum location */
|
||
|
#define IP_REQ_SRC_IP_LOC 13 /* Src IP add loc of ICMP req */
|
||
|
#define IP_REQ_DEST_IP_LOC 15 /* Dest IP add loc of ICMP req */
|
||
|
|
||
|
#define ICMP_KNOWN_DATA_LEN 16 /* ICMP known data length */
|
||
|
#define ICMP_ECHO_FIELD_LOC 17 /* Echo field loc */
|
||
|
#define ICMP_DATA_START_LOC 17 /* Data field start location */
|
||
|
#define ICMP_DATA_LEN 18 /* ICMP data length */
|
||
|
#define ICMP_DATA_CHECKSUM_LOC 18 /* ICMP data checksum location */
|
||
|
#define ICMP_IDEN_FIELD_LOC 19 /* Identifier field loc */
|
||
|
#define ICMP_DATA_LOC 19 /* ICMP data loc including
|
||
|
identifier number and sequence number */
|
||
|
#define ICMP_SEQ_NO_LOC 20 /* sequence number location */
|
||
|
#define ICMP_DATA_FIELD_LEN 20 /* Data field length */
|
||
|
#define ICMP_KNOWN_DATA_LOC 21 /* ICMP known data start loc */
|
||
|
|
||
|
#define ARP_REQ_STATUS_LOC 10 /* ARP request loc */
|
||
|
#define ARP_REQ_SRC_IP_LOC 14 /* Src IP add loc of ARP req Packet */
|
||
|
|
||
|
/**************************** Type Definitions *******************************/
|
||
|
|
||
|
|
||
|
/***************** Macros (Inline Functions) Definitions *********************/
|
||
|
|
||
|
|
||
|
/************************** Function Prototypes ******************************/
|
||
|
|
||
|
static int EmacLitePingReqExample(u16 DeviceId);
|
||
|
|
||
|
static void SendArpReqFrame(XEmacLite *InstancePtr);
|
||
|
|
||
|
static void SendEchoReqFrame(XEmacLite *InstancePtr);
|
||
|
|
||
|
static int ProcessRecvFrame(XEmacLite *InstancePtr);
|
||
|
|
||
|
static u16 CheckSumCalculation(u16 *RxFramePtr16, int StartLoc, int Length);
|
||
|
|
||
|
static int CompareData(u16 *LhsPtr, u16 *RhsPtr, int LhsLoc, int RhsLoc,
|
||
|
int Count);
|
||
|
|
||
|
/************************** Variable Definitions *****************************/
|
||
|
|
||
|
/*
|
||
|
* Set up a local MAC address.
|
||
|
*/
|
||
|
static u8 LocalMacAddr[XEL_MAC_ADDR_SIZE] =
|
||
|
{
|
||
|
0x00, 0x0A, 0x35, 0x03, 0x02, 0x01
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* The IP address was set to 172.16.63.121. User need to set a free IP address
|
||
|
* based on the network on which this example is to be run.
|
||
|
*/
|
||
|
static u8 LocalIpAddress[IP_ADDR_SIZE] =
|
||
|
{
|
||
|
172, 16, 63, 121
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Set up a Destination IP address. Currently it is set to 172.16.63.61.
|
||
|
*/
|
||
|
static u8 DestIpAddress[IP_ADDR_SIZE] =
|
||
|
{
|
||
|
172, 16, 63, 61
|
||
|
};
|
||
|
|
||
|
static u16 DestMacAddr[MAC_ADDR_LEN]; /* Destination MAC Address */
|
||
|
static XEmacLite EmacLiteInstance; /* Instance of the EmacLite driver */
|
||
|
|
||
|
/*
|
||
|
* Known data transmitted in Echo request.
|
||
|
*/
|
||
|
u16 IcmpData[ICMP_KNOWN_DATA_LEN] =
|
||
|
{
|
||
|
0x6162, 0x6364, 0x6566, 0x6768, 0x696A, 0x6B6C, 0x6D6E, 0x6F70,
|
||
|
0x7172, 0x7374, 0x7576, 0x7761, 0x6263, 0x6465, 0x6667, 0x6869
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* IP header information -- each field has its own significance.
|
||
|
* Icmp type, ipv4 typelength, packet length, identification field
|
||
|
* Fragment type, time to live and ICM, checksum.
|
||
|
*/
|
||
|
u16 IpHeaderInfo[IP_HEADER_INFO_LEN] =
|
||
|
{
|
||
|
0x0800, 0x4500, 0x003C, 0x5566, 0x0000, 0x8001, 0x0000
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Buffers used for Transmission and Reception of Packets. These are declared as
|
||
|
* global so that they are not a part of the stack.
|
||
|
*/
|
||
|
static u8 RxFrame[XEL_MAX_FRAME_SIZE];
|
||
|
static u8 TxFrame[XEL_MAX_FRAME_SIZE];
|
||
|
|
||
|
/*
|
||
|
* Variable used to indicate the length of the received frame.
|
||
|
*/
|
||
|
u32 RecvFrameLength;
|
||
|
|
||
|
/*
|
||
|
* Variable used to indicate the sequence number of the ICMP(echo) packet.
|
||
|
*/
|
||
|
int SeqNum;
|
||
|
|
||
|
/*
|
||
|
* Variable used to indicate the number of ping request packets to be send.
|
||
|
*/
|
||
|
int NumOfPingReqPkts;
|
||
|
|
||
|
/****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function is the main function of the Ping Request example in polled mode.
|
||
|
*
|
||
|
* @param None.
|
||
|
*
|
||
|
* @return XST_FAILURE to indicate failure, otherwise it will return
|
||
|
* XST_SUCCESS after sending specified number of packets as
|
||
|
* defined in "NUM_OF_PING_REQ_PKTS" .
|
||
|
*
|
||
|
* @note None.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
int main()
|
||
|
{
|
||
|
int Status;
|
||
|
|
||
|
/*
|
||
|
* Run the EmacLite Ping request example.
|
||
|
*/
|
||
|
Status = EmacLitePingReqExample(EMAC_DEVICE_ID);
|
||
|
if (Status != XST_SUCCESS) {
|
||
|
return XST_FAILURE;
|
||
|
}
|
||
|
|
||
|
return XST_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* The entry point for the EmacLite driver to ping request example in polled
|
||
|
* mode. This function will generate specified number of request packets as
|
||
|
* defined in "NUM_OF_PING_REQ_PKTS.
|
||
|
*
|
||
|
* @param DeviceId is device ID of the XEmacLite Device.
|
||
|
*
|
||
|
* @return XST_FAILURE to indicate failure, otherwise it will return
|
||
|
* XST_SUCCESS.
|
||
|
*
|
||
|
* @note None.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static int EmacLitePingReqExample(u16 DeviceId)
|
||
|
{
|
||
|
int Status;
|
||
|
int Index;
|
||
|
int Count;
|
||
|
int EchoReplyStatus;
|
||
|
XEmacLite_Config *ConfigPtr;
|
||
|
XEmacLite *EmacLiteInstPtr = &EmacLiteInstance;
|
||
|
SeqNum = 0;
|
||
|
RecvFrameLength = 0;
|
||
|
EchoReplyStatus = XST_FAILURE;
|
||
|
NumOfPingReqPkts = NUM_OF_PING_REQ_PKTS;
|
||
|
|
||
|
/*
|
||
|
* Initialize the EmacLite device.
|
||
|
*/
|
||
|
ConfigPtr = XEmacLite_LookupConfig(DeviceId);
|
||
|
if (ConfigPtr == NULL) {
|
||
|
return XST_FAILURE;
|
||
|
}
|
||
|
Status = XEmacLite_CfgInitialize(EmacLiteInstPtr,
|
||
|
ConfigPtr,
|
||
|
ConfigPtr->BaseAddress);
|
||
|
if (Status != XST_SUCCESS) {
|
||
|
return XST_FAILURE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set the MAC address.
|
||
|
*/
|
||
|
XEmacLite_SetMacAddress(EmacLiteInstPtr, LocalMacAddr);
|
||
|
|
||
|
/*
|
||
|
* Empty any existing receive frames.
|
||
|
*/
|
||
|
XEmacLite_FlushReceive(EmacLiteInstPtr);
|
||
|
while (NumOfPingReqPkts--) {
|
||
|
|
||
|
/*
|
||
|
* Introduce delay.
|
||
|
*/
|
||
|
Count = DELAY;
|
||
|
while (Count--) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Send an ARP or an ICMP packet based on receive packet.
|
||
|
*/
|
||
|
if (SeqNum == 0) {
|
||
|
SendArpReqFrame(EmacLiteInstPtr);
|
||
|
} else {
|
||
|
SendEchoReqFrame(EmacLiteInstPtr);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check next 10 packets for the correct reply.
|
||
|
*/
|
||
|
Index = NUM_RX_PACK_CHECK_REQ;
|
||
|
while (Index--) {
|
||
|
|
||
|
/*
|
||
|
* Wait for a Receive packet.
|
||
|
*/
|
||
|
Count = NUM_PACK_CHECK_RX_PACK;
|
||
|
while (RecvFrameLength == 0) {
|
||
|
RecvFrameLength = XEmacLite_Recv(
|
||
|
EmacLiteInstPtr,
|
||
|
(u8 *)RxFrame);
|
||
|
|
||
|
/*
|
||
|
* To avoid infinite loop when no packet is
|
||
|
* received.
|
||
|
*/
|
||
|
if (Count-- == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Process the Receive frame.
|
||
|
*/
|
||
|
if (RecvFrameLength != 0) {
|
||
|
EchoReplyStatus = ProcessRecvFrame(
|
||
|
EmacLiteInstPtr);
|
||
|
}
|
||
|
RecvFrameLength = 0;
|
||
|
|
||
|
/*
|
||
|
* Comes out of loop when an echo reply packet is
|
||
|
* received.
|
||
|
*/
|
||
|
if (EchoReplyStatus == XST_SUCCESS) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If no echo reply packet is received, it reports
|
||
|
* request timed out.
|
||
|
*/
|
||
|
if (EchoReplyStatus == XST_FAILURE) {
|
||
|
xil_printf("Packet No: %d",
|
||
|
NUM_OF_PING_REQ_PKTS - NumOfPingReqPkts);
|
||
|
xil_printf(" Seq NO %d Request timed out\r\n",
|
||
|
SeqNum);
|
||
|
}
|
||
|
}
|
||
|
return XST_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function will send a ARP request packet.
|
||
|
*
|
||
|
* @param InstancePtr is a pointer to the instance of the EmacLite.
|
||
|
*
|
||
|
* @return None.
|
||
|
*
|
||
|
* @note None.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static void SendArpReqFrame(XEmacLite *InstancePtr)
|
||
|
{
|
||
|
u16 *TempPtr;
|
||
|
u16 *TxFramePtr;
|
||
|
u32 NextTxBuffBaseAddr;
|
||
|
int Index;
|
||
|
|
||
|
TxFramePtr = (u16 *)TxFrame;
|
||
|
|
||
|
/*
|
||
|
* Determine the next expected transmit buffer base address.
|
||
|
*/
|
||
|
NextTxBuffBaseAddr = XEmacLite_NextTransmitAddr(InstancePtr);
|
||
|
|
||
|
/*
|
||
|
* Add broadcast address.
|
||
|
*/
|
||
|
Index = MAC_ADDR_LEN;
|
||
|
while (Index--) {
|
||
|
*TxFramePtr++ = BROADCAST_ADDR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add local MAC address.
|
||
|
*/
|
||
|
Index = 0;
|
||
|
TempPtr = (u16 *)LocalMacAddr;
|
||
|
while (Index < MAC_ADDR_LEN) {
|
||
|
*TxFramePtr++ = *(TempPtr + Index);
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add
|
||
|
* - Ethernet proto type.
|
||
|
* - Hardware Type
|
||
|
* - Protocol IP Type
|
||
|
* - IP version (IPv6/IPv4)
|
||
|
* - ARP Request
|
||
|
*/
|
||
|
*TxFramePtr++ = Xil_Htons(XEL_ETHER_PROTO_TYPE_ARP);
|
||
|
*TxFramePtr++ = Xil_Htons(HW_TYPE);
|
||
|
*TxFramePtr++ = Xil_Htons(XEL_ETHER_PROTO_TYPE_IP);
|
||
|
*TxFramePtr++ = Xil_Htons(IP_VERSION);
|
||
|
*TxFramePtr++ = Xil_Htons(ARP_REQUEST);
|
||
|
|
||
|
/*
|
||
|
* Add local MAC address.
|
||
|
*/
|
||
|
Index = 0;
|
||
|
TempPtr = (u16 *)LocalMacAddr;
|
||
|
while (Index < MAC_ADDR_LEN) {
|
||
|
*TxFramePtr++ = *(TempPtr + Index);
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add local IP address.
|
||
|
*/
|
||
|
Index = 0;
|
||
|
TempPtr = (u16 *)LocalIpAddress;
|
||
|
while (Index < IP_ADDR_LEN) {
|
||
|
*TxFramePtr++ = *(TempPtr + Index);
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Fills 6 bytes of information with zeros as per protocol.
|
||
|
*/
|
||
|
Index = 0;
|
||
|
while (Index < 3) {
|
||
|
*TxFramePtr++ = 0x0000;
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add Destination IP address.
|
||
|
*/
|
||
|
Index = 0;
|
||
|
TempPtr = (u16 *)DestIpAddress;
|
||
|
while (Index < IP_ADDR_LEN) {
|
||
|
*TxFramePtr++ = *(TempPtr + Index);
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Transmit the Frame.
|
||
|
*/
|
||
|
XEmacLite_Send(InstancePtr, (u8 *)&TxFrame, ARP_REQ_PKT_SIZE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function will send a Echo request packet.
|
||
|
*
|
||
|
* @param InstancePtr is a pointer to the instance of the EmacLite.
|
||
|
*
|
||
|
* @return None.
|
||
|
*
|
||
|
* @note None.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static void SendEchoReqFrame(XEmacLite *InstancePtr)
|
||
|
{
|
||
|
u16 *TempPtr;
|
||
|
u16 *TxFramePtr;
|
||
|
u16 *RxFramePtr;
|
||
|
u16 CheckSum;
|
||
|
u32 NextTxBuffBaseAddr;
|
||
|
int Index;
|
||
|
|
||
|
TxFramePtr = (u16 *)TxFrame;
|
||
|
RxFramePtr = (u16 *)RxFrame;
|
||
|
|
||
|
/*
|
||
|
* Determine the next expected transmit buffer base address.
|
||
|
*/
|
||
|
NextTxBuffBaseAddr = XEmacLite_NextTransmitAddr(InstancePtr);
|
||
|
|
||
|
/*
|
||
|
* Add Destination MAC Address.
|
||
|
*/
|
||
|
Index = MAC_ADDR_LEN;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + Index) = *(DestMacAddr + Index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add Source MAC Address.
|
||
|
*/
|
||
|
Index = MAC_ADDR_LEN;
|
||
|
TempPtr = (u16 *)LocalMacAddr;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + (Index + SRC_MAC_ADDR_LOC )) =
|
||
|
*(TempPtr + Index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add IP header information.
|
||
|
*/
|
||
|
Index = IP_START_LOC;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + (Index + ETHER_PROTO_TYPE_LOC )) =
|
||
|
Xil_Htons(*(IpHeaderInfo + Index));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add Source IP address.
|
||
|
*/
|
||
|
Index = IP_ADDR_LEN;
|
||
|
TempPtr = (u16 *)LocalIpAddress;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + (Index + IP_REQ_SRC_IP_LOC )) =
|
||
|
*(TempPtr + Index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add Destination IP address.
|
||
|
*/
|
||
|
Index = IP_ADDR_LEN;
|
||
|
TempPtr = (u16 *)DestIpAddress;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + (Index + IP_REQ_DEST_IP_LOC )) =
|
||
|
*(TempPtr + Index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Checksum is calculated for IP field and added in the frame.
|
||
|
*/
|
||
|
CheckSum = CheckSumCalculation((u16 *)TxFrame, IP_START_LOC,
|
||
|
IP_HEADER_LEN);
|
||
|
CheckSum = ~CheckSum;
|
||
|
*(TxFramePtr + IP_CHECKSUM_LOC) = Xil_Htons(CheckSum);
|
||
|
|
||
|
/*
|
||
|
* Add echo field information.
|
||
|
*/
|
||
|
*(TxFramePtr + ICMP_ECHO_FIELD_LOC) = Xil_Htons(XEL_ETHER_PROTO_TYPE_IP);
|
||
|
|
||
|
/*
|
||
|
* Checksum value is initialized to zeros.
|
||
|
*/
|
||
|
*(TxFramePtr + ICMP_DATA_LEN) = 0x0000;
|
||
|
|
||
|
/*
|
||
|
* Add identifier and sequence number to the frame.
|
||
|
*/
|
||
|
*(TxFramePtr + ICMP_IDEN_FIELD_LOC) = (IDEN_NUM);
|
||
|
*(TxFramePtr + (ICMP_IDEN_FIELD_LOC + 1)) = Xil_Htons((u16)(++SeqNum));
|
||
|
|
||
|
/*
|
||
|
* Add known data to the frame.
|
||
|
*/
|
||
|
Index = ICMP_KNOWN_DATA_LEN;
|
||
|
while (Index--) {
|
||
|
*(TxFramePtr + (Index + ICMP_KNOWN_DATA_LOC)) =
|
||
|
Xil_Htons(*(IcmpData + Index));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Checksum is calculated for Data Field and added in the frame.
|
||
|
*/
|
||
|
CheckSum = CheckSumCalculation((u16 *)TxFrame, ICMP_DATA_START_LOC,
|
||
|
ICMP_DATA_FIELD_LEN );
|
||
|
CheckSum = ~CheckSum;
|
||
|
*(TxFramePtr + ICMP_DATA_CHECKSUM_LOC) = Xil_Htons(CheckSum);
|
||
|
|
||
|
/*
|
||
|
* Transmit the Frame.
|
||
|
*/
|
||
|
XEmacLite_Send(InstancePtr, (u8 *)&TxFrame, ICMP_PKT_SIZE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function will process the received packet. This function sends
|
||
|
* the echo request packet based on the ARP reply packet.
|
||
|
*
|
||
|
* @param InstancePtr is a pointer to the instance of the EmacLite.
|
||
|
*
|
||
|
* @return XST_SUCCESS is returned when an echo reply is received.
|
||
|
* Otherwise, XST_FAILURE is returned.
|
||
|
*
|
||
|
* @note This assumes MAC does not strip padding or CRC.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static int ProcessRecvFrame(XEmacLite *InstancePtr)
|
||
|
{
|
||
|
u16 *RxFramePtr;
|
||
|
u16 *TempPtr;
|
||
|
u16 CheckSum;
|
||
|
int Index;
|
||
|
int Match = 0;
|
||
|
int DataWrong = 0;
|
||
|
|
||
|
RxFramePtr = (u16 *)RxFrame;
|
||
|
TempPtr = (u16 *)LocalMacAddr;
|
||
|
|
||
|
/*
|
||
|
* Check Dest Mac address of the packet with the LocalMac address.
|
||
|
*/
|
||
|
Match = CompareData(RxFramePtr, TempPtr, 0, 0, MAC_ADDR_LEN);
|
||
|
if (Match == XST_SUCCESS) {
|
||
|
|
||
|
/*
|
||
|
* Check ARP type.
|
||
|
*/
|
||
|
if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) ==
|
||
|
XEL_ETHER_PROTO_TYPE_ARP ) {
|
||
|
|
||
|
/*
|
||
|
* Check ARP status.
|
||
|
*/
|
||
|
if (Xil_Ntohs(*(RxFramePtr + ARP_REQ_STATUS_LOC)) == ARP_REPLY) {
|
||
|
|
||
|
/*
|
||
|
* Check destination IP address with
|
||
|
* packet's source IP address.
|
||
|
*/
|
||
|
TempPtr = (u16 *)DestIpAddress;
|
||
|
Match = CompareData(RxFramePtr,
|
||
|
TempPtr, ARP_REQ_SRC_IP_LOC,
|
||
|
0, IP_ADDR_LEN);
|
||
|
if (Match == XST_SUCCESS) {
|
||
|
|
||
|
/*
|
||
|
* Copy src Mac address of the received
|
||
|
* packet.
|
||
|
*/
|
||
|
Index = MAC_ADDR_LEN;
|
||
|
TempPtr = (u16 *)DestMacAddr;
|
||
|
while (Index--) {
|
||
|
*(TempPtr + Index) =
|
||
|
*(RxFramePtr +
|
||
|
(SRC_MAC_ADDR_LOC +
|
||
|
Index));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Send Echo request packet.
|
||
|
*/
|
||
|
SendEchoReqFrame(InstancePtr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check for IP type.
|
||
|
*/
|
||
|
else if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) ==
|
||
|
XEL_ETHER_PROTO_TYPE_IP) {
|
||
|
|
||
|
/*
|
||
|
* Calculate checksum.
|
||
|
*/
|
||
|
CheckSum = CheckSumCalculation(RxFramePtr,
|
||
|
ICMP_DATA_START_LOC,
|
||
|
ICMP_DATA_FIELD_LEN);
|
||
|
|
||
|
/*
|
||
|
* Verify checksum, echo reply, identifier number and
|
||
|
* sequence number of the received packet.
|
||
|
*/
|
||
|
if ((CheckSum == CORRECT_CHECKSUM_VALUE) &&
|
||
|
(Xil_Ntohs(*(RxFramePtr + ICMP_ECHO_FIELD_LOC)) == ECHO_REPLY) &&
|
||
|
(Xil_Ntohs(*(RxFramePtr + ICMP_IDEN_FIELD_LOC)) == IDEN_NUM) &&
|
||
|
(Xil_Ntohs(*(RxFramePtr + (ICMP_SEQ_NO_LOC))) == SeqNum)) {
|
||
|
|
||
|
/*
|
||
|
* Verify data in the received packet with known
|
||
|
* data.
|
||
|
*/
|
||
|
TempPtr = IcmpData;
|
||
|
Match = CompareData(RxFramePtr,
|
||
|
TempPtr, ICMP_KNOWN_DATA_LOC,
|
||
|
0, ICMP_KNOWN_DATA_LEN);
|
||
|
if (Match == XST_FAILURE) {
|
||
|
DataWrong = 1;
|
||
|
}
|
||
|
}
|
||
|
if (DataWrong != 1) {
|
||
|
xil_printf("Packet No: %d ",
|
||
|
NUM_OF_PING_REQ_PKTS - NumOfPingReqPkts);
|
||
|
xil_printf("Seq NO %d Echo Packet received\r\n",
|
||
|
SeqNum);
|
||
|
return XST_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return XST_FAILURE;
|
||
|
}
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function calculates the checksum and returns a 16 bit result.
|
||
|
*
|
||
|
* @param RxFramePtr is a 16 bit pointer for the data to which checksum
|
||
|
* is to be calculated.
|
||
|
* @param StartLoc is the starting location of the data from which the
|
||
|
* checksum has to be calculated.
|
||
|
* @param Length is the number of halfwords(16 bits) to which checksum is
|
||
|
* to be calculated.
|
||
|
*
|
||
|
* @return It returns a 16 bit checksum value.
|
||
|
*
|
||
|
* @note This can also be used for calculating checksum. The ones
|
||
|
* complement of this return value will give the final checksum.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static u16 CheckSumCalculation(u16 *RxFramePtr, int StartLoc, int Length)
|
||
|
{
|
||
|
u32 Sum = 0;
|
||
|
u16 CheckSum = 0;
|
||
|
int Index;
|
||
|
|
||
|
/*
|
||
|
* Add all the 16 bit data.
|
||
|
*/
|
||
|
Index = StartLoc;
|
||
|
while (Index < (StartLoc + Length)) {
|
||
|
Sum = Sum + Xil_Htons(*(RxFramePtr + Index));
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add upper 16 bits to lower 16 bits.
|
||
|
*/
|
||
|
CheckSum = Sum;
|
||
|
Sum = Sum>>16;
|
||
|
CheckSum = Sum + CheckSum;
|
||
|
return CheckSum;
|
||
|
}
|
||
|
/*****************************************************************************/
|
||
|
/**
|
||
|
*
|
||
|
* This function checks the match for the specified number of half words.
|
||
|
*
|
||
|
* @param LhsPtr is a LHS entity pointer.
|
||
|
* @param RhsPtr is a RHS entity pointer.
|
||
|
* @param LhsLoc is a LHS entity location.
|
||
|
* @param RhsLoc is a RHS entity location.
|
||
|
* @param Count is the number of location which has to compared.
|
||
|
*
|
||
|
* @return XST_SUCCESS is returned when both the entities are same,
|
||
|
* otherwise XST_FAILURE is returned.
|
||
|
*
|
||
|
* @note None.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
static int CompareData(u16 *LhsPtr, u16 *RhsPtr, int LhsLoc, int RhsLoc,
|
||
|
int Count)
|
||
|
{
|
||
|
int Result;
|
||
|
while (Count--) {
|
||
|
if (*(LhsPtr + LhsLoc + Count) == *(RhsPtr + RhsLoc + Count)) {
|
||
|
Result = XST_SUCCESS;
|
||
|
} else {
|
||
|
Result = XST_FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return Result;
|
||
|
}
|
||
|
|