You are not logged in.
Hi,
I want to check destination IP address for the data I am sending. I made certain changes in the pollDataSource Function in warpmac:
warpmac_pollDataSource() {
unsigned int dIPAddr, dhostAddr;
unsigned short int temp;
if(XIo_In32(EMAC_FIFO_BaseAddr+XLLF_RDFO_OFFSET) > 0)
{
// 30 is the offset for destination IP Address in the RXFIFO_DATA
dIPAddr = XIo_In32(EMAC_FIFO_BaseAddr+XLLF_RDFD_OFFSET+30);
dhostAddr = dIPAddr & 0x000000FF;
xil_printf("host addr %d", dhostAddr);
//Clear the LLFIFO status bits
XIo_Out32(EMAC_FIFO_BaseAddr+XLLF_ISR_OFFSET, 0x0FFFFFFF);
//Call the ethernet packet handler
emacRx_handler();
}
}
But this always gives the dhostAddr as 0...Is there anything wrong with reading data offset before reading rx length and then doing DMA from fifo to buffer in emacrx_handler() ??
Please suggest how can this be done in case of temac & FIFO....we have done this successfully with reference design 12.1 which used emaclite..
Offline
The xps_ll_fifo does not have a memory mapped packet buffer. It operates as FIFO, moving packet payloads one 32-bit word per access, always from the same address. I suggest moving your IP address checking to the top-level dataFromNetwork callback, where a pointer to the full Ethernet payload is provided. (This works by using DMA to move Ethernet packets from the ll_fifo into one of the PHY packet buffers, which are memory mapped).
Offline
Hi,
As suggested we moved the IP address checking operation to higher level i.e after the DMA transfer of the payload is done. We made some more changes to the code shown below:
#define ETHER_TYPE_OFFSET 12
#define ETHER_PROTO_TYPE_IP 0x0800 /**< IP Protocol */
#define ETHER_PROTO_TYPE_ARP 0x0806 /**< ARP Protocol */
#define HEADER_IP_LENGTH_OFFSET 16 /**< IP Length Offset */
#define HEADER_IP_DESTIP_OFFSET 30 /** Destination IP address offset */
#define ARP_PACKET_TPA_OFFSET 38 /** TARGET PROTOCOL ADDRESS (IP ADDRESS OF DESTINATION) OFFSET 24 + 14 FOR ETHERNET*/
inline void warpmac_pollDataSource() {
if( controlStruct.enableEth == 0)
return;
warpmac_setDebugGPIO(0x1);
if(XIo_In32(EMAC_FIFO_BaseAddr+XLLF_RDFO_OFFSET) > 0)
{
XIo_Out32(EMAC_FIFO_BaseAddr+XLLF_ISR_OFFSET, 0x0FFFFFFF);
warpmac_setDebugGPIO(0x3);
emacRx_handler();
}
warpmac_setDebugGPIO(0x0);
return;
}
void emacRx_handler() {
unsigned int dIPAddr;
unsigned short RxPktLength=0;
void* pktBufPtr = NULL;
pktBufPtr = (void *)warpphy_getBuffAddr(1)+NUM_HEADER_BYTES;
//Wait for the DMA to be idle
warpmac_waitForDMA();
//Set DMA to non-increment source, increment dest addresses
XDmaCentral_SetControl(&DmaCentralInst, XDMC_DMACR_DEST_INCR_MASK);
//Read the Rx packet length; the packet must be read from the FIFO immediately after this read
RxPktLength = XIo_In32(EMAC_FIFO_BaseAddr+XLLF_RLF_OFFSET);
warpmac_setDebugGPIO(0x7);
//Transfer the Ethernet frame from the FIFO to the PHY buffer
XDmaCentral_Transfer(&DmaCentralInst,
(u8 *)(EMAC_FIFO_BaseAddr+XLLF_RDFD_OFFSET),
(u8 *)pktBufPtr,
RxPktLength);
ethType = XIo_In32((unsigned int )warpphy_getBuffAddr(1)+NUM_HEADER_BYTES+ETHER_TYPE_OFFSET);
ethType = (ethType >> 16) & 0x0000FFFF;
if (ethType == ETHER_PROTO_TYPE_ARP) {
dIPAddr = XIo_In32((unsigned int )warpphy_getBuffAddr(1)+NUM_HEADER_BYTES+ARP_PACKET_TPA_OFFSET);
dhostIPAddr = (dIPAddr & 0x000000FF);
xil_printf("IP %d\r\n", dhostIPAddr);
if(dhostIPAddr==2 || dhostIPAddr==3)
//some operation
}
else if (ethType == ETHER_PROTO_TYPE_IP) {
dIPAddr = XIo_In32((unsigned int )warpphy_getBuffAddr(empty.start->index)+NUM_HEADER_BYTES+HEADER_IP_DESTIP_OFFSET);
dhostIPAddr = (dIPAddr & 0x000000FF);
//xil_printf("IP %d\r\n", dhostIPAddr);
if(dhostIPAddr==2 || dhostIPAddr==3)
//some operation
}
warpmac_setDebugGPIO(0xF);
usr_dataFromNetworkLayer(RxPktLength, pktBufPtr);
return;
}
The changes were made keeping the suggestions of one previous post also in mind..
http://warp.rice.edu/forums/viewtopic.php?id=706
Now it is printing the IP values we are sending data to, but it is also printing lot of random values also besides those even when we are not sending any data....why is it so?? Please help..!!
Offline
Two things:
-In your two access to the packet buffer, you used "warpphy_getBuffAddr(empty.start->index)", while the code above actually copied the packet to "warpphy_getBuffAddr(1)". Maybe they're accessing different packets?
-The DMA is fast, but does take time to copy the full packet. Your code jumps directly from initiating the DMA transfer (XDmaCentral_Transfer) to accessing the destination of the transfer. It's entirely possible the DMA hasn't actually copied enough bytes yet. You can call warpmac_waitForDMA() to wait for the DMA to finish. It might also be possible to poll the DMA to monitor how many bytes have been transferred; you'd have to refer to its datasheet/driver for details.
Also, I would strongly recommend reverting warpmac.c and putting your custom packet-handling code in the top level dataFromNetworkLayer callback. This way your function will be called with a pointer to the just-received packet, wherever the framework copied it. It will also facilitate migrating your code to newer reference designs in the future.
Offline