summaryrefslogtreecommitdiff
path: root/nuttx/drivers/net
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-24 09:03:16 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-24 09:03:16 -0600
commit332ecad5b20f77e8fc05ad3c30503864891bab46 (patch)
treeb631d223033c08b3ab200aa0931d115441c0726a /nuttx/drivers/net
parent060571bf63632a3430b213fe75d15020c9f2f6b7 (diff)
downloadpx4-nuttx-332ecad5b20f77e8fc05ad3c30503864891bab46.tar.gz
px4-nuttx-332ecad5b20f77e8fc05ad3c30503864891bab46.tar.bz2
px4-nuttx-332ecad5b20f77e8fc05ad3c30503864891bab46.zip
ENCx24J600 UDP backlog support from Maz Holtzberg
Diffstat (limited to 'nuttx/drivers/net')
-rw-r--r--nuttx/drivers/net/Kconfig10
-rw-r--r--nuttx/drivers/net/encx24j600.c457
2 files changed, 364 insertions, 103 deletions
diff --git a/nuttx/drivers/net/Kconfig b/nuttx/drivers/net/Kconfig
index 133a7cc8c..49957149d 100644
--- a/nuttx/drivers/net/Kconfig
+++ b/nuttx/drivers/net/Kconfig
@@ -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
diff --git a/nuttx/drivers/net/encx24j600.c b/nuttx/drivers/net/encx24j600.c
index f4d163a33..1b724fa0b 100644
--- a/nuttx/drivers/net/encx24j600.c
+++ b/nuttx/drivers/net/encx24j600.c
@@ -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
@@ -1277,6 +1292,105 @@ static void enc_txif(FAR struct enc_driver_s *priv)
}
/****************************************************************************
+ * 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
*
* Description:
@@ -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);
+ {
+ nllvdbg("Try to process IP packet (%02x)\n", BUF->type);
- /* 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.
- */
+ 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)
+ if (priv->dev.d_len > 0)
+ {
+ uip_arp_out(&priv->dev);
+ enc_txenqueue(priv);
+ }
+ }
+ else if (BUF->type == htons(UIP_ETHTYPE_ARP))
{
- uip_arp_out(&priv->dev);
- enc_txenqueue(priv);
+ nllvdbg("ARP packet received (%02x)\n", BUF->type);
+ uip_arp_arpin(&priv->dev);
+
+ /* ARP packets are freed immediately */
+
+ 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 if (BUF->type == htons(UIP_ETHTYPE_ARP))
- {
- nllvdbg("ARP packet received (%02x)\n", BUF->type);
- uip_arp_arpin(&priv->dev);
+ else
+ {
+ /* free unsupported packet */
- /* 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.
- */
+ enc_rxrmpkt(priv, descr);
- if (priv->dev.d_len > 0)
- {
- enc_txenqueue(priv);
- }
- }
- else
- {
- nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type));
+ 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) */
+ /* Enqueue all pending packets to the RX queue until PKTCNT == 0 or
+ * no more descriptors are available.
+ */
- enc_cmd(priv, ENC_WRXRDPT, priv->nextpkt);
+ pktcnt = (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) >> ESTAT_PKTCNT_SHIFT;
- /* 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)
- */
+ while (pktcnt > 0)
+ {
+ curpkt = priv->nextpkt;
- enc_rdbuffer(priv, rsv, 8);
+ /* Set the rx data pointer to the start of the received packet (ERXRDPT) */
- /* 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_cmd(priv, ENC_WRXRDPT, curpkt);
- 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];
+ /* 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)
+ */
- nllvdbg("Receiving packet, nextpkt: %04x pktlen: %d rxstat: %08x\n",
- priv->nextpkt, pktlen, rxstat);
+ enc_rdbuffer(priv, rsv, 8);
- /* Check if the packet was received OK */
+ /* 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.
+ */
- if ((rxstat & RXSTAT_OK) == 0)
- {
- nlldbg("ERROR: RXSTAT: %08x\n", rxstat);
+ 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++;
+ priv->stats.rxnotok++;
#endif
- }
+ }
- /* Check for a usable packet length (4 added for the CRC) */
+ /* 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);
+ 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++;
+ priv->stats.rxpktlen++;
#endif
- }
+ }
- /* Otherwise, read and process the packet */
+ /* Otherwise, enqueue the packet to the RX queue */
- else
- {
- /* Save the packet length (without the 4 byte CRC) in priv->dev.d_len */
+ else
+ {
+ descr = (struct enc_descr_s*)sq_remfirst(&priv->freedescr);
- priv->dev.d_len = pktlen - 4;
+ if (descr != NULL)
+ {
+ nllvdbg("allocated RX descriptor: %p\n", descr);
- /* 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).
- */
+ /* Set current timestamp */
- enc_rdbuffer(priv, priv->dev.d_buf, priv->dev.d_len);
- enc_dumppacket("Received Packet", priv->dev.d_buf, priv->dev.d_len);
+ descr->ts = clock_systimer();
- /* Dispatch the packet to uIP */
+ /* Store the start address of the frame without the enc's header */
- enc_rxdispatch(priv);
+ 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);
}
@@ -2042,6 +2259,38 @@ static int enc_txavail(struct uip_driver_s *dev)
}
/****************************************************************************
+ * 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
*
* Description:
@@ -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 */