lwip: Removed support for lltemac.
Removed all files related to lltemac support. Signed-off-by: Anirudha Sarangi <anirudh@xilinx.com>
This commit is contained in:
parent
133715a74d
commit
dc4df44a44
8 changed files with 0 additions and 2099 deletions
|
@ -55,10 +55,6 @@
|
|||
#include "netif/xemacliteif.h"
|
||||
#endif
|
||||
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_TEMAC
|
||||
#include "netif/xlltemacif.h"
|
||||
#endif
|
||||
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
|
||||
#include "netif/xaxiemacif.h"
|
||||
#endif
|
||||
|
@ -149,20 +145,6 @@ xemac_add(struct netif *netif,
|
|||
);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
case xemac_type_xps_ll_temac:
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_TEMAC
|
||||
return netif_add(netif, ipaddr, netmask, gw,
|
||||
(void*)mac_baseaddr,
|
||||
xlltemacif_init,
|
||||
#if NO_SYS
|
||||
ethernet_input
|
||||
#else
|
||||
tcpip_input
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
case xemac_type_axi_ethernet:
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
|
||||
|
@ -242,17 +224,6 @@ xemacif_input(struct netif *netif)
|
|||
print("incorrect configuration: xps_ethernetlite drivers not present?");
|
||||
while(1);
|
||||
return 0;
|
||||
#endif
|
||||
case xemac_type_xps_ll_temac:
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_TEMAC
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
n_packets = xlltemacif_input(netif);
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
break;
|
||||
#else
|
||||
print("incorrect configuration: xps_ll_temac drivers not present?");
|
||||
while(1);
|
||||
return 0;
|
||||
#endif
|
||||
case xemac_type_axi_ethernet:
|
||||
#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
|
||||
|
|
|
@ -1,525 +0,0 @@
|
|||
/*
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <xparameters.h>
|
||||
|
||||
#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 "lwip/igmp.h"
|
||||
|
||||
#include "netif/etharp.h"
|
||||
#include "netif/xlltemacif.h"
|
||||
#include "netif/xadapter.h"
|
||||
#include "netif/xpqueue.h"
|
||||
|
||||
#include "xlltemacif_fifo.h"
|
||||
#include "xlltemacif_hw.h"
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xintc.h"
|
||||
|
||||
|
||||
/* Define those to better describe your network interface. */
|
||||
#define IFNAME0 't'
|
||||
#define IFNAME1 'e'
|
||||
|
||||
#if LWIP_IGMP
|
||||
static err_t xlltemacif_mac_filter_update (struct netif *netif, struct ip_addr *group,
|
||||
u8_t action);
|
||||
|
||||
static u8_t xlltemac_mcast_entry_mask = 0;
|
||||
#endif
|
||||
/*
|
||||
* this function is always called with interrupts off
|
||||
* this function also assumes that there are available BD's
|
||||
*/
|
||||
static err_t
|
||||
_unbuffered_low_level_output(xlltemacif_s *xlltemacif, struct pbuf *p)
|
||||
{
|
||||
XStatus status = 0;
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
if (XLlTemac_IsDma(&xlltemacif->lltemac))
|
||||
status = lldma_sgsend(xlltemacif, p);
|
||||
else
|
||||
status = xllfifo_send(xlltemacif, p);
|
||||
|
||||
if (status != XST_SUCCESS) {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
}
|
||||
int
|
||||
is_tx_space_available(xlltemacif_s *emac)
|
||||
{
|
||||
if (XLlTemac_IsDma(&emac->lltemac)) {
|
||||
XLlDma_BdRing *txring = &XLlDma_GetTxRing(&emac->lldma);
|
||||
|
||||
/* tx space is available as long as there are valid BD's */
|
||||
return XLlDma_BdRingGetFreeCnt(txring);
|
||||
} else {
|
||||
return ((XLlFifo_TxVacancy(&emac->llfifo) * 4) > XTE_MAX_FRAME_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
err_t err;
|
||||
|
||||
struct xemac_s *xemac = (struct xemac_s *)(netif->state);
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
|
||||
/* check if space is available to send */
|
||||
if (is_tx_space_available(xlltemacif)) {
|
||||
_unbuffered_low_level_output(xlltemacif, p);
|
||||
err = ERR_OK;
|
||||
} else {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
print("pack dropped, no space\r\n");
|
||||
err = ERR_MEM;
|
||||
}
|
||||
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct xemac_s *xemac = (struct xemac_s *)(netif->state);
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
struct pbuf *p;
|
||||
|
||||
/* see if there is data to process */
|
||||
if (pq_qlength(xlltemacif->recv_q) == 0)
|
||||
return NULL;
|
||||
|
||||
/* return one packet from receive q */
|
||||
p = (struct pbuf *)pq_dequeue(xlltemacif->recv_q);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* xlltemacif_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
|
||||
xlltemacif_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
{
|
||||
/* resolve hardware address, then send (or queue) packet */
|
||||
return etharp_output(netif, p, ipaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* xlltemacif_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.
|
||||
*
|
||||
* Returns the number of packets read (max 1 packet on success,
|
||||
* 0 if there are no packets)
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
xlltemacif_input(struct netif *netif)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
struct pbuf *p;
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
p = low_level_input(netif);
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
/* no packet could be read, silently ignore this */
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
ethhdr = p->payload;
|
||||
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
/* IP or ARP packet? */
|
||||
case ETHTYPE_IP:
|
||||
case ETHTYPE_ARP:
|
||||
#if PPPOE_SUPPORT
|
||||
/* PPPoE packet? */
|
||||
case ETHTYPE_PPPOEDISC:
|
||||
case ETHTYPE_PPPOE:
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("xlltemacif_input: IP input error\r\n"));
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static err_t
|
||||
low_level_init(struct netif *netif)
|
||||
{
|
||||
unsigned mac_address = (unsigned)(netif->state);
|
||||
struct xemac_s *xemac;
|
||||
xlltemacif_s *xlltemacif;
|
||||
|
||||
xlltemacif = mem_malloc(sizeof *xlltemacif);
|
||||
if (xlltemacif == NULL) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("xlltemacif_init: out of memory\r\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
xemac = mem_malloc(sizeof *xemac);
|
||||
if (xemac == NULL) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("xlltemacif_init: out of memory\r\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
xemac->state = (void *)xlltemacif;
|
||||
xemac->topology_index = xtopology_find_index(mac_address);
|
||||
xemac->type = xemac_type_xps_ll_temac;
|
||||
|
||||
xlltemacif->send_q = NULL;
|
||||
xlltemacif->recv_q = pq_create_queue();
|
||||
if (!xlltemacif->recv_q)
|
||||
return ERR_MEM;
|
||||
|
||||
/* maximum transfer unit */
|
||||
#ifdef USE_JUMBO_FRAMES
|
||||
netif->mtu = XTE_JUMBO_MTU - XTE_HDR_SIZE;
|
||||
#else
|
||||
netif->mtu = XTE_MTU - XTE_HDR_SIZE;
|
||||
#endif
|
||||
#if LWIP_IGMP
|
||||
netif->igmp_mac_filter = xlltemacif_mac_filter_update;
|
||||
#endif
|
||||
|
||||
/* broadcast capability */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||
|
||||
#if LWIP_IGMP
|
||||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
#endif
|
||||
|
||||
#if !NO_SYS
|
||||
sys_sem_new(&xemac->sem_rx_data_available, 0);
|
||||
#endif
|
||||
/* initialize the mac */
|
||||
init_lltemac(xlltemacif, netif);
|
||||
|
||||
/* figure out if the system has DMA */
|
||||
if (XLlTemac_IsDma(&xlltemacif->lltemac)) {
|
||||
/* initialize the DMA engine */
|
||||
init_sdma(xemac);
|
||||
} else if (XLlTemac_IsFifo(&xlltemacif->lltemac)) {
|
||||
/* initialize the locallink FIFOs */
|
||||
init_ll_fifo(xemac);
|
||||
} else {
|
||||
/* should not occur */
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("xlltemacif_init: lltemac is not configured with DMA or FIFO\r\n"));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
/* replace the state in netif (currently the emac baseaddress)
|
||||
* with the xlltemac instance pointer.
|
||||
*/
|
||||
netif->state = (void *)xemac;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
static err_t
|
||||
xlltemacif_mac_filter_update (struct netif *netif, struct ip_addr *group,
|
||||
u8_t action)
|
||||
{
|
||||
err_t return_val = ERR_OK;
|
||||
u8_t multicast_mac_addr[6];
|
||||
u8_t multicast_mac_addr_to_clr[6];
|
||||
u8_t temp_mask;
|
||||
int entry;
|
||||
int i;
|
||||
u8_t * ip_addr_temp = (u8_t *)group;
|
||||
struct xemac_s *xemac = (struct xemac_s *)(netif->state);
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
|
||||
if (action == IGMP_ADD_MAC_FILTER) {
|
||||
if ((ip_addr_temp[0] >= 224) && (ip_addr_temp[0] <= 239)) {
|
||||
if (xlltemac_mcast_entry_mask >= 0x0F) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: No multicast address registers left.\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" Multicast MAC address add operation failure !!\r\n"));
|
||||
|
||||
return_val = ERR_MEM;
|
||||
} else {
|
||||
for (i = 0; i < 4; i++) {
|
||||
temp_mask = (0x01) << i;
|
||||
if ((xlltemac_mcast_entry_mask &
|
||||
temp_mask) == temp_mask) {
|
||||
|
||||
continue;
|
||||
|
||||
} else {
|
||||
entry = i;
|
||||
xlltemac_mcast_entry_mask |=
|
||||
temp_mask;
|
||||
multicast_mac_addr[0] = 0x01;
|
||||
multicast_mac_addr[1] = 0x00;
|
||||
multicast_mac_addr[2] = 0x5E;
|
||||
|
||||
multicast_mac_addr[3] =
|
||||
ip_addr_temp[1] & 0x7F;
|
||||
multicast_mac_addr[4] =
|
||||
ip_addr_temp[2];
|
||||
multicast_mac_addr[5] =
|
||||
ip_addr_temp[3];
|
||||
|
||||
XLlTemac_Stop
|
||||
(&xlltemacif->lltemac);
|
||||
|
||||
XLlTemac_MulticastAdd
|
||||
(&xlltemacif->lltemac,
|
||||
multicast_mac_addr,entry);
|
||||
|
||||
XLlTemac_Start
|
||||
(&xlltemacif->lltemac);
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: Muticast MAC address successfully added.\r\n"));
|
||||
|
||||
return_val = ERR_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 4) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: No multicast address registers left.\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" Multicast MAC address add operation failure !!\r\n"));
|
||||
|
||||
return_val = ERR_MEM;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: The requested MAC address is not a multicast address.\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" Multicast address add operation failure !!\r\n"));
|
||||
|
||||
return_val = ERR_ARG;
|
||||
}
|
||||
} else if (action == IGMP_DEL_MAC_FILTER) {
|
||||
if ((ip_addr_temp[0] < 224) || (ip_addr_temp[0] > 239)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: The requested MAC address is not a multicast address.\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" Multicast address add operation failure !!\r\n"));
|
||||
|
||||
return_val = ERR_ARG;
|
||||
} else {
|
||||
for (i = 0; i < 4; i++) {
|
||||
temp_mask = (0x01) << i;
|
||||
if ((xlltemac_mcast_entry_mask & temp_mask)
|
||||
== temp_mask) {
|
||||
XLlTemac_MulticastGet
|
||||
(&xlltemacif->lltemac,
|
||||
multicast_mac_addr_to_clr, i);
|
||||
|
||||
if ((ip_addr_temp[3] ==
|
||||
multicast_mac_addr_to_clr[5]) &&
|
||||
(ip_addr_temp[2] ==
|
||||
multicast_mac_addr_to_clr[4]) &&
|
||||
((ip_addr_temp[1] & 0x7f) ==
|
||||
multicast_mac_addr_to_clr[3])) {
|
||||
|
||||
XLlTemac_Stop
|
||||
(&xlltemacif->lltemac);
|
||||
|
||||
XLlTemac_MulticastClear
|
||||
(&xlltemacif->lltemac, i);
|
||||
|
||||
XLlTemac_Start
|
||||
(&xlltemacif->lltemac);
|
||||
|
||||
return_val = ERR_OK;
|
||||
xlltemac_mcast_entry_mask
|
||||
&= (~temp_mask);
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i == 4) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
("xlltemacif_mac_filter_update: No multicast address registers present with\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" the requested Multicast MAC address.\r\n"));
|
||||
LWIP_DEBUGF(NETIF_DEBUG,
|
||||
(" Multicast MAC address removal failure!!.\r\n"));
|
||||
|
||||
return_val = ERR_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return return_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* xlltemacif_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
|
||||
xlltemacif_init(struct netif *netif)
|
||||
{
|
||||
#if LWIP_SNMP
|
||||
/* ifType ethernetCsmacd(6) @see RFC1213 */
|
||||
netif->link_type = 6;
|
||||
/* your link speed here */
|
||||
netif->link_speed = ;
|
||||
netif->ts = 0;
|
||||
netif->ifinoctets = 0;
|
||||
netif->ifinucastpkts = 0;
|
||||
netif->ifinnucastpkts = 0;
|
||||
netif->ifindiscards = 0;
|
||||
netif->ifoutoctets = 0;
|
||||
netif->ifoutucastpkts = 0;
|
||||
netif->ifoutnucastpkts = 0;
|
||||
netif->ifoutdiscards = 0;
|
||||
#endif
|
||||
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
netif->output = xlltemacif_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
low_level_init(netif);
|
||||
|
||||
#if 0
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
|
@ -1,243 +0,0 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 - 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "lwipopts.h"
|
||||
|
||||
#if !NO_SYS
|
||||
#include "xmk.h"
|
||||
#include "sys/intr.h"
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "netif/xadapter.h"
|
||||
#include "netif/xlltemacif.h"
|
||||
|
||||
#include "xintc_l.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#include "xlltemacif_fifo.h"
|
||||
|
||||
#include "xlwipconfig.h"
|
||||
|
||||
static void
|
||||
xllfifo_recv_handler(struct xemac_s *xemac)
|
||||
{
|
||||
u32_t frame_length;
|
||||
struct pbuf *p;
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
XLlFifo *llfifo = &xlltemacif->llfifo;
|
||||
|
||||
/* While there is data in the fifo ... */
|
||||
while (XLlFifo_RxOccupancy(llfifo)) {
|
||||
/* find packet length */
|
||||
frame_length = XLlFifo_RxGetLen(llfifo);
|
||||
|
||||
/* allocate a pbuf */
|
||||
p = pbuf_alloc(PBUF_RAW, frame_length, PBUF_POOL);
|
||||
if (!p) {
|
||||
char tmp_frame[XTE_MAX_FRAME_SIZE];
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
/* receive and drop packet to keep data & len registers in sync */
|
||||
XLlFifo_Read(llfifo, tmp_frame, frame_length);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* receive packet */
|
||||
XLlFifo_Read(llfifo, p->payload, frame_length);
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
||||
#endif
|
||||
|
||||
/* store it in the receive queue, where it'll be processed by xemacif input thread */
|
||||
if (pq_enqueue(xlltemacif->recv_q, (void*)p) < 0) {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
pbuf_free(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
sys_sem_signal(&xemac->sem_rx_data_available);
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fifo_error_handler(xlltemacif_s *xlltemacif, u32_t pending_intr)
|
||||
{
|
||||
XLlFifo *llfifo = &xlltemacif->llfifo;
|
||||
|
||||
if (pending_intr & XLLF_INT_RPURE_MASK) {
|
||||
print("llfifo: Rx under-read error");
|
||||
}
|
||||
if (pending_intr & XLLF_INT_RPORE_MASK) {
|
||||
print("llfifo: Rx over-read error");
|
||||
}
|
||||
if (pending_intr & XLLF_INT_RPUE_MASK) {
|
||||
print("llfifo: Rx fifo empty");
|
||||
}
|
||||
if (pending_intr & XLLF_INT_TPOE_MASK) {
|
||||
print("llfifo: Tx fifo overrun");
|
||||
}
|
||||
if (pending_intr & XLLF_INT_TSE_MASK) {
|
||||
print("llfifo: Tx length mismatch");
|
||||
}
|
||||
|
||||
/* Reset the tx or rx side of the fifo as needed */
|
||||
if (pending_intr & XLLF_INT_RXERROR_MASK) {
|
||||
XLlFifo_IntClear(llfifo, XLLF_INT_RRC_MASK);
|
||||
XLlFifo_RxReset(llfifo);
|
||||
}
|
||||
|
||||
if (pending_intr & XLLF_INT_TXERROR_MASK) {
|
||||
XLlFifo_IntClear(llfifo, XLLF_INT_TRC_MASK);
|
||||
XLlFifo_TxReset(llfifo);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xllfifo_intr_handler(struct xemac_s *xemac)
|
||||
{
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
XLlFifo *llfifo = &xlltemacif->llfifo;
|
||||
|
||||
u32_t pending_fifo_intr = XLlFifo_IntPending(llfifo);
|
||||
|
||||
while (pending_fifo_intr) {
|
||||
if (pending_fifo_intr & XLLF_INT_RC_MASK) {
|
||||
/* receive interrupt */
|
||||
XLlFifo_IntClear(llfifo, XLLF_INT_RC_MASK);
|
||||
xllfifo_recv_handler(xemac);
|
||||
} else if (pending_fifo_intr & XLLF_INT_TC_MASK) {
|
||||
/* tx intr */
|
||||
XLlFifo_IntClear(llfifo, XLLF_INT_TC_MASK);
|
||||
} else {
|
||||
XLlFifo_IntClear(llfifo, XLLF_INT_ALL_MASK &
|
||||
~(XLLF_INT_RC_MASK |
|
||||
XLLF_INT_TC_MASK));
|
||||
fifo_error_handler(xlltemacif, pending_fifo_intr);
|
||||
}
|
||||
pending_fifo_intr = XLlFifo_IntPending(llfifo);
|
||||
}
|
||||
}
|
||||
|
||||
XStatus
|
||||
init_ll_fifo(struct xemac_s *xemac)
|
||||
{
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
#if NO_SYS
|
||||
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
|
||||
#endif
|
||||
|
||||
/* initialize ll fifo */
|
||||
XLlFifo_Initialize(&xlltemacif->llfifo,
|
||||
XLlTemac_LlDevBaseAddress(&xlltemacif->lltemac));
|
||||
|
||||
/* Clear any pending FIFO interrupts */
|
||||
XLlFifo_IntClear(&xlltemacif->llfifo, XLLF_INT_ALL_MASK);
|
||||
|
||||
/* enable fifo interrupts */
|
||||
XLlFifo_IntEnable(&xlltemacif->llfifo, XLLF_INT_ALL_MASK);
|
||||
|
||||
#if NO_SYS
|
||||
/* Register temac interrupt with interrupt controller */
|
||||
XIntc_RegisterHandler(xtopologyp->intc_baseaddr,
|
||||
xlltemacif->lltemac.Config.TemacIntr,
|
||||
(XInterruptHandler)xlltemac_error_handler,
|
||||
&xlltemacif->lltemac);
|
||||
|
||||
/* connect & enable FIFO interrupt */
|
||||
XIntc_RegisterHandler(xtopologyp->intc_baseaddr,
|
||||
xlltemacif->lltemac.Config.LLFifoIntr,
|
||||
(XInterruptHandler)xllfifo_intr_handler,
|
||||
xemac);
|
||||
|
||||
/* Enable EMAC interrupts in the interrupt controller */
|
||||
do {
|
||||
/* read current interrupt enable mask */
|
||||
unsigned int cur_mask = XIntc_In32(xtopologyp->intc_baseaddr + XIN_IER_OFFSET);
|
||||
|
||||
/* form new mask enabling SDMA & ll_temac interrupts */
|
||||
cur_mask = cur_mask
|
||||
| (1 << xlltemacif->lltemac.Config.LLFifoIntr)
|
||||
| (1 << xlltemacif->lltemac.Config.TemacIntr);
|
||||
|
||||
/* set new mask */
|
||||
XIntc_EnableIntr(xtopologyp->intc_baseaddr, cur_mask);
|
||||
} while (0);
|
||||
#else
|
||||
/* connect & enable TEMAC interrupts */
|
||||
register_int_handler(xlltemacif->lltemac.Config.TemacIntr,
|
||||
(XInterruptHandler)xlltemac_error_handler,
|
||||
&xlltemacif->lltemac);
|
||||
enable_interrupt(xlltemacif->lltemac.Config.TemacIntr);
|
||||
|
||||
/* connect & enable FIFO interrupts */
|
||||
register_int_handler(xlltemacif->lltemac.Config.LLFifoIntr,
|
||||
(XInterruptHandler)xllfifo_intr_handler,
|
||||
xemac);
|
||||
enable_interrupt(xlltemacif->lltemac.Config.LLFifoIntr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XStatus
|
||||
xllfifo_send(xlltemacif_s *xlltemacif, struct pbuf *p)
|
||||
{
|
||||
XLlFifo *llfifo = &xlltemacif->llfifo;
|
||||
u32_t l = 0;
|
||||
struct pbuf *q;
|
||||
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
/* write frame data to FIFO */
|
||||
XLlFifo_Write(llfifo, q->payload, q->len);
|
||||
l += q->len;
|
||||
}
|
||||
|
||||
/* initiate transmit */
|
||||
XLlFifo_TxSetLen(llfifo, l);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __XLLTEMACIF_FIFO_H_
|
||||
#define __XLLTEMACIF_FIFO_H_
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "netif/xlltemacif.h"
|
||||
#include "xlwipconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
XStatus init_ll_fifo(struct xemac_s *xemac);
|
||||
XStatus xllfifo_send(xlltemacif_s *xlltemacif, struct pbuf *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,133 +0,0 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 - 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "netif/xlltemacif.h"
|
||||
#include "lwipopts.h"
|
||||
|
||||
static XLlTemac_Config *
|
||||
xlltemac_lookup_config(unsigned mac_base)
|
||||
{
|
||||
extern XLlTemac_Config XLlTemac_ConfigTable[];
|
||||
XLlTemac_Config *CfgPtr = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < XPAR_XLLTEMAC_NUM_INSTANCES; i++) {
|
||||
if (XLlTemac_ConfigTable[i].BaseAddress == mac_base) {
|
||||
CfgPtr = &XLlTemac_ConfigTable[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (CfgPtr);
|
||||
}
|
||||
|
||||
void
|
||||
init_lltemac(xlltemacif_s *xlltemacif, struct netif *netif)
|
||||
{
|
||||
int rdy;
|
||||
unsigned mac_address = (unsigned)(netif->state);
|
||||
unsigned link_speed = 1000;
|
||||
unsigned options;
|
||||
unsigned lock_message_printed = 0;
|
||||
|
||||
/* obtain config of this emac */
|
||||
XLlTemac_Config *mac_config = xlltemac_lookup_config(mac_address);
|
||||
|
||||
XLlTemac *xlltemacp = &xlltemacif->lltemac;
|
||||
|
||||
XLlTemac_CfgInitialize(xlltemacp, mac_config, mac_config->BaseAddress);
|
||||
|
||||
options = XLlTemac_GetOptions(xlltemacp);
|
||||
options |= XTE_FLOW_CONTROL_OPTION;
|
||||
options |= XTE_JUMBO_OPTION;
|
||||
options |= XTE_TRANSMITTER_ENABLE_OPTION;
|
||||
options |= XTE_RECEIVER_ENABLE_OPTION;
|
||||
options |= XTE_FCS_STRIP_OPTION;
|
||||
options |= XTE_MULTICAST_OPTION;
|
||||
XLlTemac_SetOptions(xlltemacp, options);
|
||||
XLlTemac_ClearOptions(xlltemacp, ~options);
|
||||
|
||||
/* set mac address */
|
||||
XLlTemac_SetMacAddress(xlltemacp, (Xuint8*)(netif->hwaddr));
|
||||
|
||||
/* make sure the hard TEMAC is ready */
|
||||
rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress,
|
||||
XTE_RDY_OFFSET);
|
||||
while ((rdy & XTE_RDY_HARD_ACS_RDY_MASK) == 0) {
|
||||
rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress,
|
||||
XTE_RDY_OFFSET);
|
||||
}
|
||||
|
||||
link_speed = Phy_Setup(xlltemacp);
|
||||
XLlTemac_SetOperatingSpeed(xlltemacp, link_speed);
|
||||
|
||||
/* Setting the operating speed of the MAC needs a delay. */
|
||||
{
|
||||
volatile int wait;
|
||||
for (wait=0; wait < 100000; wait++);
|
||||
for (wait=0; wait < 100000; wait++);
|
||||
}
|
||||
|
||||
/* in a soft temac implementation, we need to explicitly make sure that
|
||||
* the RX DCM has been locked. See xps_ll_temac manual for details.
|
||||
* This bit is guaranteed to be 1 for hard temac's
|
||||
*/
|
||||
lock_message_printed = 0;
|
||||
while (!(XLlTemac_ReadReg(xlltemacp->Config.BaseAddress, XTE_IS_OFFSET)
|
||||
& XTE_INT_RXDCM_LOCK_MASK)) {
|
||||
int first = 1;
|
||||
if (first) {
|
||||
print("Waiting for RX DCM to lock..");
|
||||
first = 0;
|
||||
lock_message_printed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_message_printed)
|
||||
print("RX DCM locked.\r\n");
|
||||
|
||||
/* start the temac */
|
||||
XLlTemac_Start(xlltemacp);
|
||||
|
||||
/* enable TEMAC interrupts */
|
||||
XLlTemac_IntEnable(xlltemacp, XTE_INT_RECV_ERROR_MASK);
|
||||
}
|
||||
|
||||
void
|
||||
xlltemac_error_handler(XLlTemac * Temac)
|
||||
{
|
||||
unsigned Pending = XLlTemac_IntPending(Temac);
|
||||
if (Pending & XTE_INT_RXFIFOOVR_MASK) {
|
||||
print("Temac error interrupt: Rx fifo over run\r\n");
|
||||
}
|
||||
XLlTemac_IntClear(Temac, Pending);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 - 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __XLLTEMACIF_HW_H_
|
||||
#define __XLLTEMACIF_HW_H_
|
||||
|
||||
#include "netif/xlltemacif.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void init_lltemac(xlltemacif_s *xlltemacif, struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,311 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of Advanced Micro Devices, Inc. nor the names
|
||||
* of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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 COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some portions copyright (c) 2008-2013 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Xilinx, Inc.
|
||||
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
|
||||
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
|
||||
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
|
||||
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
|
||||
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
|
||||
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
|
||||
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
|
||||
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
|
||||
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
|
||||
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "netif/xlltemacif.h"
|
||||
#include "lwipopts.h"
|
||||
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
|
||||
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
|
||||
|
||||
|
||||
#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \
|
||||
ADVERTISE_10HALF | ADVERTISE_100HALF)
|
||||
#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
||||
#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)
|
||||
|
||||
#define ADVERTISE_1000 0x0300
|
||||
|
||||
|
||||
#define IEEE_CONTROL_REG_OFFSET 0
|
||||
#define IEEE_STATUS_REG_OFFSET 1
|
||||
#define IEEE_AUTONEGO_ADVERTISE_REG 4
|
||||
#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
|
||||
#define IEEE_PARTNER_ABILITIES_2_REG_OFFSET 8
|
||||
#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
|
||||
#define IEEE_1000_ADVERTISE_REG_OFFSET 9
|
||||
#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
|
||||
#define IEEE_CTRL_LINKSPEED_MASK 0x0040
|
||||
#define IEEE_CTRL_LINKSPEED_1000M 0x0040
|
||||
#define IEEE_CTRL_LINKSPEED_100M 0x2000
|
||||
#define IEEE_CTRL_LINKSPEED_10M 0x0000
|
||||
#define IEEE_CTRL_RESET_MASK 0x8000
|
||||
#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
|
||||
#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
|
||||
#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
|
||||
#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
|
||||
#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
|
||||
#define IEEE_AN1_ABILITY_MASK 0x1FE0
|
||||
#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
|
||||
#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
|
||||
#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
|
||||
|
||||
#define PHY_DETECT_REG 1
|
||||
#define PHY_DETECT_MASK 0x1808
|
||||
|
||||
|
||||
static int detect_phy(XLlTemac *xlltemacp)
|
||||
{
|
||||
u16 phy_reg;
|
||||
u32 phy_addr;
|
||||
|
||||
for (phy_addr = 31; phy_addr > 0; phy_addr--) {
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr, PHY_DETECT_REG, &phy_reg);
|
||||
|
||||
if ((phy_reg != 0xFFFF) &&
|
||||
((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
|
||||
/* Found a valid PHY address */
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("XLlTemac detect_phy: PHY detected at address %d.\r\n", phy_addr));
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("XLlTemac detect_phy: PHY detected.\r\n"));
|
||||
return phy_addr;
|
||||
}
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("XLlTemac detect_phy: No PHY detected. Assuming a PHY at address 0\r\n"));
|
||||
|
||||
/* default to zero */
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
get_IEEE_phy_speed(XLlTemac *xlltemacp)
|
||||
{
|
||||
|
||||
u16 control;
|
||||
u16 status;
|
||||
u16 partner_capabilities;
|
||||
u16 partner_capabilities_1000;
|
||||
u16 phylinkspeed;
|
||||
u32 phy_addr = detect_phy(xlltemacp);
|
||||
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
ADVERTISE_1000);
|
||||
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100_AND_10);
|
||||
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
|
||||
IEEE_STAT_AUTONEGOTIATE_RESTART);
|
||||
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
control);
|
||||
|
||||
/* Read PHY control and status registers is successful. */
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
|
||||
if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) &&
|
||||
(status & IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
|
||||
|
||||
while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_STATUS_REG_OFFSET,
|
||||
&status);
|
||||
}
|
||||
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
|
||||
&partner_capabilities);
|
||||
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
|
||||
&partner_capabilities_1000);
|
||||
if (partner_capabilities_1000 &
|
||||
IEEE_AN3_ABILITY_MASK_1GBPS)
|
||||
return 1000;
|
||||
}
|
||||
|
||||
if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
|
||||
return 100;
|
||||
if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
|
||||
return 10;
|
||||
|
||||
xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
|
||||
__FUNCTION__);
|
||||
return 10;
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
/* Update TEMAC speed accordingly */
|
||||
if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
|
||||
|
||||
/* Get commanded link speed */
|
||||
phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
|
||||
|
||||
switch (phylinkspeed) {
|
||||
case (IEEE_CTRL_LINKSPEED_1000M):
|
||||
return 1000;
|
||||
case (IEEE_CTRL_LINKSPEED_100M):
|
||||
return 100;
|
||||
case (IEEE_CTRL_LINKSPEED_10M):
|
||||
return 10;
|
||||
default:
|
||||
xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
|
||||
__FUNCTION__, phylinkspeed);
|
||||
return 10;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
unsigned configure_IEEE_phy_speed(XLlTemac *xlltemacp, unsigned speed)
|
||||
{
|
||||
u16 control;
|
||||
u32 phy_addr = detect_phy(xlltemacp);
|
||||
|
||||
XLlTemac_PhyRead(xlltemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
&control);
|
||||
control &= ~IEEE_CTRL_LINKSPEED_1000M;
|
||||
control &= ~IEEE_CTRL_LINKSPEED_100M;
|
||||
control &= ~IEEE_CTRL_LINKSPEED_10M;
|
||||
|
||||
if (speed == 1000) {
|
||||
control |= IEEE_CTRL_LINKSPEED_1000M;
|
||||
}
|
||||
|
||||
else if (speed == 100) {
|
||||
control |= IEEE_CTRL_LINKSPEED_100M;
|
||||
/* Dont advertise PHY speed of 1000 Mbps */
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
0);
|
||||
/* Dont advertise PHY speed of 10 Mbps */
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_100);
|
||||
|
||||
}
|
||||
else if (speed == 10) {
|
||||
control |= IEEE_CTRL_LINKSPEED_10M;
|
||||
/* Dont advertise PHY speed of 1000 Mbps */
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_1000_ADVERTISE_REG_OFFSET,
|
||||
0);
|
||||
/* Dont advertise PHY speed of 100 Mbps */
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_AUTONEGO_ADVERTISE_REG,
|
||||
ADVERTISE_10);
|
||||
}
|
||||
|
||||
XLlTemac_PhyWrite(xlltemacp, phy_addr,
|
||||
IEEE_CONTROL_REG_OFFSET,
|
||||
control | IEEE_CTRL_RESET_MASK);
|
||||
{
|
||||
volatile int wait;
|
||||
for (wait=0; wait < 100000; wait++);
|
||||
for (wait=0; wait < 100000; wait++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned Phy_Setup (XLlTemac *xlltemacp)
|
||||
{
|
||||
unsigned link_speed = 1000;
|
||||
|
||||
if (XLlTemac_GetPhysicalInterface(xlltemacp) ==
|
||||
XTE_PHY_TYPE_RGMII_1_3) {
|
||||
; /* Add PHY initialization code for RGMII 1.3 */
|
||||
} else if (XLlTemac_GetPhysicalInterface(xlltemacp) ==
|
||||
XTE_PHY_TYPE_RGMII_2_0) {
|
||||
; /* Add PHY initialization code for RGMII 2.0 */
|
||||
} else if (XLlTemac_GetPhysicalInterface(xlltemacp) ==
|
||||
XTE_PHY_TYPE_SGMII) {
|
||||
; /* Add PHY initialization code for SGMII */
|
||||
} else if (XLlTemac_GetPhysicalInterface(xlltemacp) ==
|
||||
XTE_PHY_TYPE_1000BASE_X) {
|
||||
; /* Add PHY initialization code for 1000 Base-X */
|
||||
}
|
||||
/* set PHY <--> MAC data clock */
|
||||
#ifdef CONFIG_LINKSPEED_AUTODETECT
|
||||
link_speed = get_IEEE_phy_speed(xlltemacp);
|
||||
xil_printf("auto-negotiated link speed: %d\r\n", link_speed);
|
||||
#elif defined(CONFIG_LINKSPEED1000)
|
||||
link_speed = 1000;
|
||||
configure_IEEE_phy_speed(xlltemacp, link_speed);
|
||||
xil_printf("link speed: %d\r\n", link_speed);
|
||||
#elif defined(CONFIG_LINKSPEED100)
|
||||
link_speed = 100;
|
||||
configure_IEEE_phy_speed(xlltemacp, link_speed);
|
||||
xil_printf("link speed: %d\r\n", link_speed);
|
||||
#elif defined(CONFIG_LINKSPEED10)
|
||||
link_speed = 10;
|
||||
configure_IEEE_phy_speed(xlltemacp, link_speed);
|
||||
xil_printf("link speed: %d\r\n", link_speed);
|
||||
#endif
|
||||
return link_speed;
|
||||
}
|
|
@ -1,790 +0,0 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 - 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "lwipopts.h"
|
||||
|
||||
#if !NO_SYS
|
||||
#include "xmk.h"
|
||||
#include "sys/intr.h"
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
#include "netif/xadapter.h"
|
||||
#include "netif/xlltemacif.h"
|
||||
|
||||
#include "xintc_l.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#include "xlltemacif_fifo.h"
|
||||
|
||||
#include "xlwipconfig.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
#ifdef CONFIG_XTRACE
|
||||
#include "xtrace.h"
|
||||
#endif
|
||||
|
||||
/* Byte alignment of BDs */
|
||||
#define BD_ALIGNMENT (XLLDMA_BD_MINIMUM_ALIGNMENT*2)
|
||||
|
||||
//#define USE_STATIC_BDSPACE
|
||||
#ifdef USE_STATIC_BDSPACE
|
||||
#define RXBD_SPACE_BYTES XLlDma_BdRingMemCalc(BD_ALIGNMENT, XLWIP_CONFIG_N_RX_DESC)
|
||||
#define TXBD_SPACE_BYTES XLlDma_BdRingMemCalc(BD_ALIGNMENT, XLWIP_CONFIG_N_TX_DESC)
|
||||
char rx_bdspace[RXBD_SPACE_BYTES] __attribute__ ((aligned(BD_ALIGNMENT)));
|
||||
char tx_bdspace[TXBD_SPACE_BYTES] __attribute__ ((aligned(BD_ALIGNMENT)));
|
||||
#endif
|
||||
|
||||
static unsigned sdma_debug = 0;
|
||||
//#define SDMA_DEBUG
|
||||
|
||||
#ifdef SDMA_DEBUG
|
||||
void print_packet(char *p, int n)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < n; i+=16) {
|
||||
for (j = 0; j < 16; j++)
|
||||
xil_printf("%02x ", *p++&0xff);
|
||||
xil_printf("\r\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
process_sent_bds(XLlDma_BdRing *txring)
|
||||
{
|
||||
XLlDma_Bd *txbdset, *txbd;
|
||||
int n_bds, i;
|
||||
XStatus Status;
|
||||
|
||||
/* obtain a list of processed BD's */
|
||||
n_bds = XLlDma_BdRingFromHw(txring, XLLDMA_ALL_BDS, &txbdset);
|
||||
if (n_bds == 0)
|
||||
return -1;
|
||||
|
||||
/* free the pbuf associated with each BD */
|
||||
for (i = 0, txbd = txbdset; i < n_bds; i++) {
|
||||
struct pbuf *p = (struct pbuf *)XLlDma_BdGetId(txbd);
|
||||
pbuf_free(p);
|
||||
txbd = XLlDma_BdRingNext(txring, txbd);
|
||||
}
|
||||
|
||||
/* free the processed BD's */
|
||||
Status = XLlDma_BdRingFree(txring, n_bds, txbdset);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
lldma_send_handler(void *arg)
|
||||
{
|
||||
unsigned irq_status;
|
||||
struct xemac_s *xemac = (struct xemac_s *)(arg);
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
XLlDma_BdRing *TxRingPtr = &XLlDma_GetTxRing(&xlltemacif->lldma);
|
||||
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
|
||||
XLlTemac *xlltemac = &xlltemacif->lltemac;
|
||||
|
||||
/* Read pending interrupts */
|
||||
irq_status = XLlDma_BdRingGetIrq(TxRingPtr);
|
||||
|
||||
/* Acknowledge pending interrupts */
|
||||
XLlDma_BdRingAckIrq(TxRingPtr, irq_status);
|
||||
XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xlltemac->Config.LLDmaTxIntr);
|
||||
|
||||
/*
|
||||
* If error interrupt is asserted, raise error flag, reset the
|
||||
* hardware to recover from the error, and return with no further
|
||||
* processing.
|
||||
*/
|
||||
if ((irq_status & XLLDMA_IRQ_ALL_ERR_MASK)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("%s: Error: irq_status & XLLDMA_IRQ_ALL_ERR_MASK", __FUNCTION__));
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("lldma error interrupt is asserted\r\n"));
|
||||
XLlDma_Reset(&xlltemacif->lldma);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If Transmit done interrupt is asserted, process completed BD's */
|
||||
if ((irq_status & (XLLDMA_IRQ_DELAY_MASK | XLLDMA_IRQ_COALESCE_MASK))) {
|
||||
process_sent_bds(TxRingPtr);
|
||||
}
|
||||
}
|
||||
|
||||
#if !CHECKSUM_GEN_TCP
|
||||
static void
|
||||
_bd_csum_enable(XLlDma_Bd *bd)
|
||||
{
|
||||
XLlDma_BdWrite((bd), XLLDMA_BD_STSCTRL_USR0_OFFSET,
|
||||
(XLlDma_BdRead((bd), XLLDMA_BD_STSCTRL_USR0_OFFSET)
|
||||
| 1));
|
||||
}
|
||||
|
||||
static void
|
||||
_bd_csum_disable(XLlDma_Bd *bd)
|
||||
{
|
||||
XLlDma_BdWrite((bd), XLLDMA_BD_STSCTRL_USR0_OFFSET,
|
||||
(XLlDma_BdRead((bd), XLLDMA_BD_STSCTRL_USR0_OFFSET)
|
||||
& ~1));
|
||||
}
|
||||
|
||||
static void
|
||||
_bd_csum_set(XLlDma_Bd *bd, u16_t tx_csbegin, u16_t tx_csinsert, u16_t tx_csinit)
|
||||
{
|
||||
u32_t app1;
|
||||
|
||||
_bd_csum_enable(bd);
|
||||
|
||||
/* write start offset and insert offset into BD */
|
||||
app1 = ((u32_t)tx_csbegin << 16) | (u32_t) tx_csinsert;
|
||||
XLlDma_BdWrite(bd, XLLDMA_BD_USR1_OFFSET, app1);
|
||||
|
||||
/* insert init value */
|
||||
XLlDma_BdWrite(bd, XLLDMA_BD_USR2_OFFSET, tx_csinit);
|
||||
}
|
||||
#endif
|
||||
|
||||
XStatus
|
||||
lldma_sgsend(xlltemacif_s *xlltemacif, struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
int n_pbufs;
|
||||
XLlDma_Bd *txbdset, *txbd, *last_txbd = NULL;
|
||||
XStatus Status;
|
||||
XLlDma_BdRing *txring;
|
||||
unsigned max_frame_size;
|
||||
|
||||
#ifdef USE_JUMBO_FRAMES
|
||||
max_frame_size = XTE_MAX_JUMBO_FRAME_SIZE - 18;
|
||||
#else
|
||||
max_frame_size = XTE_MAX_FRAME_SIZE - 18;
|
||||
#endif
|
||||
|
||||
txring = &XLlDma_GetTxRing(&xlltemacif->lldma);
|
||||
|
||||
/* first count the number of pbufs */
|
||||
for (q = p, n_pbufs = 0; q != NULL; q = q->next)
|
||||
n_pbufs++;
|
||||
|
||||
/* obtain as many BD's */
|
||||
Status = XLlDma_BdRingAlloc(txring, n_pbufs, &txbdset);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error allocating RxBD"));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
for(q = p, txbd = txbdset; 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. */
|
||||
XLlDma_BdSetBufAddr(txbd, q->payload);
|
||||
if (q->len > max_frame_size)
|
||||
XLlDma_BdSetLength(txbd, max_frame_size);
|
||||
else
|
||||
XLlDma_BdSetLength(txbd, q->len);
|
||||
XLlDma_BdSetId(txbd, (void *)q);
|
||||
XLlDma_BdSetStsCtrl(txbd, 0);
|
||||
XCACHE_FLUSH_DCACHE_RANGE(q->payload, q->len);
|
||||
|
||||
#ifdef SDMA_DEBUG
|
||||
if (sdma_debug) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("sending packet:\r\n"));
|
||||
print_packet(q->payload, 60);
|
||||
}
|
||||
#endif
|
||||
|
||||
pbuf_ref(q);
|
||||
|
||||
last_txbd = txbd;
|
||||
txbd = XLlDma_BdRingNext(txring, txbd);
|
||||
}
|
||||
|
||||
if (n_pbufs == 1) {
|
||||
XLlDma_BdSetStsCtrl(txbdset, XLLDMA_BD_STSCTRL_SOP_MASK
|
||||
| XLLDMA_BD_STSCTRL_EOP_MASK);
|
||||
} else {
|
||||
/* in the first packet, set the SOP */
|
||||
XLlDma_BdSetStsCtrl(txbdset, XLLDMA_BD_STSCTRL_SOP_MASK);
|
||||
/* in the last packet, set the EOP */
|
||||
XLlDma_BdSetStsCtrl(last_txbd, XLLDMA_BD_STSCTRL_EOP_MASK);
|
||||
}
|
||||
|
||||
#if !CHECKSUM_GEN_TCP
|
||||
_bd_csum_disable(txbdset);
|
||||
|
||||
/* offload TCP checksum calculation to hardware */
|
||||
if (XLlTemac_IsTxCsum(&xlltemacif->lltemac)) {
|
||||
if (p->len > sizeof(struct ethip_hdr)) {
|
||||
struct ethip_hdr *ehdr = p->payload;
|
||||
u8_t proto = IPH_PROTO(&ehdr->ip);
|
||||
|
||||
/* check if it is a TCP packet */
|
||||
if (ehdr->eth.type == ETHTYPE_IP && proto == IP_PROTO_TCP) {
|
||||
u32_t iphdr_len, csum_insert_offset;
|
||||
u16_t tcp_len; /* TCP header length + data length in bytes */
|
||||
u16_t csum_init = 0;
|
||||
u16_t tcp_payload_offset;
|
||||
|
||||
/* determine length of IP header */
|
||||
iphdr_len = (IPH_HL(&ehdr->ip) * 4);
|
||||
|
||||
tcp_payload_offset = XTE_HDR_SIZE + iphdr_len;
|
||||
tcp_len = p->tot_len - tcp_payload_offset;
|
||||
|
||||
/* insert checksum at offset 16 for TCP, 6 for UDP */
|
||||
if (proto == IP_PROTO_TCP)
|
||||
csum_insert_offset = tcp_payload_offset + 16;
|
||||
else if (proto == IP_PROTO_UDP)
|
||||
csum_insert_offset = tcp_payload_offset + 6;
|
||||
else
|
||||
csum_insert_offset = 0;
|
||||
|
||||
/* compute pseudo header checksum value */
|
||||
csum_init = inet_chksum_pseudo(NULL,
|
||||
(ip_addr_t *)&ehdr->ip.src, (ip_addr_t *)&ehdr->ip.dest,
|
||||
proto, tcp_len);
|
||||
|
||||
/* init buffer descriptor */
|
||||
_bd_csum_set(txbdset, tcp_payload_offset, csum_insert_offset, ~csum_init);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* enq to h/w */
|
||||
return XLlDma_BdRingToHw(txring, n_pbufs, txbdset);
|
||||
}
|
||||
|
||||
void
|
||||
_setup_rx_bds(XLlDma_BdRing *rxring)
|
||||
{
|
||||
XLlDma_Bd *rxbd;
|
||||
int n_bds, i;
|
||||
XStatus Status;
|
||||
struct pbuf *p;
|
||||
|
||||
n_bds = XLlDma_BdRingGetFreeCnt(rxring);
|
||||
if (n_bds == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_bds; i++) {
|
||||
Status = XLlDma_BdRingAlloc(rxring, 1, &rxbd);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error allocating RxBD"));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_JUMBO_FRAMES
|
||||
p = pbuf_alloc(PBUF_RAW, XTE_MAX_JUMBO_FRAME_SIZE, PBUF_POOL);
|
||||
#else
|
||||
p = pbuf_alloc(PBUF_RAW, XTE_MAX_FRAME_SIZE, PBUF_POOL);
|
||||
#endif
|
||||
if (!p) {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
|
||||
#ifdef LWIP_STATS
|
||||
if (sdma_debug) {
|
||||
stats_display();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the BD. The BD template used in the call to XLlTemac_SgSetSpace()
|
||||
* set the "last" field of all RxBDs. Therefore we are not required to
|
||||
* issue a XLlDma_Bd_SetLast(rxbd) here.
|
||||
*/
|
||||
XLlDma_BdSetBufAddr(rxbd, p->payload);
|
||||
XLlDma_BdSetLength(rxbd, p->len);
|
||||
XLlDma_BdSetStsCtrl(rxbd, XLLDMA_BD_STSCTRL_SOP_MASK | XLLDMA_BD_STSCTRL_EOP_MASK);
|
||||
XLlDma_BdSetId(rxbd, p);
|
||||
XCACHE_FLUSH_DCACHE_RANGE(p, sizeof *p);
|
||||
XCACHE_FLUSH_DCACHE_RANGE(rxbd, sizeof *rxbd);
|
||||
|
||||
/* Enqueue to HW */
|
||||
Status = XLlDma_BdRingToHw(rxring, 1, rxbd);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to hardware: "));
|
||||
if (Status == XST_DMA_SG_LIST_ERROR)
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with XLlDma_BdRingAlloc()\r\n"));
|
||||
else
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value\r\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* zero out the checksum field of this packet
|
||||
*/
|
||||
void
|
||||
zero_checksum_field(struct pbuf *p)
|
||||
{
|
||||
/* the way checksum works in this implementation of lwIP is as follows:
|
||||
- if checksum offload is disabled, then lwIP stack performs all checksum calculations
|
||||
- if checksum is enabled,
|
||||
- if computed csum says packet is valid, then we zero out the checksum field
|
||||
- if computed csum says packet is invalid, we leave checksum as is
|
||||
- upper layer recomputes checksum if it finds a non-zero checksum value
|
||||
*/
|
||||
struct ethip_hdr *ehdr = p->payload;
|
||||
u32_t iphdr_len;
|
||||
u16_t tcp_payload_offset;
|
||||
u8_t proto = IPH_PROTO(&ehdr->ip);
|
||||
|
||||
iphdr_len = (IPH_HL(&ehdr->ip) * 4);
|
||||
tcp_payload_offset = XTE_HDR_SIZE + iphdr_len;
|
||||
|
||||
if (ehdr->eth.type == ETHTYPE_IP && proto == IP_PROTO_TCP) {
|
||||
/* set checksum = 0 */
|
||||
*(u16_t*)(p->payload + tcp_payload_offset + 16) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32_t
|
||||
csum_sub(u32_t csum, u16_t v)
|
||||
{
|
||||
csum += (u32_t)v;
|
||||
return csum + (csum < (u32_t)v);
|
||||
}
|
||||
|
||||
static u16_t
|
||||
extract_packet_len(XLlDma_Bd *rxbd) {
|
||||
u16_t packet_len = XLlDma_BdRead(rxbd, XLLDMA_BD_USR4_OFFSET) & 0x3fff;
|
||||
return packet_len;
|
||||
}
|
||||
|
||||
static u16_t
|
||||
extract_csum(XLlDma_Bd *rxbd) {
|
||||
u16_t csum = XLlDma_BdRead(rxbd, XLLDMA_BD_USR3_OFFSET) & 0xffff;
|
||||
return csum;
|
||||
}
|
||||
|
||||
/*
|
||||
* compare if the h/w computed checksum (stored in the rxbd)
|
||||
* equals the TCP checksum value in the packet
|
||||
*/
|
||||
int
|
||||
is_checksum_valid(XLlDma_Bd *rxbd, struct pbuf *p) {
|
||||
struct ethip_hdr *ehdr = p->payload;
|
||||
u8_t proto = IPH_PROTO(&ehdr->ip);
|
||||
|
||||
/* check if it is a TCP packet */
|
||||
if (ehdr->eth.type == ETHTYPE_IP && proto == IP_PROTO_TCP) {
|
||||
u32_t iphdr_len;
|
||||
u16_t csum_in_packet, csum_in_rxbd, pseudo_csum, iphdr_csum, padding_csum;
|
||||
u16_t tcp_payload_offset;
|
||||
u32_t computed_csum;
|
||||
u16_t padding_len, tcp_payload_len, packet_len;
|
||||
u16_t csum;
|
||||
|
||||
/* determine length of IP header */
|
||||
iphdr_len = (IPH_HL(&ehdr->ip) * 4);
|
||||
tcp_payload_offset = XTE_HDR_SIZE + iphdr_len;
|
||||
tcp_payload_len = IPH_LEN(&ehdr->ip) - IPH_HL(&ehdr->ip) * 4;
|
||||
packet_len = extract_packet_len(rxbd);
|
||||
padding_len = packet_len - tcp_payload_offset - tcp_payload_len;
|
||||
|
||||
csum_in_packet = *(u16_t*)(p->payload + tcp_payload_offset + 16);
|
||||
csum_in_rxbd = extract_csum(rxbd);
|
||||
pseudo_csum = inet_chksum_pseudo(NULL,
|
||||
(ip_addr_t *)&ehdr->ip.src, (ip_addr_t *)&ehdr->ip.dest,
|
||||
proto, tcp_payload_len);
|
||||
|
||||
/* xps_ll_temac computes the checksum of the packet starting at byte 14
|
||||
* we need to subtract the values of the ethernet & IP headers
|
||||
*/
|
||||
iphdr_csum = inet_chksum(p->payload + 14, tcp_payload_offset - 14);
|
||||
|
||||
/* compute csum of padding bytes, if any */
|
||||
padding_csum = inet_chksum(p->payload + p->tot_len - padding_len,
|
||||
padding_len);
|
||||
|
||||
/* get the h/w checksum value */
|
||||
computed_csum = (u32_t)csum_in_rxbd;
|
||||
|
||||
/* remove the effect of csumming the iphdr */
|
||||
computed_csum = csum_sub(computed_csum, ~iphdr_csum);
|
||||
|
||||
/* add in the pseudo csum */
|
||||
computed_csum = csum_sub(computed_csum, ~pseudo_csum);
|
||||
|
||||
/* remove any padding effect */
|
||||
computed_csum = csum_sub(computed_csum, ~padding_csum);
|
||||
|
||||
/* normalize computed csum */
|
||||
while (computed_csum >> 16) {
|
||||
computed_csum = (computed_csum & 0xffff) + (computed_csum >> 16);
|
||||
}
|
||||
|
||||
/* convert to 16 bits and take 1's complement */
|
||||
csum = (u16_t)computed_csum;
|
||||
csum = ~csum;
|
||||
|
||||
/* chksum is valid if: computed csum over the packet is 0 */
|
||||
return !csum;
|
||||
} else {
|
||||
/* just say yes to all other packets */
|
||||
/* the upper layers in the stack will compute and verify the checksum */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lldma_recv_handler(void *arg)
|
||||
{
|
||||
struct pbuf *p;
|
||||
unsigned irq_status, i;
|
||||
XLlDma_Bd *rxbd, *rxbdset;
|
||||
struct xemac_s *xemac = (struct xemac_s *)(arg);
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
XLlDma_BdRing *rxring = &XLlDma_GetRxRing(&xlltemacif->lldma);
|
||||
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
|
||||
XLlTemac *xlltemac = &xlltemacif->lltemac;
|
||||
|
||||
XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xlltemac->Config.LLDmaRxIntr);
|
||||
XLlDma_BdRingIntDisable(rxring, XLLDMA_CR_IRQ_ALL_EN_MASK);
|
||||
|
||||
/* Read pending interrupts */
|
||||
irq_status = XLlDma_BdRingGetIrq(rxring);
|
||||
|
||||
/* Acknowledge pending interrupts */
|
||||
XLlDma_BdRingAckIrq(rxring, irq_status);
|
||||
|
||||
/* If error interrupt is asserted, raise error flag, reset the
|
||||
* hardware to recover from the error, and return with no further
|
||||
* processing.
|
||||
*/
|
||||
if ((irq_status & XLLDMA_IRQ_ALL_ERR_MASK)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("LlDma: Error: irq_status & XLLDMA_IRQ_ALL_ERR_MASK"));
|
||||
XLlDma_Reset(&xlltemacif->lldma);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If Reception done interrupt is asserted, call RX call back function
|
||||
* to handle the processed BDs and then raise the according flag.
|
||||
*/
|
||||
if ((irq_status & (XLLDMA_IRQ_DELAY_MASK | XLLDMA_IRQ_COALESCE_MASK))) {
|
||||
int bd_processed;
|
||||
bd_processed = XLlDma_BdRingFromHw(rxring, XLLDMA_ALL_BDS, &rxbdset);
|
||||
|
||||
for (i = 0, rxbd = rxbdset; i < bd_processed; i++) {
|
||||
p = (struct pbuf *)XLlDma_BdGetId(rxbd);
|
||||
#ifdef USE_JUMBO_FRAMES
|
||||
XCACHE_INVALIDATE_DCACHE_RANGE(p->payload, XTE_MAX_JUMBO_FRAME_SIZE);
|
||||
#else
|
||||
XCACHE_INVALIDATE_DCACHE_RANGE(p->payload, XTE_MAX_FRAME_SIZE);
|
||||
#endif
|
||||
|
||||
#if !CHECKSUM_CHECK_TCP
|
||||
/* compare RX checksum to TCP checksum value */
|
||||
if (is_checksum_valid(rxbd, p)) {
|
||||
/* if checksum is correct, then we re-write
|
||||
* checksum field with 0's so the upper layer doesn't recompute
|
||||
*/
|
||||
zero_checksum_field(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDMA_DEBUG
|
||||
if (sdma_debug)
|
||||
print_packet(p->payload, 60);
|
||||
#endif
|
||||
|
||||
/* store it in the receive queue,
|
||||
* where it'll be processed by a different handler
|
||||
*/
|
||||
if (pq_enqueue(xlltemacif->recv_q, (void*)p) < 0) {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
pbuf_free(p);
|
||||
} else {
|
||||
#if !NO_SYS
|
||||
sys_sem_signal(&xemac->sem_rx_data_available);
|
||||
#endif
|
||||
}
|
||||
|
||||
rxbd = XLlDma_BdRingNext(rxring, rxbd);
|
||||
}
|
||||
|
||||
/* free up the BD's */
|
||||
XLlDma_BdRingFree(rxring, bd_processed, rxbdset);
|
||||
|
||||
/* return all the processed bd's back to the stack */
|
||||
/* _setup_rx_bds -> use XLlDma_BdRingGetFreeCnt */
|
||||
_setup_rx_bds(rxring);
|
||||
}
|
||||
|
||||
XLlDma_BdRingIntEnable(rxring, XLLDMA_CR_IRQ_ALL_EN_MASK);
|
||||
}
|
||||
|
||||
void *
|
||||
alloc_bdspace(int n_desc)
|
||||
{
|
||||
int space = XLlDma_BdRingMemCalc(BD_ALIGNMENT, n_desc);
|
||||
int padding = BD_ALIGNMENT*2;
|
||||
void *unaligned_mem = mem_malloc(space + padding*4);
|
||||
void *aligned_mem = (void *)(((unsigned)(unaligned_mem + BD_ALIGNMENT)) & ~(BD_ALIGNMENT - 1));
|
||||
|
||||
#ifdef SDMA_DEBUG
|
||||
xil_printf("unaligned_mem start: %8x, end: %8x\r\n", unaligned_mem, unaligned_mem + space + padding * 4);
|
||||
xil_printf(" aligned_mem start: %8x, end: %8x\r\n", aligned_mem, aligned_mem + space);
|
||||
#endif
|
||||
#if DEBUG
|
||||
assert(aligned_mem > unaligned_mem);
|
||||
assert(aligned_mem + space < unaligned_mem + space + padding);
|
||||
#endif
|
||||
return aligned_mem;
|
||||
}
|
||||
|
||||
XStatus
|
||||
init_sdma(struct xemac_s *xemac)
|
||||
{
|
||||
XLlDma_Bd BdTemplate;
|
||||
XLlDma_BdRing *RxRingPtr, *TxRingPtr;
|
||||
XLlDma_Bd *rxbd;
|
||||
struct pbuf *p;
|
||||
XStatus Status;
|
||||
int i;
|
||||
xlltemacif_s *xlltemacif = (xlltemacif_s *)(xemac->state);
|
||||
#if NO_SYS
|
||||
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
|
||||
#endif
|
||||
|
||||
/* initialize DMA */
|
||||
XLlDma_Initialize(&xlltemacif->lldma, xlltemacif->lltemac.Config.LLDevBaseAddress);
|
||||
|
||||
RxRingPtr = &XLlDma_GetRxRing(&xlltemacif->lldma);
|
||||
TxRingPtr = &XLlDma_GetTxRing(&xlltemacif->lldma);
|
||||
|
||||
xlltemacif->rx_bdspace = alloc_bdspace(XLWIP_CONFIG_N_RX_DESC);
|
||||
xlltemacif->tx_bdspace = alloc_bdspace(XLWIP_CONFIG_N_TX_DESC);
|
||||
|
||||
if (!xlltemacif->rx_bdspace || !xlltemacif->tx_bdspace) {
|
||||
xil_printf("%s@%d: Error: Unable to allocate memory for RX buffer descriptors",
|
||||
__FILE__, __LINE__);
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup RxBD space.
|
||||
*
|
||||
* Setup a BD template for the Rx channel. This template will be copied to
|
||||
* every RxBD. We will not have to explicitly set these again.
|
||||
*/
|
||||
XLlDma_BdClear(&BdTemplate);
|
||||
|
||||
/*
|
||||
* Create the RxBD ring
|
||||
*/
|
||||
#ifdef USE_STATIC_BDSPACE
|
||||
Status = XLlDma_BdRingCreate(RxRingPtr, (u32) &rx_bdspace,
|
||||
(u32) &rx_bdspace, BD_ALIGNMENT,
|
||||
XLWIP_CONFIG_N_RX_DESC);
|
||||
#else
|
||||
Status = XLlDma_BdRingCreate(RxRingPtr, (u32) xlltemacif->rx_bdspace,
|
||||
(u32) xlltemacif->rx_bdspace, BD_ALIGNMENT,
|
||||
XLWIP_CONFIG_N_RX_DESC);
|
||||
#endif
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
Status = XLlDma_BdRingClone(RxRingPtr, &BdTemplate);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the TxBD ring
|
||||
*/
|
||||
#ifdef USE_STATIC_BDSPACE
|
||||
Status = XLlDma_BdRingCreate(TxRingPtr, (u32) &tx_bdspace,
|
||||
(u32) &tx_bdspace, BD_ALIGNMENT,
|
||||
XLWIP_CONFIG_N_TX_DESC);
|
||||
#else
|
||||
Status = XLlDma_BdRingCreate(TxRingPtr, (u32) xlltemacif->tx_bdspace,
|
||||
(u32) xlltemacif->tx_bdspace, BD_ALIGNMENT,
|
||||
XLWIP_CONFIG_N_TX_DESC);
|
||||
#endif
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
/* We reuse the bd template, as the same one will work for both rx and tx. */
|
||||
Status = XLlDma_BdRingClone(TxRingPtr, &BdTemplate);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
/* enable DMA interrupts */
|
||||
XLlDma_BdRingIntEnable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);
|
||||
XLlDma_BdRingIntEnable(RxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);
|
||||
|
||||
/*
|
||||
* Allocate 1 RxBD. Note that TEMAC utilizes an in-place allocation
|
||||
* scheme. The returned rxbd will point to a free BD in the memory
|
||||
* segment setup with the call to XLlTemac_SgSetSpace()
|
||||
*/
|
||||
for (i = 0; i < XLWIP_CONFIG_N_RX_DESC - 1; i++) {
|
||||
Status = XLlDma_BdRingAlloc(RxRingPtr, 1, &rxbd);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error allocating RxBD"));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
#ifdef USE_JUMBO_FRAMES
|
||||
p = pbuf_alloc(PBUF_RAW, XTE_MAX_JUMBO_FRAME_SIZE, PBUF_POOL);
|
||||
#else
|
||||
p = pbuf_alloc(PBUF_RAW, XTE_MAX_FRAME_SIZE, PBUF_POOL);
|
||||
#endif
|
||||
if (!p) {
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the BD. The BD template used in the call to XLlTemac_SgSetSpace()
|
||||
* set the "last" field of all RxBDs. Therefore we are not required to
|
||||
* issue a XLlDma_Bd_SetLast(rxbd) here.
|
||||
*/
|
||||
XLlDma_BdSetBufAddr(rxbd, p->payload);
|
||||
XLlDma_BdSetLength(rxbd, p->len);
|
||||
XLlDma_BdSetStsCtrl(rxbd, XLLDMA_BD_STSCTRL_SOP_MASK | XLLDMA_BD_STSCTRL_EOP_MASK);
|
||||
XLlDma_BdSetId(rxbd, p);
|
||||
XCACHE_FLUSH_DCACHE_RANGE(p, sizeof *p);
|
||||
XCACHE_FLUSH_DCACHE_RANGE(rxbd, sizeof *rxbd);
|
||||
|
||||
/* Enqueue to HW */
|
||||
Status = XLlDma_BdRingToHw(RxRingPtr, 1, rxbd);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error committing RxBD to HW"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* start DMA */
|
||||
Status = XLlDma_BdRingStart(TxRingPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error failed to start TX BD ring"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XLlDma_BdRingStart(RxRingPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error failed to start RX BD ring"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XLlDma_BdRingSetCoalesce(TxRingPtr, XLWIP_CONFIG_N_TX_COALESCE, 1);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error setting coalescing settings\r\n"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XLlDma_BdRingSetCoalesce(RxRingPtr, XLWIP_CONFIG_N_RX_COALESCE, 1);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("Error setting coalescing settings\r\n"));
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
#if NO_SYS
|
||||
/* Register temac interrupt with interrupt controller */
|
||||
XIntc_RegisterHandler(xtopologyp->intc_baseaddr,
|
||||
xlltemacif->lltemac.Config.TemacIntr,
|
||||
(XInterruptHandler)xlltemac_error_handler,
|
||||
&xlltemacif->lltemac);
|
||||
|
||||
/* connect & enable DMA interrupts */
|
||||
XIntc_RegisterHandler(xtopologyp->intc_baseaddr,
|
||||
xlltemacif->lltemac.Config.LLDmaTxIntr,
|
||||
(XInterruptHandler)lldma_send_handler,
|
||||
xemac);
|
||||
XIntc_RegisterHandler(xtopologyp->intc_baseaddr,
|
||||
xlltemacif->lltemac.Config.LLDmaRxIntr,
|
||||
(XInterruptHandler)lldma_recv_handler,
|
||||
xemac);
|
||||
|
||||
/* Enable EMAC interrupts in the interrupt controller */
|
||||
do {
|
||||
/* read current interrupt enable mask */
|
||||
unsigned int cur_mask = XIntc_In32(xtopologyp->intc_baseaddr + XIN_IER_OFFSET);
|
||||
|
||||
/* form new mask enabling SDMA & ll_temac interrupts */
|
||||
cur_mask = cur_mask
|
||||
| (1 << xlltemacif->lltemac.Config.LLDmaTxIntr)
|
||||
| (1 << xlltemacif->lltemac.Config.LLDmaRxIntr)
|
||||
| (1 << xlltemacif->lltemac.Config.TemacIntr);
|
||||
|
||||
/* set new mask */
|
||||
XIntc_EnableIntr(xtopologyp->intc_baseaddr, cur_mask);
|
||||
} while (0);
|
||||
#else
|
||||
/* connect & enable TEMAC interrupts */
|
||||
register_int_handler(xlltemacif->lltemac.Config.TemacIntr,
|
||||
(XInterruptHandler)xlltemac_error_handler,
|
||||
&xlltemacif->lltemac);
|
||||
enable_interrupt(xlltemacif->lltemac.Config.TemacIntr);
|
||||
|
||||
/* connect & enable DMA interrupts */
|
||||
register_int_handler(xlltemacif->lltemac.Config.LLDmaTxIntr,
|
||||
(XInterruptHandler)lldma_send_handler,
|
||||
xemac);
|
||||
enable_interrupt(xlltemacif->lltemac.Config.LLDmaTxIntr);
|
||||
|
||||
register_int_handler(xlltemacif->lltemac.Config.LLDmaRxIntr,
|
||||
(XInterruptHandler)lldma_recv_handler,
|
||||
xemac);
|
||||
enable_interrupt(xlltemacif->lltemac.Config.LLDmaRxIntr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue