ENCx24J600 UDP backlog support from Maz Holtzberg
This commit is contained in:
parent
9bb771b8b8
commit
368867f06e
@ -5621,4 +5621,6 @@
|
||||
From Rashid Fatah (2013-9-23).
|
||||
* arch/arm/src/sama5/sam_hsmci.c: TX DMA disabled. It is just not
|
||||
reliable. No idea why. RX DMA is still used (2013-9-23).
|
||||
* driver/net/encx24j600.c: UDP/RXAVAIL backlog support from Max
|
||||
Holtzberg (2013-9-24).
|
||||
|
||||
|
@ -93,6 +93,7 @@ config ENCX24J600
|
||||
bool "Microchip ENCX24J600 support"
|
||||
default n
|
||||
select SPI
|
||||
select NET_RXAVAIL
|
||||
---help---
|
||||
References:
|
||||
ENC424J600/624J600 Data Sheet Stand-Alone 10/100 Ethernet Controller
|
||||
@ -123,6 +124,15 @@ config ENCX24J600_FREQUENCY
|
||||
---help---
|
||||
Define to use a different bus frequency
|
||||
|
||||
config ENCX24J600_NDESCR
|
||||
int "Descriptor Count"
|
||||
default 16
|
||||
---help---
|
||||
Defines how many descriptors are preallocated for the
|
||||
transmission and reception queues.
|
||||
The ENC has a relative large packet buffer of 24kB which can
|
||||
be used to buffer multiple packets silmutaneously
|
||||
|
||||
config ENCX24J600_STATS
|
||||
bool "Network statistics support"
|
||||
default n
|
||||
|
@ -2,7 +2,7 @@
|
||||
* drivers/net/encx24j600.c
|
||||
*
|
||||
* Copyright (C) 2013 UVC Ingenieure. All rights reserved.
|
||||
* Author: Max Holtberg <mh@uvc.de>
|
||||
* Author: Max Holztberg <mh@uvc.de>
|
||||
*
|
||||
* References:
|
||||
* - ENC424J600/624J600 Data Sheet, Stand-Alone 10/100 Ethernet Controller
|
||||
@ -151,6 +151,10 @@
|
||||
|
||||
#define ENC_TXTIMEOUT (60*CLK_TCK)
|
||||
|
||||
/* RX timeout (Time packets are held in the RX queue until they are dropped) */
|
||||
|
||||
#define ENC_RXTIMEOUT MSEC2TICK(2000)
|
||||
|
||||
/* Poll timeout */
|
||||
|
||||
#define ENC_POLLTIMEOUT MSEC2TICK(50)
|
||||
@ -160,7 +164,6 @@
|
||||
/* Packet memory layout */
|
||||
|
||||
#define PKTMEM_ALIGNED_BUFSIZE ((CONFIG_NET_BUFSIZE + 1) & ~1)
|
||||
#define PKTMEM_NDESCR ((PKTMEM_SIZE / 2) / PKTMEM_ALIGNED_BUFSIZE)
|
||||
#define PKTMEM_RX_START (PKTMEM_START + PKTMEM_SIZE / 2) /* Followed by RX buffer */
|
||||
#define PKTMEM_RX_END (PKTMEM_START + PKTMEM_SIZE - 2) /* RX buffer goes to the end of SRAM */
|
||||
|
||||
@ -204,6 +207,7 @@ struct enc_descr_s
|
||||
struct enc_descr_next *flink;
|
||||
uint16_t addr;
|
||||
uint16_t len;
|
||||
uint32_t ts; /* Timestamp of reception for timeout */
|
||||
};
|
||||
|
||||
/* The enc_driver_s encapsulates all state information for a single hardware
|
||||
@ -232,9 +236,10 @@ struct enc_driver_s
|
||||
struct work_s towork; /* Tx timeout work queue support */
|
||||
struct work_s pollwork; /* Poll timeout work queue support */
|
||||
|
||||
struct enc_descr_s descralloc[PKTMEM_NDESCR];
|
||||
sq_queue_t freedescr; /* The free descriptor list */
|
||||
sq_queue_t txqueue; /* Enqueued descriptors waiting for transmition */
|
||||
struct enc_descr_s descralloc[CONFIG_ENCX24J600_NDESCR];
|
||||
sq_queue_t freedescr; /* The free descriptor list */
|
||||
sq_queue_t txqueue; /* Enqueued descriptors waiting for transmition */
|
||||
sq_queue_t rxqueue; /* Unhandled incoming packets waiting for reception */
|
||||
|
||||
/* This is the contained SPI driver intstance */
|
||||
|
||||
@ -242,7 +247,7 @@ struct enc_driver_s
|
||||
|
||||
/* This holds the information visible to uIP/NuttX */
|
||||
|
||||
struct uip_driver_s dev; /* Interface understood by uIP */
|
||||
struct uip_driver_s dev; /* Interface understood by uIP */
|
||||
|
||||
/* Statistics */
|
||||
|
||||
@ -312,12 +317,18 @@ static int enc_txenqueue(FAR struct enc_driver_s *priv);
|
||||
static int enc_transmit(FAR struct enc_driver_s *priv);
|
||||
static int enc_uiptxpoll(struct uip_driver_s *dev);
|
||||
|
||||
/* Common RX logic */
|
||||
|
||||
static void enc_rxldpkt(FAR struct enc_driver_s *priv, struct enc_descr_s *descr);
|
||||
static void enc_rxrmpkt(FAR struct enc_driver_s *priv, struct enc_descr_s *descr);
|
||||
static void enc_rxdispatch(FAR struct enc_driver_s *priv);
|
||||
|
||||
/* Interrupt handling */
|
||||
|
||||
static void enc_linkstatus(FAR struct enc_driver_s *priv);
|
||||
static void enc_txif(FAR struct enc_driver_s *priv);
|
||||
static void enc_rxdispatch(FAR struct enc_driver_s *priv);
|
||||
static void enc_pktif(FAR struct enc_driver_s *priv);
|
||||
static void enc_rxabtif(FAR struct enc_driver_s *priv);
|
||||
static void enc_irqworker(FAR void *arg);
|
||||
static int enc_interrupt(int irq, FAR void *context);
|
||||
|
||||
@ -333,6 +344,7 @@ static void enc_polltimer(int argc, uint32_t arg, ...);
|
||||
static int enc_ifup(struct uip_driver_s *dev);
|
||||
static int enc_ifdown(struct uip_driver_s *dev);
|
||||
static int enc_txavail(struct uip_driver_s *dev);
|
||||
static int enc_rxavail(struct uip_driver_s *dev);
|
||||
#ifdef CONFIG_NET_IGMP
|
||||
static int enc_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
|
||||
static int enc_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
|
||||
@ -1140,6 +1152,7 @@ static int enc_txenqueue(FAR struct enc_driver_s *priv)
|
||||
}
|
||||
else
|
||||
{
|
||||
nlldbg("no free descriptors\n");
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1214,6 +1227,8 @@ static void enc_linkstatus(FAR struct enc_driver_s *priv)
|
||||
{
|
||||
uint16_t regval;
|
||||
|
||||
nllvdbg("link status changed\n");
|
||||
|
||||
/* Before transmitting the first packet after link establishment or
|
||||
* auto-negotiation, the MAC duplex configuration must be manually set to
|
||||
* match the duplex configuration of the PHY. To do this, configure
|
||||
@ -1276,6 +1291,105 @@ static void enc_txif(FAR struct enc_driver_s *priv)
|
||||
(void)uip_poll(&priv->dev, enc_uiptxpoll);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: enc_rxldpkt
|
||||
*
|
||||
* Description:
|
||||
* Load packet from the enc's RX buffer to the uip d_buf.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
* descr - Reference to the descriptor that should be loaded
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are enabled but the caller holds the uIP lock.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void enc_rxldpkt(FAR struct enc_driver_s *priv,
|
||||
struct enc_descr_s *descr)
|
||||
{
|
||||
DEBUGASSERT(priv != NULL && descr != NULL);
|
||||
|
||||
nllvdbg("load packet @%04x len: %d\n", descr->addr, descr->len);
|
||||
|
||||
/* Set the rx data pointer to the start of the received packet (ERXRDPT) */
|
||||
|
||||
enc_cmd(priv, ENC_WRXRDPT, descr->addr);
|
||||
|
||||
/* Save the packet length (without the 4 byte CRC) in priv->dev.d_len */
|
||||
|
||||
priv->dev.d_len = descr->len - 4;
|
||||
|
||||
/* Copy the data data from the receive buffer to priv->dev.d_buf */
|
||||
|
||||
enc_rdbuffer(priv, priv->dev.d_buf, priv->dev.d_len);
|
||||
|
||||
enc_dumppacket("loaded RX packet", priv->dev.d_buf, priv->dev.d_len);
|
||||
}
|
||||
|
||||
{
|
||||
nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: enc_rxrmpkt
|
||||
*
|
||||
* Description:
|
||||
* Remove packet from the RX queue and free the block of memory in the enc's
|
||||
* SRAM.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
* descr - Reference to the descriptor that should be freed
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are enabled but the caller holds the uIP lock.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void enc_rxrmpkt(FAR struct enc_driver_s *priv, struct enc_descr_s *descr)
|
||||
{
|
||||
uint16_t addr;
|
||||
|
||||
nllvdbg("free descr: %p\n", descr);
|
||||
|
||||
/* If it is the last descriptor in the queue, advance ERXTAIL.
|
||||
* This way it is possible that gaps occcur. Maybe pending packets
|
||||
* can be reordered th enc's DMA to free RX space?
|
||||
*/
|
||||
|
||||
if (descr == (struct enc_descr_s*)sq_peek(&priv->rxqueue))
|
||||
{
|
||||
/* @REVISIT wrap around? */
|
||||
|
||||
addr = descr->addr + descr->len - 2;
|
||||
|
||||
nllvdbg("set ERXTAIL to %04x\n", addr);
|
||||
|
||||
enc_wrreg(priv, ENC_ERXTAIL, addr);
|
||||
|
||||
/* Remove packet from RX queue */
|
||||
|
||||
sq_remfirst(&priv->rxqueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove packet from RX queue */
|
||||
|
||||
sq_rem((sq_entry_t*)descr, &priv->rxqueue);
|
||||
}
|
||||
|
||||
sq_addlast((sq_entry_t*)descr, &priv->freedescr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: enc_rxdispatch
|
||||
*
|
||||
@ -1295,45 +1409,87 @@ static void enc_txif(FAR struct enc_driver_s *priv)
|
||||
|
||||
static void enc_rxdispatch(FAR struct enc_driver_s *priv)
|
||||
{
|
||||
/* We only accept IP packets of the configured type and ARP packets */
|
||||
struct enc_descr_s *descr;
|
||||
struct enc_descr_s *next;
|
||||
|
||||
int ret = ERROR;
|
||||
|
||||
/* Process the RX queue */
|
||||
|
||||
descr = (struct enc_descr_s*)sq_peek(&priv->rxqueue);
|
||||
|
||||
while (descr != NULL)
|
||||
{
|
||||
/* Store the next pointer, because removing the item from list will set
|
||||
* flink to NULL
|
||||
*/
|
||||
|
||||
next = (struct enc_descr_s*)sq_next(descr);
|
||||
|
||||
/* Load the packet from the enc's SRAM */
|
||||
|
||||
enc_rxldpkt(priv, descr);
|
||||
|
||||
/* We only accept IP packets of the configured type and ARP packets */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
|
||||
if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
|
||||
#else
|
||||
if (BUF->type == HTONS(UIP_ETHTYPE_IP))
|
||||
if (BUF->type == HTONS(UIP_ETHTYPE_IP))
|
||||
#endif
|
||||
{
|
||||
nllvdbg("IP packet received (%02x)\n", BUF->type);
|
||||
uip_arp_ipin(&priv->dev);
|
||||
uip_input(&priv->dev);
|
||||
|
||||
/* If the above function invocation resulted in data that should be
|
||||
* sent out on the network, the field d_len will set to a value > 0.
|
||||
*/
|
||||
|
||||
if (priv->dev.d_len > 0)
|
||||
{
|
||||
uip_arp_out(&priv->dev);
|
||||
enc_txenqueue(priv);
|
||||
nllvdbg("Try to process IP packet (%02x)\n", BUF->type);
|
||||
|
||||
uip_arp_ipin(&priv->dev);
|
||||
ret = uip_input(&priv->dev);
|
||||
|
||||
if (ret == OK || (clock_systimer() - descr->ts) > ENC_RXTIMEOUT)
|
||||
{
|
||||
/* If packet has been sucessfully processed or has timed out,
|
||||
* free it.
|
||||
*/
|
||||
|
||||
enc_rxrmpkt(priv, descr);
|
||||
}
|
||||
|
||||
/* If the above function invocation resulted in data that should be
|
||||
* sent out on the network, the field d_len will set to a value > 0.
|
||||
*/
|
||||
|
||||
if (priv->dev.d_len > 0)
|
||||
{
|
||||
uip_arp_out(&priv->dev);
|
||||
enc_txenqueue(priv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (BUF->type == htons(UIP_ETHTYPE_ARP))
|
||||
{
|
||||
nllvdbg("ARP packet received (%02x)\n", BUF->type);
|
||||
uip_arp_arpin(&priv->dev);
|
||||
else if (BUF->type == htons(UIP_ETHTYPE_ARP))
|
||||
{
|
||||
nllvdbg("ARP packet received (%02x)\n", BUF->type);
|
||||
uip_arp_arpin(&priv->dev);
|
||||
|
||||
/* If the above function invocation resulted in data that should be
|
||||
* sent out on the network, the field d_len will set to a value > 0.
|
||||
*/
|
||||
/* ARP packets are freed immediately */
|
||||
|
||||
if (priv->dev.d_len > 0)
|
||||
{
|
||||
enc_txenqueue(priv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type));
|
||||
enc_rxrmpkt(priv, descr);
|
||||
|
||||
/* If the above function invocation resulted in data that should be
|
||||
* sent out on the network, the field d_len will set to a value > 0.
|
||||
*/
|
||||
|
||||
if (priv->dev.d_len > 0)
|
||||
{
|
||||
enc_txenqueue(priv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* free unsupported packet */
|
||||
|
||||
enc_rxrmpkt(priv, descr);
|
||||
|
||||
nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type));
|
||||
}
|
||||
|
||||
descr = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1356,94 +1512,156 @@ static void enc_rxdispatch(FAR struct enc_driver_s *priv)
|
||||
|
||||
static void enc_pktif(FAR struct enc_driver_s *priv)
|
||||
{
|
||||
struct enc_descr_s *descr;
|
||||
uint8_t rsv[8];
|
||||
uint16_t pktlen;
|
||||
uint32_t rxstat;
|
||||
uint16_t curpkt;
|
||||
int pktcnt;
|
||||
|
||||
DEBUGASSERT(priv->nextpkt >= PKTMEM_RX_START && priv->nextpkt <= PKTMEM_RX_END);
|
||||
|
||||
/* Set the rx data pointer to the start of the received packet (ERXRDPT) */
|
||||
|
||||
enc_cmd(priv, ENC_WRXRDPT, priv->nextpkt);
|
||||
|
||||
/* Read the next packet pointer and the 6 byte read status vector (RSV)
|
||||
* at the beginning of the received packet. (ERXRDPT should auto-increment
|
||||
* and wrap to the beginning of the read buffer as necessary)
|
||||
/* Enqueue all pending packets to the RX queue until PKTCNT == 0 or
|
||||
* no more descriptors are available.
|
||||
*/
|
||||
|
||||
enc_rdbuffer(priv, rsv, 8);
|
||||
pktcnt = (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) >> ESTAT_PKTCNT_SHIFT;
|
||||
|
||||
/* Decode the new next packet pointer, and the RSV. The
|
||||
* RSV is encoded as:
|
||||
*
|
||||
* Bits 0-15: Indicates length of the received frame. This includes the
|
||||
* destination address, source address, type/length, data,
|
||||
* padding and CRC fields. This field is stored in little-
|
||||
* endian format.
|
||||
* Bits 16-47: Bit encoded RX status.
|
||||
*/
|
||||
|
||||
priv->nextpkt = (uint16_t)rsv[1] << 8 | (uint16_t)rsv[0];
|
||||
pktlen = (uint16_t)rsv[3] << 8 | (uint16_t)rsv[2];
|
||||
rxstat = (uint32_t)rsv[7] << 24 | (uint32_t)rsv[6] << 16 |
|
||||
(uint32_t)rsv[5] << 8 | (uint32_t)rsv[4];
|
||||
|
||||
nllvdbg("Receiving packet, nextpkt: %04x pktlen: %d rxstat: %08x\n",
|
||||
priv->nextpkt, pktlen, rxstat);
|
||||
|
||||
/* Check if the packet was received OK */
|
||||
|
||||
if ((rxstat & RXSTAT_OK) == 0)
|
||||
while (pktcnt > 0)
|
||||
{
|
||||
nlldbg("ERROR: RXSTAT: %08x\n", rxstat);
|
||||
curpkt = priv->nextpkt;
|
||||
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
priv->stats.rxnotok++;
|
||||
#endif
|
||||
}
|
||||
/* Set the rx data pointer to the start of the received packet (ERXRDPT) */
|
||||
|
||||
/* Check for a usable packet length (4 added for the CRC) */
|
||||
enc_cmd(priv, ENC_WRXRDPT, curpkt);
|
||||
|
||||
else if (pktlen > (CONFIG_NET_BUFSIZE + 4) || pktlen <= (UIP_LLH_LEN + 4))
|
||||
{
|
||||
nlldbg("Bad packet size dropped (%d)\n", pktlen);
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
priv->stats.rxpktlen++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Otherwise, read and process the packet */
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the packet length (without the 4 byte CRC) in priv->dev.d_len */
|
||||
|
||||
priv->dev.d_len = pktlen - 4;
|
||||
|
||||
/* Copy the data data from the receive buffer to priv->dev.d_buf.
|
||||
* ERXRDPT should be correctly positioned from the last call to to
|
||||
* enc_rdbuffer (above).
|
||||
/* Read the next packet pointer and the 6 byte read status vector (RSV)
|
||||
* at the beginning of the received packet. (ERXRDPT should auto-increment
|
||||
* and wrap to the beginning of the read buffer as necessary)
|
||||
*/
|
||||
|
||||
enc_rdbuffer(priv, priv->dev.d_buf, priv->dev.d_len);
|
||||
enc_dumppacket("Received Packet", priv->dev.d_buf, priv->dev.d_len);
|
||||
enc_rdbuffer(priv, rsv, 8);
|
||||
|
||||
/* Dispatch the packet to uIP */
|
||||
/* Decode the new next packet pointer, and the RSV. The
|
||||
* RSV is encoded as:
|
||||
*
|
||||
* Bits 0-15: Indicates length of the received frame. This includes the
|
||||
* destination address, source address, type/length, data,
|
||||
* padding and CRC fields. This field is stored in little-
|
||||
* endian format.
|
||||
* Bits 16-47: Bit encoded RX status.
|
||||
*/
|
||||
|
||||
enc_rxdispatch(priv);
|
||||
priv->nextpkt = (uint16_t)rsv[1] << 8 | (uint16_t)rsv[0];
|
||||
pktlen = (uint16_t)rsv[3] << 8 | (uint16_t)rsv[2];
|
||||
rxstat = (uint32_t)rsv[7] << 24 | (uint32_t)rsv[6] << 16 |
|
||||
(uint32_t)rsv[5] << 8 | (uint32_t)rsv[4];
|
||||
|
||||
nllvdbg("Receiving packet, nextpkt: %04x pktlen: %d rxstat: %08x pktcnt: %d\n",
|
||||
priv->nextpkt, pktlen, rxstat, pktcnt);
|
||||
|
||||
/* Check if the packet was received OK */
|
||||
|
||||
if ((rxstat & RXSTAT_OK) == 0)
|
||||
{
|
||||
nlldbg("ERROR: RXSTAT: %08x\n", rxstat);
|
||||
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
priv->stats.rxnotok++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for a usable packet length (4 added for the CRC) */
|
||||
|
||||
else if (pktlen > (CONFIG_NET_BUFSIZE + 4) || pktlen <= (UIP_LLH_LEN + 4))
|
||||
{
|
||||
nlldbg("Bad packet size dropped (%d)\n", pktlen);
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
priv->stats.rxpktlen++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Otherwise, enqueue the packet to the RX queue */
|
||||
|
||||
else
|
||||
{
|
||||
descr = (struct enc_descr_s*)sq_remfirst(&priv->freedescr);
|
||||
|
||||
if (descr != NULL)
|
||||
{
|
||||
nllvdbg("allocated RX descriptor: %p\n", descr);
|
||||
|
||||
/* Set current timestamp */
|
||||
|
||||
descr->ts = clock_systimer();
|
||||
|
||||
/* Store the start address of the frame without the enc's header */
|
||||
|
||||
descr->addr = curpkt + 8;
|
||||
|
||||
descr->len = pktlen;
|
||||
|
||||
/* Enqueue packet */
|
||||
|
||||
sq_addlast((sq_entry_t*)descr, &priv->rxqueue);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
nlldbg("no free descriptors\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Decrement PKTCNT */
|
||||
|
||||
enc_bfs(priv, ENC_ECON1, ECON1_PKTDEC);
|
||||
|
||||
/* Read out again, maybe there has another packet arrived */
|
||||
|
||||
pktcnt = (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) >> ESTAT_PKTCNT_SHIFT;
|
||||
}
|
||||
|
||||
/* Once the whole frame has been processed, the final value of ERXTAIL should
|
||||
* be equal to (NextPacketPointer - 2).
|
||||
*/
|
||||
/* Process the RX queue */
|
||||
|
||||
/* @TODO check if no special handling needed (skip odd addresses?) */
|
||||
enc_wrreg(priv, ENC_ERXTAIL, priv->nextpkt - 2);
|
||||
enc_rxdispatch(priv);
|
||||
}
|
||||
|
||||
/* Decrement the packet counter indicate we are done with this packet */
|
||||
/****************************************************************************
|
||||
* Function: enc_rxabtif
|
||||
*
|
||||
* Description:
|
||||
* An interrupt was received indicating the abortion of an RX packet
|
||||
*
|
||||
* "The receive abort interrupt occurs when the reception of a frame has been
|
||||
* aborted. A frame being received is aborted when the Head Pointer attempts
|
||||
* to overrun the Tail Pointer, or when the packet counter has reached FFh.
|
||||
* In either case, the receive buffer is full and cannot fit the incoming
|
||||
* frame, so the packet has been dropped.
|
||||
* This interrupt does not occur when packets are dropped due to the receive
|
||||
* filters rejecting a packet. The interrupt should be cleared by software
|
||||
* once it has been serviced."
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are enabled but the caller holds the uIP lock.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void enc_rxabtif(FAR struct enc_driver_s *priv)
|
||||
{
|
||||
/* Free the last received packet from the RX queue */
|
||||
|
||||
enc_bfs(priv, ENC_ECON1, ECON1_PKTDEC);
|
||||
nlldbg("rx abort\n");
|
||||
|
||||
enc_rxrmpkt(priv, (struct enc_descr_s*)sq_peek(&priv->rxqueue));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1557,7 +1775,6 @@ static void enc_irqworker(FAR void *arg)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
|
||||
/* The transmit abort interrupt occurs when the transmission of a frame
|
||||
* has been aborted. An abort can occur for any of the following reasons:
|
||||
*
|
||||
@ -1584,6 +1801,7 @@ static void enc_irqworker(FAR void *arg)
|
||||
priv->stats.txerifs++;
|
||||
enc_bfc(priv, ENC_EIR, EIR_TXABTIF); /* Clear the TXABTIF interrupt */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The receive abort interrupt occurs when the reception of a frame has
|
||||
* been aborted. A frame being received is aborted when the Head Pointer
|
||||
@ -1600,13 +1818,18 @@ static void enc_irqworker(FAR void *arg)
|
||||
|
||||
if ((eir & EIR_RXABTIF) != 0) /* Receive Abort */
|
||||
{
|
||||
#ifdef CONFIG_ENCX24J600_STATS
|
||||
priv->stats.rxerifs++;
|
||||
#endif
|
||||
enc_rxabtif(priv);
|
||||
enc_bfc(priv, ENC_EIR, EIR_RXABTIF); /* Clear the RXABTIF interrupt */
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Enable GPIO interrupts */
|
||||
|
||||
priv->lower->enable(priv->lower);
|
||||
|
||||
/* Enable Ethernet interrupts */
|
||||
|
||||
enc_bfs(priv, ENC_EIE, EIE_INTIE);
|
||||
@ -1615,10 +1838,6 @@ static void enc_irqworker(FAR void *arg)
|
||||
|
||||
enc_unlock(priv);
|
||||
uip_unlock(lock);
|
||||
|
||||
/* Enable GPIO interrupts */
|
||||
|
||||
priv->lower->enable(priv->lower);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1686,10 +1905,9 @@ static void enc_toworker(FAR void *arg)
|
||||
nlldbg("Tx timeout\n");
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Get exclusive access to both uIP and the SPI bus. */
|
||||
/* Get exclusive access to uIP. */
|
||||
|
||||
lock = uip_lock();
|
||||
enc_lock(priv);
|
||||
|
||||
/* Increment statistics and dump debug info */
|
||||
|
||||
@ -1711,9 +1929,8 @@ static void enc_toworker(FAR void *arg)
|
||||
|
||||
(void)uip_poll(&priv->dev, enc_uiptxpoll);
|
||||
|
||||
/* Release lock on the SPI bus and uIP */
|
||||
/* Release uIP */
|
||||
|
||||
enc_unlock(priv);
|
||||
uip_unlock(lock);
|
||||
}
|
||||
|
||||
@ -2041,6 +2258,38 @@ static int enc_txavail(struct uip_driver_s *dev)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: enc_rxavail
|
||||
*
|
||||
* Description:
|
||||
* Driver callback invoked when new TX data is available. This is a
|
||||
* stimulus perform an out-of-cycle poll and, thereby, reduce the TX
|
||||
* latency.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Reference to the NuttX driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Called in normal user mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int enc_rxavail(struct uip_driver_s *dev)
|
||||
{
|
||||
FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
|
||||
|
||||
if (!sq_empty(&priv->rxqueue))
|
||||
{
|
||||
nlldbg("RX queue not empty, trying to dispatch\n");
|
||||
enc_rxdispatch(priv);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: enc_addmac
|
||||
*
|
||||
@ -2269,7 +2518,7 @@ static int enc_reset(FAR struct enc_driver_s *priv)
|
||||
int ret;
|
||||
uint16_t regval;
|
||||
|
||||
nlldbg("Reset\n");
|
||||
nllvdbg("Reset\n");
|
||||
|
||||
/* configure SPI for the ENCX24J600 */
|
||||
|
||||
@ -2322,8 +2571,9 @@ static int enc_reset(FAR struct enc_driver_s *priv)
|
||||
|
||||
sq_init(&priv->freedescr);
|
||||
sq_init(&priv->txqueue);
|
||||
sq_init(&priv->rxqueue);
|
||||
|
||||
for (i = 0; i < PKTMEM_NDESCR; i++)
|
||||
for (i = 0; i < CONFIG_ENCX24J600_NDESCR; i++)
|
||||
{
|
||||
priv->descralloc[i].addr = PKTMEM_START + PKTMEM_ALIGNED_BUFSIZE * i;
|
||||
sq_addlast((sq_entry_t*)&priv->descralloc[i], &priv->freedescr);
|
||||
@ -2346,7 +2596,7 @@ static int enc_reset(FAR struct enc_driver_s *priv)
|
||||
}
|
||||
while ((regval & PHSTAT1_ANDONE) != 0);
|
||||
|
||||
nlldbg("Auto-negotation completed\n");
|
||||
nllvdbg("Auto-negotation completed\n");
|
||||
|
||||
enc_linkstatus(priv);
|
||||
|
||||
@ -2397,6 +2647,7 @@ int enc_initialize(FAR struct spi_dev_s *spi,
|
||||
priv->dev.d_ifup = enc_ifup; /* I/F up (new IP address) callback */
|
||||
priv->dev.d_ifdown = enc_ifdown; /* I/F down callback */
|
||||
priv->dev.d_txavail = enc_txavail; /* New TX data callback */
|
||||
priv->dev.d_rxavail = enc_rxavail; /* RX wating callback */
|
||||
#ifdef CONFIG_NET_IGMP
|
||||
priv->dev.d_addmac = enc_addmac; /* Add multicast MAC address */
|
||||
priv->dev.d_rmmac = enc_rmmac; /* Remove multicast MAC address */
|
||||
|
Loading…
Reference in New Issue
Block a user