This patch removes all network device drivers which is based on NuttX uIP.
These drivers are not integrated with LwIP and does not work.
Change-Id: Ia7334ffc56ebd6aed83623ce928ed5a49565eeb6
Signed-off-by: EunBong Song <eunb.song@samsung.com>
CSRCS += telnet.c
endif
-ifeq ($(CONFIG_NET_DM90x0),y)
- CSRCS += dm90x0.c
-endif
-
-ifeq ($(CONFIG_NET_CS89x0),y)
- CSRCS += cs89x0.c
-endif
-
ifeq ($(CONFIG_ENC28J60),y)
CSRCS += enc28j60.c
endif
-ifeq ($(CONFIG_ENCX24J600),y)
- CSRCS += encx24j600.c
-endif
-
-ifeq ($(CONFIG_NET_VNET),y)
- CSRCS += vnet.c
-endif
-
-ifeq ($(CONFIG_NET_E1000),y)
- CSRCS += e1000.c
-endif
-
ifeq ($(CONFIG_NET_SLIP),y)
CSRCS += slip.c
endif
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2016 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/****************************************************************************
- * drivers/net/dm9x.c
- *
- * Copyright (C) 2007-2010, 2014 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * References: Davicom data sheets (DM9000-DS-F03-041906.pdf,
- * DM9010-DS-F01-103006.pdf) and looking at lots of other DM90x0
- * drivers.
- *
- * 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <tinyara/config.h>
-#if defined(CONFIG_NET) && defined(CONFIG_NET_DM90x0)
-
-/* Only one hardware interface supported at present (although there are
- * hooks throughout the design to that extending the support to multiple
- * interfaces should not be that difficult)
- */
-
-#undef CONFIG_DM9X_NINTERFACES
-#define CONFIG_DM9X_NINTERFACES 1
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <time.h>
-#include <string.h>
-#include <debug.h>
-#include <errno.h>
-
-#include <arpa/inet.h>
-#include <net/ethernet.h>
-
-#include <tinyara/arch.h>
-#include <tinyara/irq.h>
-#include <tinyara/wdog.h>
-#include <tinyara/net/arp.h>
-#include <tinyara/net/netdev.h>
-
-#ifdef CONFIG_NET_PKT
-#include <tinyara/net/pkt.h>
-#endif
-
-/****************************************************************************
- * Definitions
- ****************************************************************************/
-
-/* DM90000 and DM9010 register offets */
-
-#define DM9X_NETC 0x00 /* Network control register */
-#define DM9X_NETS 0x01 /* Network Status register */
-#define DM9X_TXC 0x02 /* TX control register */
-#define DM9X_TXS1 0x03 /* TX status register 1 */
-#define DM9X_TXS2 0x03 /* TX status register 2 */
-#define DM9X_RXC 0x05 /* RX control register */
-#define DM9X_RXS 0x06 /* RX status register */
-#define DM9X_RXOVF 0x07 /* Receive overflow counter register */
-#define DM9X_BPTHRES 0x08 /* Back pressure threshold register */
-#define DM9X_FCTHRES 0x09 /* Flow control threshold register */
-#define DM9X_FC 0x0a /* RX/TX flow control register */
-#define DM9X_EEPHYC 0x0b /* EEPROM & PHY control register */
-#define DM9X_EEPHYA 0x0c /* EEPROM & PHY address register */
-#define DM9X_EEPHYDL 0x0d /* EEPROM & PHY data register (lo) */
-#define DM9X_EEPHYDH 0x0e /* EEPROM & PHY data register (hi) */
-#define DM9X_WAKEUP 0x0f /* Wake-up control register */
-#define DM9X_PAB0 0x10 /* Physical address register (byte 0) */
-#define DM9X_PAB1 0x11 /* Physical address register (byte 1) */
-#define DM9X_PAB2 0x12 /* Physical address register (byte 2) */
-#define DM9X_PAB3 0x13 /* Physical address register (byte 3) */
-#define DM9X_PAB4 0x14 /* Physical address register (byte 4) */
-#define DM9X_PAB5 0x15 /* Physical address register (byte 5) */
-#define DM9X_MAB0 0x16 /* Multicast address register (byte 0) */
-#define DM9X_MAB1 0x17 /* Multicast address register (byte 1) */
-#define DM9X_MAB2 0x18 /* Multicast address register (byte 2) */
-#define DM9X_MAB3 0x19 /* Multicast address register (byte 3) */
-#define DM9X_MAB4 0x1a /* Multicast address register (byte 4) */
-#define DM9X_MAB5 0x1b /* Multicast address register (byte 5) */
-#define DM9X_MAB6 0x1c /* Multicast address register (byte 6) */
-#define DM9X_MAB7 0x1d /* Multicast address register (byte 7) */
-#define DM9X_GPC 0x1e /* General purpose control register */
-#define DM9X_GPD 0x1f /* General purpose register */
-
-#define DM9X_TRPAL 0x22 /* TX read pointer address (lo) */
-#define DM9X_TRPAH 0x23 /* TX read pointer address (hi) */
-#define DM9X_RWPAL 0x24 /* RX write pointer address (lo) */
-#define DM9X_RWPAH 0x25 /* RX write pointer address (hi) */
-
-#define DM9X_VIDL 0x28 /* Vendor ID (lo) */
-#define DM9X_VIDH 0x29 /* Vendor ID (hi) */
-#define DM9X_PIDL 0x2a /* Product ID (lo) */
-#define DM9X_PIDH 0x2b /* Product ID (hi) */
-#define DM9X_CHIPR 0x2c /* Product ID (lo) */
-#define DM9X_TXC2 0x2d /* Transmit control register 2 (dm9010) */
-#define DM9X_OTC 0x2e /* Operation test control register (dm9010) */
-#define DM9X_SMODEC 0x2f /* Special mode control register */
-#define DM9X_ETXCSR 0x30 /* Early transmit control/status register (dm9010) */
-#define DM9X_TCCR 0x31 /* Transmit checksum control register (dm9010) */
-#define DM9X_RCSR 0x32 /* Receive checksum control/status register (dm9010) */
-#define DM9X_EPHYA 0x33 /* External PHY address register (dm9010) */
-#define DM9X_GPC2 0x34 /* General purpose control register 2 (dm9010) */
-#define DM9X_GPD2 0x35 /* General purpose register 2 */
-#define DM9X_GPC3 0x36 /* General purpose control register 3 (dm9010) */
-#define DM9X_GPD3 0x37 /* General purpose register 3 */
-#define DM9X_PBUSC 0x38 /* Processor bus control register (dm9010) */
-#define DM9X_IPINC 0x39 /* INT pin control register (dm9010) */
-
-#define DM9X_MON1 0x40 /* Monitor register 1 (dm9010) */
-#define DM9X_MON2 0x41 /* Monitor register 2 (dm9010) */
-
-#define DM9X_SCLKC 0x50 /* System clock turn ON control register (dm9010) */
-#define DM9X_SCLKR 0x51 /* Resume system clock control register (dm9010) */
-
-#define DM9X_MRCMDX 0xf0 /* Memory data pre-fetch read command without address increment */
-#define DM9X_MRCMDX1 0xf1 /* memory data read command without address increment (dm9010) */
-#define DM9X_MRCMD 0xf2 /* Memory data read command with address increment */
-#define DM9X_MDRAL 0xf4 /* Memory data read address register (lo) */
-#define DM9X_MDRAH 0xf5 /* Memory data read address register (hi) */
-#define DM9X_MWCMDX 0xf6 /* Memory data write command without address increment */
-#define DM9X_MWCMD 0xf8 /* Memory data write command with address increment */
-#define DM9X_MDWAL 0xfa /* Memory data write address register (lo) */
-#define DM9X_MDWAH 0xfb /* Memory data write address register (lo) */
-#define DM9X_TXPLL 0xfc /* Memory data write address register (lo) */
-#define DM9X_TXPLH 0xfd /* Memory data write address register (hi) */
-#define DM9X_ISR 0xfe /* Interrupt status register */
-#define DM9X_IMR 0xff /* Interrupt mask register */
-
-/* Network control register bit definitions */
-
-#define DM9X_NETC_RST (1 << 0) /* Software reset */
-#define DM9X_NETC_LBKM (3 << 1) /* Loopback mode mask */
-#define DM9X_NETC_LBK0 (0 << 1) /* 0: Normal */
-#define DM9X_NETC_LBK1 (1 << 1) /* 1: MAC internal loopback */
-#define DM9X_NETC_LBK2 (2 << 1) /* 2: Internal PHY 100M mode loopback */
-#define DM9X_NETC_FDX (1 << 3) /* Full dupliex mode */
-#define DM9X_NETC_FCOL (1 << 4) /* Force collision mode */
-#define DM9X_NETC_WAKEEN (1 << 6) /* Wakeup event enable */
-#define DM9X_NETC_EXTPHY (1 << 7) /* Select external PHY */
-
-/* Network status bit definitions */
-
-#define DM9X_NETS_RXOV (1 << 1) /* RX Fifo overflow */
-#define DM9X_NETS_TX1END (1 << 2) /* TX packet 1 complete status */
-#define DM9X_NETS_TX2END (1 << 3) /* TX packet 2 complete status */
-#define DM9X_NETS_WAKEST (1 << 5) /* Wakeup event status */
-#define DM9X_NETS_LINKST (1 << 6) /* Link status */
-#define DM9X_NETS_SPEED (1 << 7) /* Media speed */
-
-/* IMR/ISR bit definitions */
-
-#define DM9X_INT_PR (1 << 0) /* Packet received interrupt */
-#define DM9X_INT_PT (1 << 1) /* Packet transmitted interrupt */
-#define DM9X_INT_RO (1 << 2) /* Receive overflow interrupt */
-#define DM9X_INT_ROO (1 << 3) /* Receive overflow counter overflow int */
-#define DM9X_INT_UDRUN (1 << 4) /* Transmit underrun interrupt */
-#define DM9X_INT_LNKCHG (1 << 5) /* Link status change interrupt */
-#define DM9X_INT_ALL (0x3f)
-
-#define DM9X_IMR_UNUSED (1 << 6) /* (not used) */
-#define DM9X_IMR_PAR (1 << 7) /* Enable auto R/W pointer reset */
-
-#define DM9X_ISR_IOMODEM (3 << 6) /* IO mode mask */
-#define DM9X_ISR_IOMODE8 (2 << 6) /* IO mode = 8 bit */
-#define DM9X_ISR_IOMODE16 (0 << 6) /* IO mode = 16 bit */
-#define DM9X_ISR_IOMODE32 (1 << 6) /* IO mode = 32 bit */
-
-#define DM9X_IMRENABLE (DM9X_INT_PR|DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR)
-#define DM9X_IMRRXDISABLE (DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR)
-#define DM9X_IMRDISABLE (DM9X_IMR_PAR)
-
-/* EEPROM/PHY control regiser bits */
-
-#define DM9X_EEPHYC_ERRE (1 << 0) /* EEPROM (vs PHY) access status */
-#define DM9X_EEPHYC_ERPRW (1 << 1) /* EEPROM/PHY write access */
-#define DM9X_EEPHYC_ERPRR (1 << 2) /* EEPROM/PHY read access */
-#define DM9X_EEPHYC_EPOS (1 << 3) /* EEPROM/PHY operation select */
-#define DM9X_EEPHYC_WEP (1 << 4) /* Write EEPROM enable */
-#define DM9X_EEPHYC_REEP (1 << 5) /* Reload EEPROM */
-
-/* Supported values from the vendor and product ID register */
-
-#define DM9X_DAVICOMVID 0x0a46
-#define DM9X_DM9000PID 0x9000
-#define DM9X_DM9010PID 0x9010
-
-/* RX control register bit settings */
-
-#define DM9X_RXC_RXEN (1 << 0) /* RX enable */
-#define DM9X_RXC_PRMSC (1 << 1) /* Promiscuous mode */
-#define DM9X_RXC_RUNT (1 << 2) /* Pass runt packet */
-#define DM9X_RXC_ALL (1 << 3) /* Pass all multicast */
-#define DM9X_RXC_DISCRC (1 << 4) /* Discard CRC error packets */
-#define DM9X_RXC_DISLONG (1 << 5) /* Discard long packets */
-#define DM9X_RXC_WTDIS (1 << 6) /* Disable watchdog timer */
-#define DM9X_RXC_HASHALL (1 << 7) /* Filter all addresses in hash table */
-
-#define DM9X_RXCSETUP (DM9X_RXC_DISCRC|DM9X_RXC_DISLONG)
-
-/* EEPHY bit settings */
-
-#define DM9X_EEPHYA_EROA 0x40 /* PHY register address 0x01 */
-
-#define DM9X_PKTRDY 0x01 /* Packet ready to receive */
-
-/* The RX interrupt will be disabled if more than the following RX
- * interrupts are received back-to-back.
- */
-
-#define DM9X_CRXTHRES 10
-
-/* All access is via an index register and a data regist. Select accecss
- * according to user supplied base address and bus width.
- */
-
-#if defined(CONFIG_DM9X_BUSWIDTH8)
-#define DM9X_INDEX *(volatile uint8_t*)(CONFIG_DM9X_BASE)
-#define DM9X_DATA *(volatile uint8_t*)(CONFIG_DM9X_BASE + 2)
-#elif defined(CONFIG_DM9X_BUSWIDTH16)
-#define DM9X_INDEX *(volatile uint16_t*)(CONFIG_DM9X_BASE)
-#define DM9X_DATA *(volatile uint16_t*)(CONFIG_DM9X_BASE + 2)
-#elif defined(CONFIG_DM9X_BUSWIDTH32)
-#define DM9X_INDEX *(volatile uint32_t*)(CONFIG_DM9X_BASE)
-#define DM9X_DATA *(volatile uint32_t*)(CONFIG_DM9X_BASE + 2)
-#endif
-
-/* Phy operating mode. Default is AUTO, but this setting can be overridden
- * in the TinyAra configuration file.
- */
-
-#if !defined(CONFIG_DM9X_MODE_AUTO) && !defined(CONFIG_DM9X_MODE_10MHD) && \
- !defined(CONFIG_DM9X_MODE_100MHD) && !defined(CONFIG_DM9X_MODE_10MFD) && \
- !defined(CONFIG_DM9X_MODE_100MFD)
-#define CONFIG_DM9X_MODE_AUTO 1
-#endif
-
-/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */
-
-#define DM6X_WDDELAY (1*CLK_TCK)
-#define DM6X_POLLHSEC (1*2)
-
-/* TX timeout = 1 minute */
-
-#define DM6X_TXTIMEOUT (60*CLK_TCK)
-
-/* This is a helper pointer for accessing the contents of the Ethernet header */
-
-#define BUF ((struct eth_hdr_s *)dm9x->dm_dev.d_buf)
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-union rx_desc_u {
- uint8_t rx_buf[4];
- struct {
- uint8_t rx_byte;
- uint8_t rx_status;
- uint16_t rx_len;
- } desc;
-};
-
-/* The dm9x_driver_s encapsulates all DM90x0 state information for a single
- * DM90x0 hardware interface
- */
-
-struct dm9x_driver_s {
- bool dm_bifup; /* true:ifup false:ifdown */
- bool dm_b100M; /* true:speed == 100M; false:speed == 10M */
- WDOG_ID dm_txpoll; /* TX poll timer */
- WDOG_ID dm_txtimeout; /* TX timeout timer */
- uint8_t dm_ntxpending; /* Count of packets pending transmission */
- uint8_t ncrxpackets; /* Number of continuous rx packets */
-
- /* Mode-dependent function to move data in 8/16/32 I/O modes */
-
- void (*dm_read)(uint8_t *ptr, int len);
- void (*dm_write)(const uint8_t *ptr, int len);
- void (*dm_discard)(int len);
-
-#if defined(CONFIG_DM9X_STATS)
- uint32_t dm_ntxpackets; /* Count of packets sent */
- uint32_t dm_ntxbytes; /* Count of bytes sent */
- uint32_t dm_ntxerrors; /* Count of TX errors */
- uint32_t dm_nrxpackets; /* Count of packets received */
- uint32_t dm_nrxbytes; /* Count of bytes received */
- uint32_t dm_nrxfifoerrors; /* Count of RX FIFO overflow errors */
- uint32_t dm_nrxcrcerrors; /* Count of RX CRC errors */
- uint32_t dm_nrxlengtherrors; /* Count of RX length errors */
- uint32_t dm_nphyserrors; /* Count of physical layer errors */
- uint32_t dm_nresets; /* Counts number of resets */
- uint32_t dm_ntxtimeouts; /* Counts resets caused by TX timeouts */
-#endif
-
- /* This holds the information visible to uIP/TinyAra */
-
- struct net_driver_s dm_dev;
-};
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-/* At present, only a single DM90x0 device is supported. */
-
-static struct dm9x_driver_s g_dm9x[CONFIG_DM9X_NINTERFACES];
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/* Utility functions */
-
-static uint8_t getreg(int reg);
-static void putreg(int reg, uint8_t value);
-static void read8(uint8_t *ptr, int len);
-static void read16(uint8_t *ptr, int len);
-static void read32(uint8_t *ptr, int len);
-static void discard8(int len);
-static void discard16(int len);
-static void discard32(int len);
-static void write8(const uint8_t *ptr, int len);
-static void write16(const uint8_t *ptr, int len);
-static void write32(const uint8_t *ptr, int len);
-
-/* static uint16_t dm9x_readsrom(struct dm9x_driver_s *dm9x, int offset); */
-static uint16_t dm9x_phyread(struct dm9x_driver_s *dm9x, int reg);
-static void dm9x_phywrite(struct dm9x_driver_s *dm9x, int reg, uint16_t value);
-
-#if defined(CONFIG_DM9X_STATS)
-static void dm9x_resetstatistics(struct dm9x_driver_s *dm9x);
-#else
-#define dm9x_resetstatistics(dm9x)
-#endif
-
-#if defined(CONFIG_DM9X_STATS) && defined(CONFIG_DEBUG)
-static void dm9x_dumpstatistics(struct dm9x_driver_s *dm9x);
-#else
-#define dm9x_dumpstatistics(dm9x)
-#endif
-
-#if defined(CONFIG_DM9X_CHECKSUM)
-static bool dm9x_rxchecksumready(uint8_t);
-#else
-#define dm9x_rxchecksumready(a) ((a) == 0x01)
-#endif
-
-/* Common TX logic */
-
-static int dm9x_transmit(struct dm9x_driver_s *dm9x);
-static int dm9x_txpoll(struct net_driver_s *dev);
-
-/* Interrupt handling */
-
-static void dm9x_receive(struct dm9x_driver_s *dm9x);
-static void dm9x_txdone(struct dm9x_driver_s *dm9x);
-static int dm9x_interrupt(int irq, FAR void *context);
-
-/* Watchdog timer expirations */
-
-static void dm9x_polltimer(int argc, uint32_t arg, ...);
-static void dm9x_txtimeout(int argc, uint32_t arg, ...);
-
-/* TinyAra callback functions */
-
-static int dm9x_ifup(struct net_driver_s *dev);
-static int dm9x_ifdown(struct net_driver_s *dev);
-static int dm9x_txavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_IGMP
-static int dm9x_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-static int dm9x_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-#endif
-
-/* Initialization functions */
-
-static void dm9x_bringup(struct dm9x_driver_s *dm9x);
-static void dm9x_reset(struct dm9x_driver_s *dm9x);
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: getreg and setreg
- *
- * Description:
- * Access to memory-mapped DM90x0 8-bit registers
- *
- * Parameters:
- * reg - Register number
- * value - Value to write to the register (setreg only)
- *
- * Returned Value:
- * Value read from the register (getreg only)
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static uint8_t getreg(int reg)
-{
- DM9X_INDEX = reg;
- return DM9X_DATA & 0xff;
-}
-
-static void putreg(int reg, uint8_t value)
-{
- DM9X_INDEX = reg;
- DM9X_DATA = value & 0xff;
-}
-
-/****************************************************************************
- * Function: read8, read16, read32
- *
- * Description:
- * Read packet data from the DM90x0 SRAM based on its current I/O mode
- *
- * Parameters:
- * ptr - Location to write the packet data
- * len - The number of bytes to read
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void read8(uint8_t *ptr, int len)
-{
- nvdbg("Read %d bytes (8-bit mode)\n", len);
- for (; len > 0; len--) {
- *ptr++ = DM9X_DATA;
- }
-}
-
-static void read16(uint8_t *ptr, int len)
-{
- register uint16_t *ptr16 = (uint16_t *) ptr;
- nvdbg("Read %d bytes (16-bit mode)\n", len);
- for (; len > 0; len -= sizeof(uint16_t)) {
- *ptr16++ = DM9X_DATA;
- }
-}
-
-static void read32(uint8_t *ptr, int len)
-{
- register uint32_t *ptr32 = (uint32_t *) ptr;
- nvdbg("Read %d bytes (32-bit mode)\n", len);
- for (; len > 0; len -= sizeof(uint32_t)) {
- *ptr32++ = DM9X_DATA;
- }
-}
-
-/****************************************************************************
- * Function: discard8, discard16, discard32
- *
- * Description:
- * Read and discard packet data in the DM90x0 SRAM based on its current
- * I/O mode
- *
- * Parameters:
- * len - The number of bytes to discard
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void discard8(int len)
-{
- nvdbg("Discard %d bytes (8-bit mode)\n", len);
- for (; len > 0; len--) {
- DM9X_DATA;
- }
-}
-
-static void discard16(int len)
-{
- nvdbg("Discard %d bytes (16-bit mode)\n", len);
- for (; len > 0; len -= sizeof(uint16_t)) {
- DM9X_DATA;
- }
-}
-
-static void discard32(int len)
-{
- nvdbg("Discard %d bytes (32-bit mode)\n", len);
- for (; len > 0; len -= sizeof(uint32_t)) {
- DM9X_DATA;
- }
-}
-
-/****************************************************************************
- * Function: write8, write16, write32
- *
- * Description:
- * Write packet data into the DM90x0 SRAM based on its current I/O mode
- *
- * Parameters:
- * ptr - Location to write the packet data
- * len - The number of bytes to read
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void write8(const uint8_t *ptr, int len)
-{
- nvdbg("Write %d bytes (8-bit mode)\n", len);
- for (; len > 0; len--) {
- DM9X_DATA = (*ptr++ & 0xff);
- }
-}
-
-static void write16(const uint8_t *ptr, int len)
-{
- register uint16_t *ptr16 = (uint16_t *) ptr;
- nvdbg("Write %d bytes (16-bit mode)\n", len);
-
- for (; len > 0; len -= sizeof(uint16_t)) {
- DM9X_DATA = *ptr16++;
- }
-}
-
-static void write32(const uint8_t *ptr, int len)
-{
- register uint32_t *ptr32 = (uint32_t *) ptr;
- nvdbg("Write %d bytes (32-bit mode)\n", len);
- for (; len > 0; len -= sizeof(uint32_t)) {
- DM9X_DATA = *ptr32++;
- }
-}
-
-/****************************************************************************
- * Function: dm9x_readsrom
- *
- * Description:
- * Read a word from SROM
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- * offset - SROM offset to read from
- *
- * Returned Value:
- * SROM content at that offset
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#if 0 /* Not used */
-static uint16_t dm9x_readsrom(struct dm9x_driver_s *dm9x, int offset)
-{
- putreg(DM9X_EEPHYA, offset);
- putreg(DM9X_EEPHYC, DM9X_EEPHYC_ERPRR);
- up_udelay(200);
- putreg(DM9X_EEPHYC, 0x00);
- return (getreg(DM9X_EEPHYDL) + (getreg(DM9X_EEPHYDH) << 8));
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_phyread and dm9x_phywrite
- *
- * Description:
- * Read/write data from/to the PHY
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- * reg - PHY register offset
- * value - The value to write to the PHY register (dm9x_write only)
- *
- * Returned Value:
- * The value read from the PHY (dm9x_read only)
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static uint16_t dm9x_phyread(struct dm9x_driver_s *dm9x, int reg)
-{
- /* Setup DM9X_EEPHYA, the EEPROM/PHY address register */
-
- putreg(DM9X_EEPHYA, DM9X_EEPHYA_EROA | reg);
-
- /* Issue PHY read command pulse in the EEPROM/PHY control register */
-
- putreg(DM9X_EEPHYC, (DM9X_EEPHYC_ERPRR | DM9X_EEPHYC_EPOS));
- up_udelay(100);
- putreg(DM9X_EEPHYC, 0x00);
-
- /* Return the data from the EEPROM/PHY data register pair */
-
- return (((uint16_t)getreg(DM9X_EEPHYDH)) << 8) | (uint16_t)getreg(DM9X_EEPHYDL);
-}
-
-static void dm9x_phywrite(struct dm9x_driver_s *dm9x, int reg, uint16_t value)
-{
- /* Setup DM9X_EEPHYA, the EEPROM/PHY address register */
-
- putreg(DM9X_EEPHYA, DM9X_EEPHYA_EROA | reg);
-
- /* Put the data to write in the EEPROM/PHY data register pair */
-
- putreg(DM9X_EEPHYDL, (value & 0xff));
- putreg(DM9X_EEPHYDH, ((value >> 8) & 0xff));
-
- /* Issue PHY write command pulse in the EEPROM/PHY control register */
-
- putreg(DM9X_EEPHYC, (DM9X_EEPHYC_ERPRW | DM9X_EEPHYC_EPOS));
- up_udelay(500);
- putreg(DM9X_EEPHYC, 0x0);
-}
-
-/****************************************************************************
- * Function: dm9x_resetstatistics
- *
- * Description:
- * Reset all DM90x0 statistics
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#if defined(CONFIG_DM9X_STATS)
-static void dm9x_resetstatistics(struct dm9x_driver_s *dm9x)
-{
- dm9x->dm_ntxpackets = 0; /* Count of packets sent */
- dm9x->dm_ntxbytes = 0; /* Count of bytes sent */
- dm9x->dm_ntxerrors = 0; /* Count of TX errors */
- dm9x->dm_nrxpackets = 0; /* Count of packets received */
- dm9x->dm_nrxbytes = 0; /* Count of bytes received */
- dm9x->dm_nrxfifoerrors = 0; /* Count of RX FIFO overflow errors */
- dm9x->dm_nrxcrcerrors = 0; /* Count of RX CRC errors */
- dm9x->dm_nrxlengtherrors = 0; /* Count of RX length errors */
- dm9x->dm_nphyserrors = 0; /* Count of physical layer errors */
- dm9x->dm_nresets = 0; /* Counts number of resets */
- dm9x->dm_ntxtimeouts = 0; /* Counts resets caused by TX timeouts */
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_dumpstatistics
- *
- * Description:
- * Print the current value of all DM90x0 statistics
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#if defined(CONFIG_DM9X_STATS) && defined(CONFIG_DEBUG)
-static void dm9x_dumpstatistics(struct dm9x_driver_s *dm9x)
-{
- ndbg("TX packets: %d\n", dm9x->dm_ntxpackets);
- ndbg(" bytes: %d\n", dm9x->dm_ntxbytes);
- ndbg(" errors: %d\n", dm9x->dm_ntxerrors);
- ndbg("RX packets: %d\n", dm9x->dm_nrxpackets);
- ndbg(" bytes: %d\n", dm9x->dm_nrxbytes);
- ndbg(" FIFO overflows: %d\n", dm9x->dm_nrxfifoerrors);
- ndbg(" CRC errors: %d\n", dm9x->dm_nrxcrcerrors);
- ndbg(" length errors: %d\n", dm9x->dm_nrxlengtherrors);
- ndbg("Physical layer errors: %d\n", dm9x->dm_nphyserrors);
- ndbg("Resets: %d\n", dm9x->dm_nresets);
- ndbg("TX timeout resets: %d\n", dm9x->dm_ntxtimeouts);
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_rxchecksumready
- *
- * Description:
- * Return true if the RX checksum is available
- *
- * Parameters:
- * rxbyte
- *
- * Returned Value:
- * true: checksum is ready
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#if defined(CONFIG_DM9X_CHECKSUM)
-static inline bool dm9x_rxchecksumready(uint8_t rxbyte)
-{
- if ((rxbyte & 0x01) == 0) {
- return false;
- }
-
- return ((rxbyte >> 4) | 0x01) != 0;
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_transmit
- *
- * Description:
- * Start hardware transmission. Called either from the txdone interrupt
- * handling or from watchdog based polling.
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int dm9x_transmit(struct dm9x_driver_s *dm9x)
-{
- /* Check if there is room in the DM90x0 to hold another packet. In 100M mode,
- * that can be 2 packets, otherwise it is a single packet.
- */
-
- if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) {
- /* Increment count of packets transmitted */
-
- dm9x->dm_ntxpending++;
-#if defined(CONFIG_DM9X_STATS)
- dm9x->dm_ntxpackets++;
- dm9x->dm_ntxbytes += dm9x->dm_dev.d_len;
-#endif
-
- /* Disable all DM90x0 interrupts */
-
- putreg(DM9X_IMR, DM9X_IMRDISABLE);
-
- /* Set the TX length */
-
- putreg(DM9X_TXPLL, (dm9x->dm_dev.d_len & 0xff));
- putreg(DM9X_TXPLH, (dm9x->dm_dev.d_len >> 8) & 0xff);
-
- /* Move the data to be sent into TX SRAM */
-
- DM9X_INDEX = DM9X_MWCMD;
- dm9x->dm_write(dm9x->dm_dev.d_buf, dm9x->dm_dev.d_len);
-
-#if !defined(CONFIG_DM9X_ETRANS)
- /* Issue TX polling command */
-
- putreg(DM9X_TXC, 0x1); /* Cleared after TX complete */
-#endif
-
- /* Clear count of back-to-back RX packet transfers */
-
- dm9x->ncrxpackets = 0;
-
- /* Re-enable DM90x0 interrupts */
-
- putreg(DM9X_IMR, DM9X_IMRENABLE);
-
- /* Setup the TX timeout watchdog (perhaps restarting the timer) */
-
- (void)wd_start(dm9x->dm_txtimeout, DM6X_TXTIMEOUT, dm9x_txtimeout, 1, (uint32_t)dm9x);
- return OK;
- }
- return -EBUSY;
-}
-
-/****************************************************************************
- * Function: dm9x_txpoll
- *
- * Description:
- * The transmitter is available, check if uIP has any outgoing packets ready
- * to send. This is a callback from netif_poll(). netif_poll() may be called:
- *
- * 1. When the preceding TX packet send is complete,
- * 2. When the preceding TX packet send timesout and the DM90x0 is reset
- * 3. During normal TX polling
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int dm9x_txpoll(struct net_driver_s *dev)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;
-
- /* If the polling resulted in data that should be sent out on the network,
- * the field d_len is set to a value > 0.
- */
-
- if (dm9x->dm_dev.d_len > 0) {
- /* Look up the destination MAC address and add it to the Ethernet
- * header.
- */
-
-#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(dm9x->dm_dev.d_flags))
-#endif
- {
- arp_out(&dm9x->dm_dev);
- }
-#endif /* CONFIG_NET_IPv4 */
-
-#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- else
-#endif
- {
- neighbor_out(&dm9x->dm_dev);
- }
-#endif /* CONFIG_NET_IPv6 */
-
- /* Send the packet */
-
- dm9x_transmit(dm9x);
-
- /* Check if there is room in the DM90x0 to hold another packet. In 100M mode,
- * that can be 2 packets, otherwise it is a single packet.
- */
-
- if (dm9x->dm_ntxpending > 1 || !dm9x->dm_b100M) {
- /* Returning a non-zero value will terminate the poll operation */
-
- return 1;
- }
- }
-
- /* If zero is returned, the polling will continue until all connections have
- * been examined.
- */
-
- return 0;
-}
-
-/****************************************************************************
- * Function: dm9x_receive
- *
- * Description:
- * An interrupt was received indicating the availability of a new RX packet
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_receive(struct dm9x_driver_s *dm9x)
-{
- union rx_desc_u rx;
- bool bchecksumready;
- uint8_t rxbyte;
-
- nvdbg("Packet received\n");
-
- do {
- /* Store the value of memory data read address register */
-
- (void)getreg(DM9X_MDRAH);
- (void)getreg(DM9X_MDRAL);
-
- getreg(DM9X_MRCMDX); /* Dummy read */
- rxbyte = (uint8_t)DM9X_DATA; /* Get the most up-to-date data */
-
- /* Packet ready for receive check */
-
- bchecksumready = dm9x_rxchecksumready(rxbyte);
- if (!bchecksumready) {
- break;
- }
-
- /* A packet is ready now. Get status/length */
-
- DM9X_INDEX = DM9X_MRCMD; /* set read ptr ++ */
-
- /* Read packet status & length */
-
- dm9x->dm_read((uint8_t *)&rx, 4);
-
- /* Check if any errors were reported by the hardware */
-
- if (rx.desc.rx_status & 0xbf) {
- /* Bad RX packet... update statistics */
-
-#if defined(CONFIG_DM9X_STATS)
- if (rx.desc.rx_status & 0x01) {
- dm9x->dm_nrxfifoerrors++;
- ndbg("RX FIFO error: %d\n", dm9x->dm_nrxfifoerrors);
- }
-
- if (rx.desc.rx_status & 0x02) {
- dm9x->dm_nrxcrcerrors++;
- ndbg("RX CRC error: %d\n", dm9x->dm_nrxcrcerrors);
- }
-
- if (rx.desc.rx_status & 0x80) {
- dm9x->dm_nrxlengtherrors++;
- ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors);
- }
-
- if (rx.desc.rx_status & 0x08) {
- dm9x->dm_nphyserrors++;
- ndbg("Physical Layer error: %d\n", dm9x->dm_nphyserrors);
- }
-#else
- ndbg("Received packet with errors: %02x\n", rx.desc.rx_status);
-#endif
- /* Drop this packet and continue to check the next packet */
-
- dm9x->dm_discard(rx.desc.rx_len);
- }
-
- /* Also check if the packet is a valid size for the uIP configuration */
-
- else if (rx.desc.rx_len < ETH_HDRLEN || rx.desc.rx_len > (CONFIG_NET_ETH_MTU + 2)) {
-#if defined(CONFIG_DM9X_STATS)
- dm9x->dm_nrxlengtherrors++;
- ndbg("RX length error: %d\n", dm9x->dm_nrxlengtherrors);
-#endif
- /* Drop this packet and continue to check the next packet */
-
- dm9x->dm_discard(rx.desc.rx_len);
- } else {
- /* Good packet... Copy the packet data out of SRAM and pass it one to uIP */
-
- dm9x->dm_dev.d_len = rx.desc.rx_len;
- dm9x->dm_read(dm9x->dm_dev.d_buf, rx.desc.rx_len);
-
-#ifdef CONFIG_NET_PKT
- /* When packet sockets are enabled, feed the frame into the packet tap */
-
- pkt_input(&dm9x->dm_dev);
-#endif
-
- /* We only accept IP packets of the configured type and ARP packets */
-
-#ifdef CONFIG_NET_IPv4
- if (BUF->type == HTONS(ETHTYPE_IP)) {
- nllvdbg("IPv4 frame\n");
-
- /* Handle ARP on input then give the IPv4 packet to the network
- * layer
- */
-
- arp_ipin(&dm9x->dm_dev);
- ipv4_input(&dm9x->dm_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 (dm9x->dm_dev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(dm9x->dm_dev.d_flags))
-#endif
- {
- arp_out(&dm9x->dm_dev);
- }
-#ifdef CONFIG_NET_IPv6
- else {
- neighbor_out(&dm9x->dm_dev);
- }
-#endif
-
- /* And send the packet */
-
- dm9x_transmit(dm9x);
- }
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- if (BUF->type == HTONS(ETHTYPE_IP6)) {
- nllvdbg("Iv6 frame\n");
-
- /* Give the IPv6 packet to the network layer */
-
- ipv6_input(&dm9x->dm_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 (dm9x->dm_dev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv4
- if (IFF_IS_IPv4(dm9x->dm_dev.d_flags)) {
- arp_out(&dm9x->dm_dev);
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- {
- neighbor_out(&dm9x->dm_dev);
- }
-#endif
-
- /* And send the packet */
-
- dm9x_transmit(dm9x);
- }
- } else
-#endif
-#ifdef CONFIG_NET_ARP
- if (BUF->type == htons(ETHTYPE_ARP)) {
- arp_arpin(&dm9x->dm_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 (dm9x->dm_dev.d_len > 0) {
- dm9x_transmit(dm9x);
- }
- }
-#endif
- }
-
-#if defined(CONFIG_DM9X_STATS)
- dm9x->dm_nrxpackets++;
- dm9x->dm_nrxbytes += rx.desc.rx_len;
-#endif
- dm9x->ncrxpackets++;
- } while ((rxbyte & 0x01) == DM9X_PKTRDY && dm9x->ncrxpackets < DM9X_CRXTHRES);
- nvdbg("All RX packets processed\n");
-}
-
-/****************************************************************************
- * Function: dm9x_txdone
- *
- * Description:
- * An interrupt was received indicating that the last TX packet(s) is done
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_txdone(struct dm9x_driver_s *dm9x)
-{
- int nsr;
-
- nvdbg("TX done\n");
-
- /* Another packet has completed transmission. Decrement the count of
- * of pending TX transmissions.
- */
-
- nsr = getreg(DM9X_NETS);
- if (nsr & DM9X_NETS_TX1END) {
- if (dm9x->dm_ntxpending) {
- dm9x->dm_ntxpending--;
- } else {
- ndbg("Bad TX count (TX1END)\n");
- }
- }
-
- if (nsr & DM9X_NETS_TX2END) {
- if (dm9x->dm_ntxpending) {
- dm9x->dm_ntxpending--;
- } else {
- ndbg("Bad TX count (TX2END)\n");
- }
- }
-
- /* Cancel the TX timeout */
-
- if (dm9x->dm_ntxpending == 0) {
- wd_cancel(dm9x->dm_txtimeout);
- }
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&dm9x->dm_dev, dm9x_txpoll);
-}
-
-/****************************************************************************
- * Function: dm9x_interrupt
- *
- * Description:
- * DM90x0 interrupt handler
- *
- * Parameters:
- * irq - Number of the IRQ that generated the interrupt
- * context - Interrupt register state save info (architecture-specific)
- *
- * Returned Value:
- * OK on success
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int dm9x_interrupt(int irq, FAR void *context)
-{
-#if CONFIG_DM9X_NINTERFACES == 1
- register struct dm9x_driver_s *dm9x = &g_dm9x[0];
-#else
-#error "Additional logic needed to support multiple interfaces"
-#endif
- uint8_t isr;
- uint8_t save;
- int i;
-
- /* Save previous register address */
-
- save = (uint8_t)DM9X_INDEX;
-
- /* Disable all DM90x0 interrupts */
-
- putreg(DM9X_IMR, DM9X_IMRDISABLE);
-
- /* Get and clear the DM90x0 interrupt status bits */
-
- isr = getreg(DM9X_ISR);
- putreg(DM9X_ISR, isr);
- nvdbg("Interrupt status: %02x\n", isr);
-
- /* Check for link status change */
-
- if (isr & DM9X_INT_LNKCHG) {
- /* Wait up to 0.5s for link OK */
-
- for (i = 0; i < 500; i++) {
- dm9x_phyread(dm9x, 0x1);
- if (dm9x_phyread(dm9x, 0x1) & 0x4) { /*Link OK */
- /* Wait to get detected speed */
-
- for (i = 0; i < 200; i++) {
- up_mdelay(1);
- }
-
- /* Set the new network speed */
-
- if (dm9x_phyread(dm9x, 0) & 0x2000) {
- dm9x->dm_b100M = true;
- } else {
- dm9x->dm_b100M = false;
- }
- break;
- }
- up_mdelay(1);
- }
- ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M");
- }
-
- /* Check if we received an incoming packet */
-
- if (isr & DM9X_INT_PR) {
- dm9x_receive(dm9x);
- }
-
- /* Check if we are able to transmit a packet */
-
- if (isr & DM9X_INT_PT) {
- dm9x_txdone(dm9x);
- }
-
- /* If the number of consecutive receive packets exceeds a threshold,
- * then disable the RX interrupt.
- */
-
- if (dm9x->ncrxpackets >= DM9X_CRXTHRES) {
- /* Eanble all DM90x0 interrupts EXCEPT for RX */
-
- putreg(DM9X_IMR, DM9X_IMRRXDISABLE);
- } else {
- /* Enable all DM90x0 interrupts */
-
- putreg(DM9X_IMR, DM9X_IMRENABLE);
- }
-
- /* Restore previous register address */
-
- DM9X_INDEX = save;
- return OK;
-}
-
-/****************************************************************************
- * Function: dm9x_txtimeout
- *
- * Description:
- * Our TX watchdog timed out. Called from the timer interrupt handler.
- * The last TX never completed. Reset the DM90x0 and start again.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_txtimeout(int argc, uint32_t arg, ...)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg;
-
- ndbg("TX timeout\n");
-
- /* Increment statistics and dump debug info */
-
-#if defined(CONFIG_DM9X_STATS)
- dm9x->dm_ntxtimeouts++;
- dm9x->dm_ntxerrors++;
-#endif
-
- ndbg(" TX packet count: %d\n", dm9x->dm_ntxpending);
-#if defined(CONFIG_DM9X_STATS)
- ndbg(" TX timeouts: %d\n", dm9x->dm_ntxtimeouts);
-#endif
- ndbg(" TX read pointer address: 0x%02x:%02x\n", getreg(DM9X_TRPAH), getreg(DM9X_TRPAL));
- ndbg(" Memory data write address: 0x%02x:%02x (DM9010)\n", getreg(DM9X_MDWAH), getreg(DM9X_MDWAL));
-
- /* Then reset the DM90x0 */
-
- dm9x_reset(dm9x);
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&dm9x->dm_dev, dm9x_txpoll);
-}
-
-/****************************************************************************
- * Function: dm9x_polltimer
- *
- * Description:
- * Periodic timer handler. Called from the timer interrupt handler.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_polltimer(int argc, uint32_t arg, ...)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)arg;
-
- /* If the number of contiguous RX packets exceeds a threshold, reset the counter and
- * re-enable RX interrupts
- */
-
- if (dm9x->ncrxpackets >= DM9X_CRXTHRES) {
- dm9x->ncrxpackets = 0;
- putreg(DM9X_IMR, DM9X_IMRENABLE);
- }
-
- /* Check if there is room in the DM90x0 to hold another packet. In 100M mode,
- * that can be 2 packets, otherwise it is a single packet.
- */
-
- if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) {
- /* If so, update TCP timing states and poll uIP for new XMIT data */
-
- (void)netif_timer(&dm9x->dm_dev, dm9x_txpoll, DM6X_POLLHSEC);
- }
-
- /* Setup the watchdog poll timer again */
-
- (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, arg);
-}
-
-/****************************************************************************
- * Function: dm9x_phymode
- *
- * Description:
- * Configure the PHY operating mode
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static inline void dm9x_phymode(struct dm9x_driver_s *dm9x)
-{
- uint16_t phyreg0;
- uint16_t phyreg4;
-
-#if defined(CONFIG_DM9X_MODE_AUTO)
- phyreg0 = 0x1200; /* Auto-negotiation & Restart Auto-negotiation */
- phyreg4 = 0x01e1; /* Default flow control disable */
-#elif defined(CONFIG_DM9X_MODE_10MHD)
- phyreg4 = 0x21;
- phyreg0 = 0x1000;
-#elif defined(CONFIG_DM9X_MODE_10MFD)
- phyreg4 = 0x41;
- phyreg0 = 0x1100;
-#elif defined(CONFIG_DM9X_MODE_100MHD)
- phyreg4 = 0x81;
- phyreg0 = 0x3000;
-#elif defined(CONFIG_DM9X_MODE_100MFD)
- phyreg4 = 0x101;
- phyreg0 = 0x3100;
-#else
-#error "Recognized PHY mode"
-#endif
-
- dm9x_phywrite(dm9x, 0, phyreg0);
- dm9x_phywrite(dm9x, 4, phyreg4);
-}
-
-/****************************************************************************
- * Function: dm9x_ifup
- *
- * Description:
- * TinyAra Callback: Bring up the DM90x0 interface when an IP address is
- * provided
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int dm9x_ifup(struct net_driver_s *dev)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;
- uint8_t netstatus;
- int i;
-
- ndbg("Bringing up: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
-
- /* Initilize DM90x0 chip */
-
- dm9x_bringup(dm9x);
-
- /* Check link state and media speed (waiting up to 3s for link OK) */
-
- dm9x->dm_b100M = false;
- for (i = 0; i < 3000; i++) {
- netstatus = getreg(DM9X_NETS);
- if (netstatus & DM9X_NETS_LINKST) {
- /* Link OK... Wait a bit before getting the detected speed */
-
- up_mdelay(200);
- netstatus = getreg(DM9X_NETS);
- if ((netstatus & DM9X_NETS_SPEED) == 0) {
- dm9x->dm_b100M = true;
- }
- break;
- }
- i++;
- up_mdelay(1);
- }
-
- ndbg("delay: %dmS speed: %s\n", i, dm9x->dm_b100M ? "100M" : "10M");
-
- /* Set and activate a timer process */
-
- (void)wd_start(dm9x->dm_txpoll, DM6X_WDDELAY, dm9x_polltimer, 1, (uint32_t)dm9x);
-
- /* Enable the DM9X interrupt */
-
- dm9x->dm_bifup = true;
- up_enable_irq(CONFIG_DM9X_IRQ);
- return OK;
-}
-
-/****************************************************************************
- * Function: dm9x_ifdown
- *
- * Description:
- * TinyAra Callback: Stop the interface.
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int dm9x_ifdown(struct net_driver_s *dev)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;
- irqstate_t flags;
-
- ndbg("Stopping\n");
-
- /* Disable the DM9X interrupt */
-
- flags = irqsave();
- up_disable_irq(CONFIG_DM9X_IRQ);
-
- /* Cancel the TX poll timer and TX timeout timers */
-
- wd_cancel(dm9x->dm_txpoll);
- wd_cancel(dm9x->dm_txtimeout);
-
- /* Reset the device */
-
- dm9x_phywrite(dm9x, 0x00, 0x8000); /* PHY reset */
- putreg(DM9X_GPD, 0x01); /* Power-down PHY (GEPIO0=1) */
- putreg(DM9X_IMR, DM9X_IMRDISABLE); /* Disable all interrupts */
- putreg(DM9X_RXC, 0x00); /* Disable RX */
- putreg(DM9X_ISR, DM9X_INT_ALL); /* Clear interrupt status */
-
- dm9x->dm_bifup = false;
- irqrestore(flags);
-
- /* Dump statistics */
-
- dm9x_dumpstatistics(dm9x);
- return OK;
-}
-
-/****************************************************************************
- * Function: dm9x_txavail
- *
- * 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 TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- ****************************************************************************/
-
-static int dm9x_txavail(struct net_driver_s *dev)
-{
- struct dm9x_driver_s *dm9x = (struct dm9x_driver_s *)dev->d_private;
- irqstate_t flags;
-
- ndbg("Polling\n");
- flags = irqsave();
-
- /* Ignore the notification if the interface is not yet up */
-
- if (dm9x->dm_bifup) {
-
- /* Check if there is room in the DM90x0 to hold another packet. In 100M
- * mode, that can be 2 packets, otherwise it is a single packet.
- */
-
- if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2)) {
- /* If so, then poll uIP for new XMIT data */
-
- (void)netif_poll(&dm9x->dm_dev, dm9x_txpoll);
- }
- }
- irqrestore(flags);
- return OK;
-}
-
-/****************************************************************************
- * Function: dm9x_addmac
- *
- * Description:
- * TinyAra Callback: Add the specified MAC address to the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be added
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int dm9x_addmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct dm9x_driver_s *priv = (FAR struct dm9x_driver_s *)dev->d_private;
-
- /* Add the MAC address to the hardware multicast routing table */
-
-#warning "Multicast MAC support not implemented"
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_rmmac
- *
- * Description:
- * TinyAra Callback: Remove the specified MAC address from the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be removed
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int dm9x_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct dm9x_driver_s *priv = (FAR struct dm9x_driver_s *)dev->d_private;
-
- /* Add the MAC address to the hardware multicast routing table */
-
-#warning "Multicast MAC support not implemented"
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: dm9x_bringup
- *
- * Description:
- * Initialize the dm90x0 chip
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_bringup(struct dm9x_driver_s *dm9x)
-{
- ndbg("Initializing\n");
-
- /* Set the internal PHY power-on, GPIOs normal, and wait 2ms */
-
- putreg(DM9X_GPD, 0x01); /* Power-down the PHY (GEPIO0=1) */
- up_udelay(500);
- putreg(DM9X_GPD, 0x00); /* Preactivate PHY (GPIO0=0 */
- up_udelay(20); /* Wait 20us for PHY power-on ready */
-
- /* Do a software reset and wait 20us (twice). The reset autoclears
- * in 10us; 20us guarantees completion of the reset
- */
-
- putreg(DM9X_NETC, (DM9X_NETC_RST | DM9X_NETC_LBK1));
- up_udelay(20);
- putreg(DM9X_NETC, (DM9X_NETC_RST | DM9X_NETC_LBK1));
- up_udelay(20);
-
- /* Configure I/O mode */
-
- switch (getreg(DM9X_ISR) & DM9X_ISR_IOMODEM) {
- case DM9X_ISR_IOMODE8:
- dm9x->dm_read = read8;
- dm9x->dm_write = write8;
- dm9x->dm_discard = discard8;
- break;
-
- case DM9X_ISR_IOMODE16:
- dm9x->dm_read = read16;
- dm9x->dm_write = write16;
- dm9x->dm_discard = discard16;
- break;
-
- case DM9X_ISR_IOMODE32:
- dm9x->dm_read = read32;
- dm9x->dm_write = write32;
- dm9x->dm_discard = discard32;
- break;
-
- default:
- break;
- }
-
- /* Program PHY operating mode */
-
- dm9x_phymode(dm9x);
-
- /* Program operating mode */
-
- putreg(DM9X_NETC, 0x00); /* Network control */
- putreg(DM9X_TXC, 0x00); /* Clear TX Polling */
- putreg(DM9X_BPTHRES, 0x3f); /* Less 3kb, 600us */
- putreg(DM9X_SMODEC, 0x00); /* Special mode */
- putreg(DM9X_NETS, (DM9X_NETS_WAKEST | DM9X_NETS_TX1END | DM9X_NETS_TX2END)); /* Clear TX status */
- putreg(DM9X_ISR, DM9X_INT_ALL); /* Clear interrupt status */
-
-#if defined(CONFIG_DM9X_CHECKSUM)
- putreg(DM9X_TCCR, 0x07); /* TX UDP/TCP/IP checksum enable */
- putreg(DM9X_RCSR, 0x02); /* Receive checksum enable */
-#endif
-
-#if defined(CONFIG_DM9X_ETRANS)
- putreg(DM9X_ETXCSR, 0x83);
-#endif
-
- /* Initialize statistics */
-
- dm9x->ncrxpackets = 0; /* Number of continuous RX packets */
- dm9x->dm_ntxpending = 0; /* Number of pending TX packets */
- dm9x_resetstatistics(dm9x);
-
- /* Activate DM9000A/DM9010 */
-
- putreg(DM9X_RXC, DM9X_RXCSETUP | 1); /* RX enable */
- putreg(DM9X_IMR, DM9X_IMRENABLE); /* Enable TX/RX interrupts */
-}
-
-/****************************************************************************
- * Function: dm9x_reset
- *
- * Description:
- * Stop, reset, re-initialize, and restart the DM90x0 chip and driver. At
- * present, the chip is only reset after a TX timeout.
- *
- * Parameters:
- * dm9x - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void dm9x_reset(struct dm9x_driver_s *dm9x)
-{
- uint8_t save;
- int i;
-
- /* Cancel the TX poll timer and TX timeout timers */
-
- wd_cancel(dm9x->dm_txpoll);
- wd_cancel(dm9x->dm_txtimeout);
-
- /* Save previous register address */
-
- save = (uint8_t)DM9X_INDEX;
-
-#if defined(CONFIG_DM9X_STATS)
- dm9x->dm_nresets++;
-#endif
- dm9x_bringup(dm9x);
-
- /* Wait up to 1 second for the link to be OK */
-
- dm9x->dm_b100M = false;
- for (i = 0; i < 1000; i++) {
- if (dm9x_phyread(dm9x, 0x1) & 0x4) {
- if (dm9x_phyread(dm9x, 0) & 0x2000) {
- dm9x->dm_b100M = true;
- }
- break;
- }
- up_mdelay(1);
- }
-
- /* Restore previous register address */
-
- DM9X_INDEX = save;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: dm9x_initialize
- *
- * Description:
- * Initialize the DM90x0 driver
- *
- * Parameters:
- * None
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-/* Initialize the DM90x0 chip and driver */
-
-int dm9x_initialize(void)
-{
- uint8_t *mptr;
- uint16_t vid;
- uint16_t pid;
- int i;
- int j;
-
- /* Get the chip vendor ID and product ID */
-
- vid = (((uint16_t)getreg(DM9X_VIDH)) << 8) | (uint16_t)getreg(DM9X_VIDL);
- pid = (((uint16_t)getreg(DM9X_PIDH)) << 8) | (uint16_t)getreg(DM9X_PIDL);
- nlldbg("I/O base: %08x VID: %04x PID: %04x\n", CONFIG_DM9X_BASE, vid, pid);
-
- /* Check if a DM90x0 chip is recognized at this I/O base */
-
- if (vid != DM9X_DAVICOMVID || (pid != DM9X_DM9000PID && pid != DM9X_DM9010PID)) {
- nlldbg("DM90x0 vendor/product ID not found at this base address\n");
- return -ENODEV;
- }
-
- /* Attach the IRQ to the driver */
-
- if (irq_attach(CONFIG_DM9X_IRQ, dm9x_interrupt)) {
- /* We could not attach the ISR to the ISR */
-
- nlldbg("irq_attach() failed\n");
- return -EAGAIN;
- }
-
- /* Initialize the driver structure */
-
- memset(g_dm9x, 0, CONFIG_DM9X_NINTERFACES * sizeof(struct dm9x_driver_s));
- g_dm9x[0].dm_dev.d_ifup = dm9x_ifup; /* I/F down callback */
- g_dm9x[0].dm_dev.d_ifdown = dm9x_ifdown; /* I/F up (new IP address) callback */
- g_dm9x[0].dm_dev.d_txavail = dm9x_txavail; /* New TX data callback */
-#ifdef CONFIG_NET_IGMP
- g_dm9x[0].dm_dev.d_addmac = dm9x_addmac; /* Add multicast MAC address */
- g_dm9x[0].dm_dev.d_rmmac = dm9x_rmmac; /* Remove multicast MAC address */
-#endif
- g_dm9x[0].dm_dev.d_private = (void *)g_dm9x; /* Used to recover private state from dev */
-
- /* Create a watchdog for timing polling for and timing of transmisstions */
-
- g_dm9x[0].dm_txpoll = wd_create(); /* Create periodic poll timer */
- g_dm9x[0].dm_txtimeout = wd_create(); /* Create TX timeout timer */
-
- /* Read the MAC address */
-
- mptr = g_dm9x[0].dm_dev.d_mac.ether_addr_octet;
- for (i = 0, j = DM9X_PAB0; i < ETHER_ADDR_LEN; i++, j++) {
- mptr[i] = getreg(j);
- }
-
- nlldbg("MAC: %0x:%0x:%0x:%0x:%0x:%0x\n", mptr[0], mptr[1], mptr[2], mptr[3], mptr[4], mptr[5]);
-
- /* Register the device with the OS so that socket IOCTLs can be performed */
-
- (void)netdev_register(&g_dm9x[0].dm_dev, NET_LL_ETHERNET);
- return OK;
-}
-
-#endif /* CONFIG_NET && CONFIG_NET_DM90x0 */
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2016 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/****************************************************************************
- * drivers/net/e1000.c
- *
- * Copyright (C) 2011 Yu Qiang. All rights reserved.
- * Author: Yu Qiang <yuq825@gmail.com>
- *
- * This file is a part of NuttX:
- *
- * Copyright (C) 2011, 2014 Gregory Nutt. 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <tinyara/config.h>
-#include <tinyara/kmalloc.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <time.h>
-#include <debug.h>
-#include <errno.h>
-
-#include <arpa/inet.h>
-
-#include <tinyara/arch.h>
-#include <tinyara/irq.h>
-#include <tinyara/wdog.h>
-#include <tinyara/kmalloc.h>
-#include <tinyara/net/arp.h>
-#include <tinyara/net/netdev.h>
-
-#ifdef CONFIG_NET_PKT
-#include <tinyara/net/pkt.h>
-#endif
-
-#include <rgmp/pmap.h>
-#include <rgmp/string.h>
-#include <rgmp/stdio.h>
-#include <rgmp/utils.h>
-#include <rgmp/arch/pci.h>
-#include <rgmp/memio.h>
-
-#include "e1000.h"
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */
-
-#define E1000_WDDELAY (1*CLK_TCK)
-#define E1000_POLLHSEC (1*2)
-
-/* TX timeout = 1 minute */
-
-#define E1000_TXTIMEOUT (60*CLK_TCK)
-
-/* This is a helper pointer for accessing the contents of the Ethernet header */
-
-#define BUF ((struct eth_hdr_s *)e1000->netdev.d_buf)
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-struct tx_ring {
- struct tx_desc *desc;
- char *buf;
- int tail; /* where to write desc */
-};
-
-struct rx_ring {
- struct rx_desc *desc;
- char *buf;
- int head; /* where to read */
- int tail; /* where to release free desc */
- int free; /* number of freed desc */
-};
-
-struct e1000_dev {
- uint32_t phy_mem_base;
- uint32_t io_mem_base;
- uint32_t mem_size;
- int pci_dev_id;
- uint16_t pci_addr;
- unsigned char src_mac[6];
- unsigned char dst_mac[6];
- struct irq_action int_desc;
- struct tx_ring tx_ring;
- struct rx_ring rx_ring;
- struct e1000_dev *next;
-
- /* TinyAra net data */
-
- bool bifup; /* true:ifup false:ifdown */
- WDOG_ID txpoll; /* TX poll timer */
- WDOG_ID txtimeout; /* TX timeout timer */
-
- /* This holds the information visible to uIP/TinyAra */
-
- struct net_driver_s netdev; /* Interface understood by networking layer */
-};
-
-struct e1000_dev_head {
- struct e1000_dev *next;
-};
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static struct e1000_dev_head e1000_list = { 0 };
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/* Common TX logic */
-
-static int e1000_transmit(struct e1000_dev *e1000);
-static int e1000_txpoll(struct net_driver_s *dev);
-
-/* Interrupt handling */
-
-static void e1000_receive(struct e1000_dev *e1000);
-
-/* Watchdog timer expirations */
-
-static void e1000_polltimer(int argc, uint32_t arg, ...);
-static void e1000_txtimeout(int argc, uint32_t arg, ...);
-
-/* TinyAra callback functions */
-
-static int e1000_ifup(struct net_driver_s *dev);
-static int e1000_ifdown(struct net_driver_s *dev);
-static int e1000_txavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_IGMP
-static int e1000_addmac(struct net_driver_s *dev, const uint8_t *mac);
-static int e1000_rmmac(struct net_driver_s *dev, const uint8_t *mac);
-#endif
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static inline void e1000_outl(struct e1000_dev *dev, int reg, uint32_t val)
-{
- writel(dev->io_mem_base + reg, val);
-}
-
-static inline uint32_t e1000_inl(struct e1000_dev *dev, int reg)
-{
- return readl(dev->io_mem_base + reg);
-}
-
-/****************************** e1000 driver ********************************/
-
-void e1000_reset(struct e1000_dev *dev)
-{
- uint32_t dev_control;
-
- /* Reset the network controller hardware */
-
- dev_control = 0;
- dev_control |= (1 << 0); /* FD-bit (Full Duplex) */
- dev_control |= (0 << 2); /* GIOMD-bit (GIO Master Disable) */
- dev_control |= (1 << 3); /* LRST-bit (Link Reset) */
- dev_control |= (1 << 6); /* SLU-bit (Set Link Up) */
- dev_control |= (2 << 8); /* SPEED=2 (1000Mbps) */
- dev_control |= (0 << 11); /* FRCSPD-bit (Force Speed) */
- dev_control |= (0 << 12); /* FRCDPLX-bit (Force Duplex) */
- dev_control |= (0 << 20); /* ADVD3WUC-bit (Advertise D3 Wake Up Cap) */
- dev_control |= (1 << 26); /* RST-bit (Device Reset) */
- dev_control |= (1 << 27); /* RFCE-bit (Receive Flow Control Enable) */
- dev_control |= (1 << 28); /* TFCE-bit (Transmit Flow Control Enable) */
- dev_control |= (0 << 30); /* VME-bit (VLAN Mode Enable) */
- dev_control |= (0 << 31); /* PHY_RST-bit (PHY Reset) */
-
- e1000_outl(dev, E1000_IMC, 0xFFFFFFFF);
- e1000_outl(dev, E1000_STATUS, 0x00000000);
- e1000_outl(dev, E1000_CTRL, dev_control);
- dev_control &= ~(1 << 26); /* clear RST-bit (Device Reset) */
- e1000_outl(dev, E1000_CTRL, dev_control);
- up_mdelay(10);
- e1000_outl(dev, E1000_CTRL_EXT, 0x001401C0);
- e1000_outl(dev, E1000_IMC, 0xFFFFFFFF);
-}
-
-void e1000_turn_on(struct e1000_dev *dev)
-{
- int tx_control;
- int rx_control;
- uint32_t ims = 0;
-
- /* turn on the controller's receive engine */
-
- rx_control = e1000_inl(dev, E1000_RCTL);
- rx_control |= (1 << 1);
- e1000_outl(dev, E1000_RCTL, rx_control);
-
- /* turn on the controller's transmit engine */
-
- tx_control = e1000_inl(dev, E1000_TCTL);
- tx_control |= (1 << 1);
- e1000_outl(dev, E1000_TCTL, tx_control);
-
- /* enable the controller's interrupts */
-
- e1000_outl(dev, E1000_ICR, 0xFFFFFFFF);
- e1000_outl(dev, E1000_IMC, 0xFFFFFFFF);
-
- ims |= 1 << 0; /* TXDW */
- ims |= 1 << 1; /* TXQE */
- ims |= 1 << 2; /* LSC */
- ims |= 1 << 4; /* RXDMT0 */
- ims |= 1 << 7; /* RXT0 */
- e1000_outl(dev, E1000_IMS, ims);
-}
-
-void e1000_turn_off(struct e1000_dev *dev)
-{
- int tx_control;
- int rx_control;
-
- /* turn off the controller's receive engine */
-
- rx_control = e1000_inl(dev, E1000_RCTL);
- rx_control &= ~(1 << 1);
- e1000_outl(dev, E1000_RCTL, rx_control);
-
- /* turn off the controller's transmit engine */
-
- tx_control = e1000_inl(dev, E1000_TCTL);
- tx_control &= ~(1 << 1);
- e1000_outl(dev, E1000_TCTL, tx_control);
-
- /* turn off the controller's interrupts */
-
- e1000_outl(dev, E1000_IMC, 0xFFFFFFFF);
-}
-
-void e1000_init(struct e1000_dev *dev)
-{
- uint32_t rxd_phys;
- uint32_t txd_phys;
- uint32_t kmem_phys;
- uint32_t rx_control;
- uint32_t tx_control;
- uint32_t pba;
- int i;
-
- e1000_reset(dev);
-
- /* configure the controller's 'receive' engine */
-
- rx_control = 0;
- rx_control |= (0 << 1); /* EN-bit (Enable) */
- rx_control |= (0 << 2); /* SPB-bit (Store Bad Packets) */
- rx_control |= (0 << 3); /* UPE-bit (Unicast Promiscuous Mode) */
- rx_control |= (1 << 4); /* MPE-bit (Multicast Promiscuous Mode) */
- rx_control |= (0 << 5); /* LPE-bit (Long Packet Enable) */
- rx_control |= (0 << 6); /* LBM=0 (Loop-Back Mode) */
- rx_control |= (0 << 8); /* RDMTS=0 (Rx Descriptor Min Threshold Size) */
- rx_control |= (0 << 10); /* DTYPE=0 (Descriptor Type) */
- rx_control |= (0 << 12); /* MO=0 (Multicast Offset) */
- rx_control |= (1 << 15); /* BAM-bit (Broadcast Address Mode) */
- rx_control |= (0 << 16); /* BSIZE=0 (Buffer Size = 2048) */
- rx_control |= (0 << 18); /* VLE-bit (VLAN filter Enable) */
- rx_control |= (0 << 19); /* CFIEN-bit (Canonical Form Indicator Enable) */
- rx_control |= (0 << 20); /* CFI-bit (Canonical Form Indicator) */
- rx_control |= (1 << 22); /* DPF-bit (Discard Pause Frames) */
- rx_control |= (0 << 23); /* PMCF-bit (Pass MAC Control Frames) */
- rx_control |= (0 << 25); /* BSEX=0 (Buffer Size EXtension) */
- rx_control |= (1 << 26); /* SECRC-bit (Strip Ethernet CRC) */
- rx_control |= (0 << 27); /* FLEXBUF=0 (Flexible Buffer size) */
- e1000_outl(dev, E1000_RCTL, rx_control);
-
- /* configure the controller's 'transmit' engine */
-
- tx_control = 0;
- tx_control |= (0 << 1); /* EN-bit (Enable) */
- tx_control |= (1 << 3); /* PSP-bit (Pad Short Packets) */
- tx_control |= (15 << 4); /* CT=15 (Collision Threshold) */
- tx_control |= (63 << 12); /* COLD=63 (Collision Distance) */
- tx_control |= (0 << 22); /* SWXOFF-bit (Software XOFF) */
- tx_control |= (1 << 24); /* RTLC-bit (Re-Transmit on Late Collision) */
- tx_control |= (0 << 25); /* UNORTX-bit (Underrun No Re-Transmit) */
- tx_control |= (0 << 26); /* TXCSCMT=0 (TxDesc Mininum Threshold) */
- tx_control |= (0 << 28); /* MULR-bit (Multiple Request Support) */
- e1000_outl(dev, E1000_TCTL, tx_control);
-
- /* hardware flow control */
-
- pba = e1000_inl(dev, E1000_PBA);
-
- /* get receive FIFO size */
-
- pba = (pba & 0x000000ff) << 10;
- e1000_outl(dev, E1000_FCAL, 0x00C28001);
- e1000_outl(dev, E1000_FCAH, 0x00000100);
- e1000_outl(dev, E1000_FCT, 0x00008808);
- e1000_outl(dev, E1000_FCTTV, 0x00000680);
- e1000_outl(dev, E1000_FCRTL, (pba * 8 / 10) | 0x80000000);
- e1000_outl(dev, E1000_FCRTH, pba * 9 / 10);
-
- /* setup tx rings */
-
- txd_phys = PADDR((uintptr_t)dev->tx_ring.desc);
- kmem_phys = PADDR((uintptr_t)dev->tx_ring.buf);
- for (i = 0; i < CONFIG_E1000_N_TX_DESC; i++, kmem_phys += CONFIG_E1000_BUFF_SIZE) {
- dev->tx_ring.desc[i].base_address = kmem_phys;
- dev->tx_ring.desc[i].packet_length = 0;
- dev->tx_ring.desc[i].cksum_offset = 0;
- dev->tx_ring.desc[i].cksum_origin = 0;
- dev->tx_ring.desc[i].desc_status = 1;
- dev->tx_ring.desc[i].desc_command = (1 << 0) | (1 << 1) | (1 << 3);
- dev->tx_ring.desc[i].special_info = 0;
- }
-
- dev->tx_ring.tail = 0;
- e1000_outl(dev, E1000_TDT, 0);
- e1000_outl(dev, E1000_TDH, 0);
-
- /* tell controller the location, size, and fetch-policy for Tx queue */
-
- e1000_outl(dev, E1000_TDBAL, txd_phys);
- e1000_outl(dev, E1000_TDBAH, 0x00000000);
- e1000_outl(dev, E1000_TDLEN, CONFIG_E1000_N_TX_DESC * 16);
- e1000_outl(dev, E1000_TXDCTL, 0x01010000);
-
- /* setup rx rings */
-
- rxd_phys = PADDR((uintptr_t)dev->rx_ring.desc);
- kmem_phys = PADDR((uintptr_t)dev->rx_ring.buf);
- for (i = 0; i < CONFIG_E1000_N_RX_DESC; i++, kmem_phys += CONFIG_E1000_BUFF_SIZE) {
- dev->rx_ring.desc[i].base_address = kmem_phys;
- dev->rx_ring.desc[i].packet_length = 0;
- dev->rx_ring.desc[i].packet_cksum = 0;
- dev->rx_ring.desc[i].desc_status = 0;
- dev->rx_ring.desc[i].desc_errors = 0;
- dev->rx_ring.desc[i].vlan_tag = 0;
- }
-
- dev->rx_ring.head = 0;
- dev->rx_ring.tail = CONFIG_E1000_N_RX_DESC - 1;
- dev->rx_ring.free = 0;
-
- /* give the controller ownership of all receive descriptors */
-
- e1000_outl(dev, E1000_RDH, 0);
- e1000_outl(dev, E1000_RDT, CONFIG_E1000_N_RX_DESC - 1);
-
- /* tell controller the location, size, and fetch-policy for RX queue */
-
- e1000_outl(dev, E1000_RDBAL, rxd_phys);
- e1000_outl(dev, E1000_RDBAH, 0x00000000);
- e1000_outl(dev, E1000_RDLEN, CONFIG_E1000_N_RX_DESC * 16);
- e1000_outl(dev, E1000_RXDCTL, 0x01010000);
-
- e1000_turn_on(dev);
-}
-
-/****************************************************************************
- * Function: e1000_transmit
- *
- * Description:
- * Start hardware transmission. Called either from the txdone interrupt
- * handling or from watchdog based polling.
- *
- * Parameters:
- * e1000 - Reference to the driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
- *
- ****************************************************************************/
-
-static int e1000_transmit(struct e1000_dev *e1000)
-{
- int tail = e1000->tx_ring.tail;
- unsigned char *cp = (unsigned char *)
- (e1000->tx_ring.buf + tail * CONFIG_E1000_BUFF_SIZE);
- int count = e1000->netdev.d_len;
-
- /* Verify that the hardware is ready to send another packet. If we get
- * here, then we are committed to sending a packet; Higher level logic
- * must have assured that there is not transmission in progress.
- */
-
- if (!e1000->tx_ring.desc[tail].desc_status) {
- return -1;
- }
-
- /* Increment statistics */
-
- /* Send the packet: address=skel->sk_dev.d_buf, length=skel->sk_dev.d_len */
-
- memcpy(cp, e1000->netdev.d_buf, e1000->netdev.d_len);
-
- /* prepare the transmit-descriptor */
-
- e1000->tx_ring.desc[tail].packet_length = count < 60 ? 60 : count;
- e1000->tx_ring.desc[tail].desc_status = 0;
-
- /* give ownership of this descriptor to the network controller */
-
- tail = (tail + 1) % CONFIG_E1000_N_TX_DESC;
- e1000->tx_ring.tail = tail;
- e1000_outl(e1000, E1000_TDT, tail);
-
- /* Enable Tx interrupts */
-
- /* Setup the TX timeout watchdog (perhaps restarting the timer) */
-
- wd_start(e1000->txtimeout, E1000_TXTIMEOUT, e1000_txtimeout, 1, (uint32_t)e1000);
- return OK;
-}
-
-/****************************************************************************
- * Function: e1000_txpoll
- *
- * Description:
- * The transmitter is available, check if uIP has any outgoing packets ready
- * to send. This is a callback from netif_poll(). netif_poll() may be called:
- *
- * 1. When the preceding TX packet send is complete,
- * 2. When the preceding TX packet send timesout and the interface is reset
- * 3. During normal TX polling
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
- *
- ****************************************************************************/
-
-static int e1000_txpoll(struct net_driver_s *dev)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
- int tail = e1000->tx_ring.tail;
-
- /* If the polling resulted in data that should be sent out on the network,
- * the field d_len is set to a value > 0.
- */
-
- if (e1000->netdev.d_len > 0) {
- /* Look up the destination MAC address and add it to the Ethernet
- * header.
- */
-
-#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(e1000->netdev.d_flags))
-#endif
- {
- arp_out(&e1000->netdev);
- }
-#endif /* CONFIG_NET_IPv4 */
-
-#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- else
-#endif
- {
- neighbor_out(&e1000->netdev);
- }
-#endif /* CONFIG_NET_IPv6 */
-
- /* Send the packet */
-
- e1000_transmit(e1000);
-
- /* Check if there is room in the device to hold another packet. If not,
- * return a non-zero value to terminate the poll.
- */
-
- if (!e1000->tx_ring.desc[tail].desc_status) {
- return -1;
- }
- }
-
- /* If zero is returned, the polling will continue until all connections have
- * been examined.
- */
-
- return 0;
-}
-
-/****************************************************************************
- * Function: e1000_receive
- *
- * Description:
- * An interrupt was received indicating the availability of a new RX packet
- *
- * Parameters:
- * e1000 - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by interrupt handling logic.
- *
- ****************************************************************************/
-
-static void e1000_receive(struct e1000_dev *e1000)
-{
- int head = e1000->rx_ring.head;
- unsigned char *cp = (unsigned char *)
- (e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE);
- int cnt;
-
- while (e1000->rx_ring.desc[head].desc_status) {
- /* Check for errors and update statistics */
-
- /* Here we do not handle packets that exceed packet-buffer size */
-
- if ((e1000->rx_ring.desc[head].desc_status & 3) == 1) {
- cprintf("NIC READ: Oversized packet\n");
- goto next;
- }
-
- /* Check if the packet is a valid size for the uIP buffer configuration */
-
- /* get the number of actual data-bytes in this packet */
-
- cnt = e1000->rx_ring.desc[head].packet_length;
-
- if (cnt > CONFIG_NET_ETH_MTU || cnt < 14) {
- cprintf("NIC READ: invalid package size\n");
- goto next;
- }
-
- /* Copy the data data from the hardware to e1000->netdev.d_buf. Set
- * amount of data in e1000->netdev.d_len
- */
-
- /* now we try to copy these data-bytes to the UIP buffer */
-
- memcpy(e1000->netdev.d_buf, cp, cnt);
- e1000->netdev.d_len = cnt;
-
-#ifdef CONFIG_NET_PKT
- /* When packet sockets are enabled, feed the frame into the packet tap */
-
- pkt_input(&e1000->netdev);
-#endif
-
- /* We only accept IP packets of the configured type and ARP packets */
-
-#ifdef CONFIG_NET_IPv4
- if (BUF->type == HTONS(ETHTYPE_IP)) {
- nllvdbg("IPv4 frame\n");
-
- /* Handle ARP on input then give the IPv4 packet to the network
- * layer
- */
-
- arp_ipin(&e1000->netdev);
- ipv4_input(&e1000->netdev);
-
- /* 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 (e1000->netdev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(e1000->netdev.d_flags))
-#endif
- {
- arp_out(&e1000->netdev);
- }
-#ifdef CONFIG_NET_IPv6
- else {
- neighbor_out(&e1000->netdev);
- }
-#endif
-
- /* And send the packet */
-
- e1000_transmit(e1000);
- }
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- if (BUF->type == HTONS(ETHTYPE_IP6)) {
- nllvdbg("Iv6 frame\n");
-
- /* Give the IPv6 packet to the network layer */
-
- ipv6_input(&e1000->netdev);
-
- /* 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 (e1000->netdev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv4
- if (IFF_IS_IPv4(e1000->netdev.d_flags)) {
- arp_out(&e1000->netdev);
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- {
- neighbor_out(&e1000->netdev);
- }
-#endif
-
- /* And send the packet */
-
- e1000_transmit(e1000);
- }
- } else
-#endif
-#ifdef CONFIG_NET_ARP
- if (BUF->type == htons(ETHTYPE_ARP)) {
- arp_arpin(&e1000->netdev);
-
- /* 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 (e1000->netdev.d_len > 0) {
- e1000_transmit(e1000);
- }
-#endif
- }
-
-next:
- e1000->rx_ring.desc[head].desc_status = 0;
- e1000->rx_ring.head = (head + 1) % CONFIG_E1000_N_RX_DESC;
- e1000->rx_ring.free++;
- head = e1000->rx_ring.head;
- cp = (unsigned char *)(e1000->rx_ring.buf + head * CONFIG_E1000_BUFF_SIZE);
- }
-}
-
-/****************************************************************************
- * Function: e1000_txtimeout
- *
- * Description:
- * Our TX watchdog timed out. Called from the timer interrupt handler.
- * The last TX never completed. Reset the hardware and start again.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void e1000_txtimeout(int argc, uint32_t arg, ...)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)arg;
-
- /* Increment statistics and dump debug info */
-
- /* Then reset the hardware */
-
- e1000_init(e1000);
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&e1000->netdev, e1000_txpoll);
-}
-
-/****************************************************************************
- * Function: e1000_polltimer
- *
- * Description:
- * Periodic timer handler. Called from the timer interrupt handler.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void e1000_polltimer(int argc, uint32_t arg, ...)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)arg;
- int tail = e1000->tx_ring.tail;
-
- /* Check if there is room in the send another TX packet. We cannot perform
- * the TX poll if he are unable to accept another packet for transmission.
- */
-
- if (!e1000->tx_ring.desc[tail].desc_status) {
- return;
- }
-
- /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm..
- * might be bug here. Does this mean if there is a transmit in progress,
- * we will missing TCP time state updates?
- */
-
- (void)netif_timer(&e1000->netdev, e1000_txpoll, E1000_POLLHSEC);
-
- /* Setup the watchdog poll timer again */
-
- (void)wd_start(e1000->txpoll, E1000_WDDELAY, e1000_polltimer, 1, arg);
-}
-
-/****************************************************************************
- * Function: e1000_ifup
- *
- * Description:
- * TinyAra Callback: Bring up the Ethernet interface when an IP address is
- * provided
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int e1000_ifup(struct net_driver_s *dev)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
-
- ndbg("Bringing up: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
-
- /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */
-
- e1000_init(e1000);
-
- /* Set and activate a timer process */
-
- (void)wd_start(e1000->txpoll, E1000_WDDELAY, e1000_polltimer, 1, (uint32_t)e1000);
-
- if (e1000_inl(e1000, E1000_STATUS) & 2) {
- e1000->bifup = true;
- } else {
- e1000->bifup = false;
- }
-
- return OK;
-}
-
-/****************************************************************************
- * Function: e1000_ifdown
- *
- * Description:
- * TinyAra Callback: Stop the interface.
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int e1000_ifdown(struct net_driver_s *dev)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
- irqstate_t flags;
-
- /* Disable the Ethernet interrupt */
-
- flags = irqsave();
-
- e1000_turn_off(e1000);
-
- /* Cancel the TX poll timer and TX timeout timers */
-
- wd_cancel(e1000->txpoll);
- wd_cancel(e1000->txtimeout);
-
- /* Put the EMAC is its reset, non-operational state. This should be
- * a known configuration that will guarantee the skel_ifup() always
- * successfully brings the interface back up.
- */
-
- //e1000_reset(e1000);
-
- /* Mark the device "down" */
-
- e1000->bifup = false;
- irqrestore(flags);
-
- return OK;
-}
-
-/****************************************************************************
- * Function: e1000_txavail
- *
- * 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 TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- ****************************************************************************/
-
-static int e1000_txavail(struct net_driver_s *dev)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
- int tail = e1000->tx_ring.tail;
- irqstate_t flags;
-
- /* Disable interrupts because this function may be called from interrupt
- * level processing.
- */
-
- flags = irqsave();
-
- /* Ignore the notification if the interface is not yet up */
-
- if (e1000->bifup) {
- /* Check if there is room in the hardware to hold another outgoing packet. */
-
- if (e1000->tx_ring.desc[tail].desc_status) {
- (void)netif_poll(&e1000->netdev, e1000_txpoll);
- }
- }
-
- irqrestore(flags);
- return OK;
-}
-
-/****************************************************************************
- * Function: e1000_addmac
- *
- * Description:
- * TinyAra Callback: Add the specified MAC address to the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be added
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int e1000_addmac(struct net_driver_s *dev, const uint8_t *mac)
-{
- /* Add the MAC address to the hardware multicast routing table */
-
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: e1000_rmmac
- *
- * Description:
- * TinyAra Callback: Remove the specified MAC address from the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be removed
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int e1000_rmmac(struct net_driver_s *dev, const uint8_t *mac)
-{
- /* Add the MAC address to the hardware multicast routing table */
-
- return OK;
-}
-#endif
-
-static irqreturn_t e1000_interrupt_handler(int irq, void *dev_id)
-{
- struct e1000_dev *e1000 = (struct e1000_dev *)dev_id;
-
- /* Get and clear interrupt status bits */
-
- int intr_cause = e1000_inl(e1000, E1000_ICR);
- e1000_outl(e1000, E1000_ICR, intr_cause);
-
- /* not for me */
-
- if (intr_cause == 0) {
- return IRQ_NONE;
- }
-
- /* Handle interrupts according to status bit settings */
-
- /* Link status change */
-
- if (intr_cause & (1 << 2)) {
- if (e1000_inl(e1000, E1000_STATUS) & 2) {
- e1000->bifup = true;
- } else {
- e1000->bifup = false;
- }
- }
-
- /* Check if we received an incoming packet, if so, call skel_receive() */
-
- /* Rx-descriptor Timer expired */
-
- if (intr_cause & (1 << 7)) {
- e1000_receive(e1000);
- }
-
- /* Tx queue empty */
-
- if (intr_cause & (1 << 1)) {
- wd_cancel(e1000->txtimeout);
- }
-
- /* Check is a packet transmission just completed. If so, call skel_txdone.
- * This may disable further Tx interrupts if there are no pending
- * tansmissions.
- */
-
- /* Tx-descriptor Written back */
-
- if (intr_cause & (1 << 0)) {
- netif_poll(&e1000->netdev, e1000_txpoll);
- }
-
- /* Rx-Descriptors Low */
-
- if (intr_cause & (1 << 4)) {
- int tail;
-
- tail = e1000->rx_ring.tail + e1000->rx_ring.free;
- tail %= CONFIG_E1000_N_RX_DESC;
- e1000->rx_ring.tail = tail;
- e1000->rx_ring.free = 0;
- e1000_outl(e1000, E1000_RDT, tail);
- }
-
- return IRQ_HANDLED;
-}
-
-/******************************* PCI driver *********************************/
-
-static pci_id_t e1000_id_table[] = {
- {.sep = {INTEL_VENDERID, E1000_82573L} },
- {.sep = {INTEL_VENDERID, E1000_82540EM} },
- {.sep = {INTEL_VENDERID, E1000_82574L} },
- {.sep = {INTEL_VENDERID, E1000_82567LM} },
- {.sep = {INTEL_VENDERID, E1000_82541PI} },
- {.sep = {0, 0} }
-};
-
-static int e1000_probe(uint16_t addr, pci_id_t id)
-{
- uint32_t mmio_base, mmio_size;
- uint32_t size;
- int err;
- void *kmem;
- void *omem;
- struct e1000_dev *dev;
-
- /* alloc e1000_dev memory */
-
- if ((dev = kmm_zalloc(sizeof(struct e1000_dev))) == NULL) {
- return -1;
- }
-
- /* save pci addr */
-
- dev->pci_addr = addr;
-
- /* enable device */
-
- if ((err = pci_enable_device(addr, PCI_BUS_MASTER)) < 0) {
- goto error;
- }
-
- /* get e1000 device type */
-
- dev->pci_dev_id = id.join;
-
- /* remap the controller's i/o-memory into kernel's address-space */
-
- mmio_base = pci_resource_start(addr, 0);
- mmio_size = pci_resource_len(addr, 0);
- err = rgmp_memmap_nocache(mmio_base, mmio_size, mmio_base);
- if (err) {
- goto error;
- }
-
- dev->phy_mem_base = mmio_base;
- dev->io_mem_base = mmio_base;
- dev->mem_size = mmio_size;
-
- /* MAC address */
-
- memset(dev->dst_mac, 0xFF, 6);
- memcpy(dev->src_mac, (void *)(dev->io_mem_base + E1000_RA), 6);
-
- /* IRQ setup */
-
- dev->int_desc.handler = e1000_interrupt_handler;
- dev->int_desc.dev_id = dev;
- if ((err = pci_request_irq(addr, &dev->int_desc, 0)) < 0) {
- goto err0;
- }
-
- /* Here we alloc a big block of memory once and make it
- * aligned to page boundary and multiple of page size. This
- * is because the memory can be modified by E1000 DMA and
- * should be mapped no-cache which will hugely reduce memory
- * access performance. The page size alloc will restrict
- * this bad effect only within the memory we alloc here.
- *
- * NEED FIX: the memalign may alloc memory continous in
- * virtual address but dis-continous in physical address
- * due to RGMP memory setup.
- */
-
- size = CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc) + CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE + CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc) + CONFIG_E1000_N_RX_DESC * CONFIG_E1000_BUFF_SIZE;
- size = ROUNDUP(size, PGSIZE);
- omem = kmem = memalign(PGSIZE, size);
- if (kmem == NULL) {
- err = -ENOMEM;
- goto err1;
- }
-
- rgmp_memremap_nocache((uintptr_t)kmem, size);
-
- /* alloc memory for tx ring */
-
- dev->tx_ring.desc = (struct tx_desc *)kmem;
- kmem += CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc);
- dev->tx_ring.buf = kmem;
- kmem += CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE;
-
- /* alloc memory for rx rings */
-
- dev->rx_ring.desc = (struct rx_desc *)kmem;
- kmem += CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc);
- dev->rx_ring.buf = kmem;
-
- /* Initialize the driver structure */
-
- dev->netdev.d_ifup = e1000_ifup; /* I/F up (new IP address) callback */
- dev->netdev.d_ifdown = e1000_ifdown; /* I/F down callback */
- dev->netdev.d_txavail = e1000_txavail; /* New TX data callback */
-#ifdef CONFIG_NET_IGMP
- dev->netdev.d_addmac = e1000_addmac; /* Add multicast MAC address */
- dev->netdev.d_rmmac = e1000_rmmac; /* Remove multicast MAC address */
-#endif
- dev->netdev.d_private = dev; /* Used to recover private state from dev */
-
- /* Create a watchdog for timing polling for and timing of transmisstions */
-
- dev->txpoll = wd_create(); /* Create periodic poll timer */
- dev->txtimeout = wd_create(); /* Create TX timeout timer */
-
- /* Put the interface in the down state.
- * e1000 reset
- */
-
- e1000_reset(dev);
-
- /* Read the MAC address from the hardware */
-
- memcpy(dev->netdev.d_mac.ether_addr_octet, (void *)(dev->io_mem_base + E1000_RA), 6);
-
- /* Register the device with the OS so that socket IOCTLs can be performed */
-
- err = netdev_register(&dev->netdev, NET_LL_ETHERNET);
- if (err) {
- goto err2;
- }
-
- /* insert into e1000_list */
-
- dev->next = e1000_list.next;
- e1000_list.next = dev;
- cprintf("bring up e1000 device: %04x %08x\n", addr, id.join);
-
- return 0;
-
-err2:
- rgmp_memremap((uintptr_t)omem, size);
- free(omem);
-err1:
- pci_free_irq(addr);
-err0:
- rgmp_memunmap(mmio_base, mmio_size);
-error:
- kmm_free(dev);
- cprintf("e1000 device probe fail: %d\n", err);
- return err;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-void e1000_mod_init(void)
-{
- pci_probe_device(e1000_id_table, e1000_probe);
-}
-
-void e1000_mod_exit(void)
-{
- uint32_t size;
- struct e1000_dev *dev;
-
- size = CONFIG_E1000_N_TX_DESC * sizeof(struct tx_desc) + CONFIG_E1000_N_TX_DESC * CONFIG_E1000_BUFF_SIZE + CONFIG_E1000_N_RX_DESC * sizeof(struct rx_desc) + CONFIG_E1000_N_RX_DESC * CONFIG_E1000_BUFF_SIZE;
- size = ROUNDUP(size, PGSIZE);
-
- for (dev = e1000_list.next; dev != NULL; dev = dev->next) {
- netdev_unregister(&dev->netdev);
- e1000_reset(dev);
- wd_delete(dev->txpoll);
- wd_delete(dev->txtimeout);
- rgmp_memremap((uintptr_t)dev->tx_ring.desc, size);
- free(dev->tx_ring.desc);
- pci_free_irq(dev->pci_addr);
- rgmp_memunmap((uintptr_t)dev->io_mem_base, dev->mem_size);
- kmm_free(dev);
- }
-
- e1000_list.next = NULL;
-}
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2016 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/****************************************************************************
- * drivers/net/e1000.h
- *
- * Copyright (C) 2011 Yu Qiang. All rights reserved.
- * Author: Yu Qiang <yuq825@gmail.com>
- *
- * This file is a part of NuttX:
- *
- * Copyright (C) 2011 Gregory Nutt. 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-#ifndef __DRIVERS_NET_E1000_H
-#define __DRIVERS_NET_E1000_H
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <stdint.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/************** PCI ID ***************/
-
-#define INTEL_VENDERID 0x8086
-#define E1000_82573L 0x109a
-#define E1000_82540EM 0x100e
-#define E1000_82574L 0x10d3
-#define E1000_82567LM 0x10f5
-#define E1000_82541PI 0x107c
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-enum e1000_registers {
- E1000_CTRL = 0x0000, // Device Control
- E1000_STATUS = 0x0008, // Device Status
- E1000_CTRL_EXT = 0x0018, // Device Control Extension
- E1000_FCAL = 0x0028, // Flow Control Address Low
- E1000_FCAH = 0x002C, // Flow Control Address High
- E1000_FCT = 0x0030, // Flow Control Type
- E1000_ICR = 0x00C0, // Interrupt Cause Read
- E1000_ICS = 0x00C8, // Interrupt Cause Set
- E1000_IMS = 0x00D0, // Interrupt Mask Set
- E1000_IMC = 0x00D8, // Interrupt Mask Clear
- E1000_RCTL = 0x0100, // Receive Control
- E1000_FCTTV = 0x0170, // Flow Control Transmit Timer Value
- E1000_TCTL = 0x0400, // Transmit Control
- E1000_PBA = 0x1000, // Packet Buffer Allocation
- E1000_FCRTL = 0x2160, // Flow Control Receive Threshold Low
- E1000_FCRTH = 0x2168, // Flow Control Receive Threshold High
- E1000_RDBAL = 0x2800, // Rx Descriptor Base Address Low
- E1000_RDBAH = 0x2804, // Rx Descriptor Base Address High
- E1000_RDLEN = 0x2808, // Rx Descriptor Length
- E1000_RDH = 0x2810, // Rx Descriptor Head
- E1000_RDT = 0x2818, // Rx Descriptor Tail
- E1000_RXDCTL = 0x2828, // Rx Descriptor Control
- E1000_TDBAL = 0x3800, // Tx Descriptor Base Address Low
- E1000_TDBAH = 0x3804, // Tx Descriptor Base Address High
- E1000_TDLEN = 0x3808, // Tx Descriptor Length
- E1000_TDH = 0x3810, // Tx Descriptor Head
- E1000_TDT = 0x3818, // Tx Descriptor Tail
- E1000_TXDCTL = 0x3828, // Tx Descriptor Control
- E1000_TPR = 0x40D0, // Total Packets Received
- E1000_TPT = 0x40D4, // Total Packets Transmitted
- E1000_RA = 0x5400, // Receive-filter Array
-};
-
-/***************** e1000 device structure *****************/
-
-struct tx_desc {
- uint64_t base_address;
- uint16_t packet_length;
- uint8_t cksum_offset;
- uint8_t desc_command;
- uint8_t desc_status;
- uint8_t cksum_origin;
- uint16_t special_info;
-};
-
-struct rx_desc {
- uint64_t base_address;
- uint16_t packet_length;
- uint16_t packet_cksum;
- uint8_t desc_status;
- uint8_t desc_errors;
- uint16_t vlan_tag;
-};
-
-#endif
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2016 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/****************************************************************************
- * drivers/net/encx24j600.c
- *
- * Copyright (C) 2013-2014 UVC Ingenieure. All rights reserved.
- * Author: Max Holtzberg <mh@uvc.de>
- *
- * References:
- * - ENC424J600/624J600 Data Sheet, Stand-Alone 10/100 Ethernet Controller
- * with SPI or Parallel Interface, DS39935C, 2010 Microchip Technology Inc.
- *
- * Derived from enc28j60 driver written by:
- *
- * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <tinyara/config.h>
-
-#if defined(CONFIG_NET) && defined(CONFIG_ENCX24J600)
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <time.h>
-#include <string.h>
-#include <debug.h>
-#include <errno.h>
-#include <queue.h>
-
-#include <arpa/inet.h>
-
-#include <tinyara/arch.h>
-#include <tinyara/irq.h>
-#include <tinyara/wdog.h>
-#include <tinyara/spi/spi.h>
-#include <tinyara/wqueue.h>
-#include <tinyara/clock.h>
-#include <tinyara/net/net.h>
-#include <tinyara/net/arp.h>
-#include <tinyara/net/netdev.h>
-#include <tinyara/net/encx24j600.h>
-
-#ifdef CONFIG_NET_PKT
-#include <tinyara/net/pkt.h>
-#endif
-
-#include "encx24j600.h"
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Configuration ************************************************************/
-
-/* ENCX24J600 Configuration Settings:
- *
- * CONFIG_ENCX24J600 - Enabled ENCX24J600 support
- * CONFIG_ENCX24J600_SPIMODE - Controls the SPI mode
- * CONFIG_ENCX24J600_FREQUENCY - Define to use a different bus frequency
- * CONFIG_ENCX24J600_NINTERFACES - Specifies the number of physical ENCX24J600
- * devices that will be supported.
- * CONFIG_ENCX24J600_STATS - Collect network statistics
- */
-
-/* The ENCX24J600 spec says that it supports SPI mode 0,0 only: "The
- * implementation used on this device supports SPI mode 0,0 only. In
- * addition, the SPI port requires that SCK be at Idle in a low state;
- * selectable clock polarity is not supported." However, sometimes you
- * need to tinker with these things.
- */
-
-#ifndef CONFIG_ENCX24J600_SPIMODE
-#define CONFIG_ENCX24J600_SPIMODE SPIDEV_MODE0
-#endif
-
-/* CONFIG_ENCX24J600_NINTERFACES determines the number of physical interfaces
- * that will be supported.
- */
-
-#ifndef CONFIG_ENCX24J600_NINTERFACES
-#define CONFIG_ENCX24J600_NINTERFACES 1
-#endif
-
-/* CONFIG_NET_ETH_MTU must always be defined */
-
-#if !defined(CONFIG_NET_ETH_MTU) && (CONFIG_NET_ETH_MTU <= MAX_FRAMELEN)
-#error "CONFIG_NET_ETH_MTU is not valid for the ENCX24J600"
-#endif
-
-/* We need to have the work queue to handle SPI interrupts */
-
-#ifndef CONFIG_SCHED_WORKQUEUE
-#error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
-#endif
-
-/* CONFIG_ENCX24J600_DUMPPACKET will dump the contents of each packet to the console. */
-
-#ifdef CONFIG_ENCX24J600_DUMPPACKET
-#define enc_dumppacket(m, a, n) lib_dumpbuffer(m, a, n)
-#else
-#define enc_dumppacket(m, a, n)
-#endif
-
-/* The ENCX24J600 will not do interrupt level processing */
-
-#ifndef CONFIG_NET_NOINTS
-#warning "CONFIG_NET_NOINTS should be set"
-#endif
-
-/* Low-level register debug */
-
-#if !defined(CONFIG_DEBUG) || !defined(CONFIG_DEBUG_NET)
-#undef CONFIG_ENCX24J600_REGDEBUG
-#endif
-
-/* Timing *******************************************************************/
-
-/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
-
-#define ENC_WDDELAY (1*CLK_TCK)
-#define ENC_POLLHSEC (1*2)
-
-/* TX timeout = 1 minute */
-
-#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)
-
-/* Register poll timeout */
-
-#define ENC_REGPOLLTIMEOUT MSEC2TICK(5000)
-
-/* Packet Memory ************************************************************/
-
-/* Packet memory layout */
-
-#define PKTMEM_ALIGNED_BUFSIZE ((CONFIG_NET_ETH_MTU + 1) & ~1)
-#define PKTMEM_RX_START (PKTMEM_START + PKTMEM_SIZE / 2) /* Followed by RX buffer */
-#define PKTMEM_RX_SIZE (PKTMEM_SIZE - PKTMEM_RX_START)
-#define PKTMEM_RX_END (PKTMEM_START + PKTMEM_SIZE) /* RX buffer goes to the end of SRAM */
-
-/* We use preinitialized TX descriptors */
-
-#define ENC_NTXDESCR ((PKTMEM_RX_START - PKTMEM_START) / PKTMEM_ALIGNED_BUFSIZE)
-
-/* This is a helper pointer for accessing the contents of the Ethernet header */
-
-#define BUF ((struct eth_hdr_s *)priv->dev.d_buf)
-
-/* Debug ********************************************************************/
-
-#ifdef CONFIG_ENCX24J600_REGDEBUG
-#define enc_wrdump(a, v) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: %02x<-%04x\n", a, v);
-#define enc_rddump(a, v) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: %02x->%04x\n", a, v);
-#define enc_bfsdump(a, m) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: %02x|=%04x\n", a, m);
-#define enc_bfcdump(a, m) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: %02x&=~%04x\n", a, m);
-#define enc_cmddump(c) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: CMD: %02x\n", c);
-#define enc_bmdump(c, b, s) \
- lowsyslog(LOG_DEBUG, "ENCX24J600: CMD: %02x buffer: %p length: %d\n", c, b, s);
-#else
-#define enc_wrdump(a, v)
-#define enc_rddump(a, v)
-#define enc_bfsdump(a, m)
-#define enc_bfcdump(a, m)
-#define enc_cmddump(c)
-#define enc_bmdump(c, b, s)
-#endif
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-/* The state of the interface */
-
-enum enc_state_e {
- ENCSTATE_UNINIT = 0, /* The interface is in an uninitialized state */
- ENCSTATE_DOWN, /* The interface is down */
- ENCSTATE_UP, /* The interface is up */
- ENCSTATE_RUNNING /* The interface is has a cable plugged in and is ready to use */
-};
-
-struct enc_descr_s {
- struct enc_descr_next *flink;
- uint16_t addr;
- uint16_t len;
- systime_t ts; /* Timestamp of reception for timeout */
-};
-
-/* The enc_driver_s encapsulates all state information for a single hardware
- * interface
- */
-
-struct enc_driver_s {
- /* Device control */
-
- uint8_t ifstate; /* Interface state: See ENCSTATE_* */
- uint8_t bank; /* Currently selected bank command */
- uint16_t nextpkt; /* Next packet address */
- FAR const struct enc_lower_s *lower; /* Low-level MCU-specific support */
-
- /* Timing */
-
- WDOG_ID txpoll; /* TX poll timer */
- WDOG_ID txtimeout; /* TX timeout timer */
-
- /* If we don't own the SPI bus, then we cannot do SPI accesses from the
- * interrupt handler.
- */
-
- struct work_s irqwork; /* Interrupt continuation work queue support */
- struct work_s towork; /* Tx timeout work queue support */
- struct work_s pollwork; /* Poll timeout work queue support */
-
- struct enc_descr_s txdescralloc[ENC_NTXDESCR];
- struct enc_descr_s rxdescralloc[CONFIG_ENCX24J600_NRXDESCR];
-
- sq_queue_t txfreedescr; /* Free inititialized TX descriptors */
- sq_queue_t rxfreedescr; /* Free RX descriptors */
- 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 */
-
- FAR struct spi_dev_s *spi;
-
- /* This holds the information visible to uIP/NuttX */
-
- struct net_driver_s dev; /* Interface understood by uIP */
-
- /* Statistics */
-
-#ifdef CONFIG_ENCX24J600_STATS
- struct enc_stats_s stats;
-#endif
-};
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static struct enc_driver_s g_encx24j600[CONFIG_ENCX24J600_NINTERFACES];
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/* Low-level SPI helpers */
-
-#ifdef CONFIG_SPI_OWNBUS
-static inline void enc_configspi(FAR struct spi_dev_s *spi);
-#define enc_lock(priv);
-#define enc_unlock(priv);
-#else
-#define enc_configspi(spi)
-static void enc_lock(FAR struct enc_driver_s *priv);
-static inline void enc_unlock(FAR struct enc_driver_s *priv);
-#endif
-
-/* SPI control register access */
-
-static inline void enc_setethrst(FAR struct enc_driver_s *priv);
-static void enc_setbank(FAR struct enc_driver_s *priv, uint8_t bank);
-static uint16_t enc_rdreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg);
-static void enc_wrreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t wrdata);
-static int enc_waitreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits, uint16_t value);
-static void enc_bfs(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits);
-static void enc_bfc(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits);
-static void enc_cmd(FAR struct enc_driver_s *priv, uint8_t cmd, uint16_t arg);
-
-#if 0 /* Sometimes useful */
-static void enc_rxdump(FAR struct enc_driver_s *priv);
-static void enc_txdump(FAR struct enc_driver_s *priv);
-#endif
-
-/* SPI buffer transfers */
-
-static void enc_rdbuffer(FAR struct enc_driver_s *priv, FAR uint8_t *buffer, size_t buflen);
-static inline void enc_wrbuffer(FAR struct enc_driver_s *priv, FAR const uint8_t *buffer, size_t buflen);
-
-/* PHY register access */
-
-static uint16_t enc_rdphy(FAR struct enc_driver_s *priv, uint8_t phyaddr);
-static void enc_wrphy(FAR struct enc_driver_s *priv, uint8_t phyaddr, uint16_t phydata);
-
-/* Common TX logic */
-
-static int enc_txenqueue(FAR struct enc_driver_s *priv);
-static int enc_transmit(FAR struct enc_driver_s *priv);
-static int enc_txpoll(struct net_driver_s *dev);
-
-/* Common RX logic */
-
-static struct enc_descr_s *enc_rxgetdescr(FAR struct enc_driver_s *priv);
-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_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);
-
-/* Watchdog timer expirations */
-
-static void enc_toworker(FAR void *arg);
-static void enc_txtimeout(int argc, uint32_t arg, ...);
-static void enc_pollworker(FAR void *arg);
-static void enc_polltimer(int argc, uint32_t arg, ...);
-
-/* TinyAra callback functions */
-
-static int enc_ifup(struct net_driver_s *dev);
-static int enc_ifdown(struct net_driver_s *dev);
-static int enc_txavail(struct net_driver_s *dev);
-static int enc_rxavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_IGMP
-static int enc_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-static int enc_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-#endif
-
-/* Initialization */
-
-static void enc_pwrsave(FAR struct enc_driver_s *priv);
-static void enc_setmacaddr(FAR struct enc_driver_s *priv);
-static void enc_resetbuffers(FAR struct enc_driver_s *priv);
-static int enc_reset(FAR struct enc_driver_s *priv);
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: enc_configspi
- *
- * Description:
- * Configure the SPI for use with the ENCX24J600
- *
- * Parameters:
- * spi - Reference to the SPI driver structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SPI_OWNBUS
-static inline void enc_configspi(FAR struct spi_dev_s *spi)
-{
- /* Configure SPI for the ENCX24J600. But only if we own the SPI bus.
- * Otherwise, don't bother because it might change.
- */
-
- SPI_SETMODE(spi, CONFIG_ENCX24J600_SPIMODE);
- SPI_SETBITS(spi, 8);
- SPI_SETFREQUENCY(spi, CONFIG_ENCX24J600_FREQUENCY);
-}
-#endif
-
-/****************************************************************************
- * Function: enc_lock
- *
- * Description:
- * Select the SPI, locking and re-configuring if necessary
- *
- * Parameters:
- * spi - Reference to the SPI driver structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifndef CONFIG_SPI_OWNBUS
-static void enc_lock(FAR struct enc_driver_s *priv)
-{
- /* Lock the SPI bus in case there are multiple devices competing for the SPI
- * bus.
- */
-
- SPI_LOCK(priv->spi, true);
-
- /* Now make sure that the SPI bus is configured for the ENCX24J600 (it
- * might have gotten configured for a different device while unlocked)
- */
-
- SPI_SETMODE(priv->spi, CONFIG_ENCX24J600_SPIMODE);
- SPI_SETBITS(priv->spi, 8);
- SPI_SETFREQUENCY(priv->spi, CONFIG_ENCX24J600_FREQUENCY);
-}
-#endif
-
-/****************************************************************************
- * Function: enc_unlock
- *
- * Description:
- * De-select the SPI
- *
- * Parameters:
- * spi - Reference to the SPI driver structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifndef CONFIG_SPI_OWNBUS
-static inline void enc_unlock(FAR struct enc_driver_s *priv)
-{
- /* Relinquish the lock on the bus. */
-
- SPI_LOCK(priv->spi, false);
-}
-#endif
-
-/****************************************************************************
- * Function: enc_cmd
- *
- * Description:
- * Execute two byte command.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * cmd - ENCX24J600 two-byte command
- * arg - Two byte argument to the command
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_cmd(FAR struct enc_driver_s *priv, uint8_t cmd, uint16_t arg)
-{
- DEBUGASSERT(priv && priv->spi);
-
- /* Select ENCX24J600 chip */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- (void)SPI_SEND(priv->spi, cmd); /* Clock out the command */
- (void)SPI_SEND(priv->spi, arg & 0xff); /* Clock out the low byte */
- (void)SPI_SEND(priv->spi, arg >> 8); /* Clock out the high byte */
-
- /* De-select ENCX24J600 chip. */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_wrdump(cmd, arg);
-}
-
-/****************************************************************************
- * Function: enc_setethrst
- *
- * Description:
- * Issues System Reset by setting ETHRST (ECON2<4>)
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static inline void enc_setethrst(FAR struct enc_driver_s *priv)
-{
- DEBUGASSERT(priv && priv->spi);
-
- /* Select ENC28J60 chip */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- /* Send the system reset command. */
-
- (void)SPI_SEND(priv->spi, ENC_SETETHRST);
-
- up_udelay(25);
-
- /* De-select ENC28J60 chip. */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_cmddump(ENC_SETETHRST);
-}
-
-/****************************************************************************
- * Function: enc_setbank
- *
- * Description:
- * Set the bank for the next control register access.
- *
- * Assumption:
- * The caller has exclusive access to the SPI bus
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * bank - SPI command to select the bank with
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * The chip is selected and SPI is ready for communication.
- *
- ****************************************************************************/
-
-static void enc_setbank(FAR struct enc_driver_s *priv, uint8_t bank)
-{
-
- /* Check if a bank has to be set and if the bank setting has changed.
- * For registers that are available on all banks, the bank command is set to 0.
- */
-
- if (bank != 0 && bank != priv->bank) {
- /* Select bank with supplied command */
-
- SPI_SEND(priv->spi, bank);
-
- /* Then remember the bank setting */
-
- priv->bank = bank;
- }
-}
-
-/****************************************************************************
- * Function: enc_rdreg
- *
- * Description:
- * Read one word from a control register using the RCR command.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * ctrlreg - Bit encoded address of banked register to read
- *
- * Returned Value:
- * The byte read from the banked register
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static uint16_t enc_rdreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg)
-{
- uint16_t rddata;
-
- DEBUGASSERT(priv && priv->spi);
- DEBUGASSERT((ctrlreg & 0xe0) == 0); /* banked regeitsers only */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);
-
- enc_setbank(priv, GETBANK(ctrlreg));
-
- SPI_SEND(priv->spi, ENC_RCR | GETADDR(ctrlreg));
-
- rddata = SPI_SEND(priv->spi, 0); /* Clock in the low byte */
- rddata |= SPI_SEND(priv->spi, 0) << 8; /* Clock in the high byte */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_rddump(GETADDR(ctrlreg), rddata);
-
- return rddata;
-}
-
-/****************************************************************************
- * Function: enc_wrreg
- *
- * Description:
- * Write one word to a control register using the WCR command.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * ctrlreg - Bit encoded address of banked register to write
- * wrdata - The data to send
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_wrreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t wrdata)
-{
- DEBUGASSERT(priv && priv->spi);
- DEBUGASSERT((ctrlreg & 0xe0) == 0); /* banked regeitsers only */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- enc_setbank(priv, GETBANK(ctrlreg));
-
- SPI_SEND(priv->spi, ENC_WCR | GETADDR(ctrlreg));
- SPI_SEND(priv->spi, wrdata & 0xff); /* Clock out the low byte */
- SPI_SEND(priv->spi, wrdata >> 8); /* Clock out the high byte */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_wrdump(GETADDR(ctrlreg), wrdata);
-}
-
-/****************************************************************************
- * Function: enc_waitbreg
- *
- * Description:
- * Wait until banked register bit(s) take a specific value (or a timeout
- * occurs).
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * ctrlreg - Bit encoded address of banked register to check
- * bits - The bits to check (a mask)
- * value - The value of the bits to return (value under mask)
- *
- * Returned Value:
- * OK on success, negated errno on failure
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_waitreg(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits, uint16_t value)
-{
- systime_t start = clock_systimer();
- systime_t elapsed;
- uint16_t rddata;
-
- /* Loop until the exit condition is met */
-
- do {
- /* Read the byte from the requested banked register */
-
- rddata = enc_rdreg(priv, ctrlreg);
- elapsed = clock_systimer() - start;
- } while ((rddata & bits) != value && elapsed < ENC_REGPOLLTIMEOUT);
-
- return (rddata & bits) == value ? OK : -ETIMEDOUT;
-}
-
-/****************************************************************************
- * Function: enc_bfs
- *
- * Description:
- * Bit Field Set.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * ctrlreg - Bit encoded address of banked register to set bits in
- * bits - The bits to set (a mask)
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_bfs(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits)
-{
- DEBUGASSERT(priv && priv->spi);
-
- /* Select ENCX24J600 chip */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- /* Set the bank */
-
- enc_setbank(priv, GETBANK(ctrlreg));
-
- /* Send the BFS command and data. The sequence requires 24-clocks:
- * 8 to clock out the cmd + 16 to clock out the data.
- */
-
- (void)SPI_SEND(priv->spi, ENC_BFS | GETADDR(ctrlreg)); /* Clock out the command */
- (void)SPI_SEND(priv->spi, bits & 0xff); /* Clock out the low byte */
- (void)SPI_SEND(priv->spi, bits >> 8); /* Clock out the high byte */
-
- /* De-select ENCX24J600 chip. */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_bfsdump(GETADDR(ctrlreg), bits);
-}
-
-/****************************************************************************
- * Function: enc_bfc
- *
- * Description:
- * Bit Field Clear.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * ctrlreg - Bit encoded address of banked register to clear bits in
- * bits - The bits to clear (a mask)
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_bfc(FAR struct enc_driver_s *priv, uint16_t ctrlreg, uint16_t bits)
-{
- DEBUGASSERT(priv && priv->spi);
-
- /* Select ENCX24J600 chip */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- /* Set the bank */
-
- enc_setbank(priv, GETBANK(ctrlreg));
-
- /* Send the BFC command and data. The sequence requires 24-clocks:
- * 8 to clock out the cmd + 16 to clock out the data.
- */
-
- (void)SPI_SEND(priv->spi, ENC_BFC | GETADDR(ctrlreg)); /* Clock out the command */
- (void)SPI_SEND(priv->spi, bits & 0xff); /* Clock out the low byte */
- (void)SPI_SEND(priv->spi, bits >> 8); /* Clock out the high byte */
-
- /* De-select ENCX24J600 chip. */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_bfcdump(GETADDR(ctrlreg), bits);
-}
-
-/****************************************************************************
- * Function: enc_txdump enc_rxdump
- *
- * Description:
- * Dump registers associated with receiving or sending packets.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#if 0 /* Sometimes useful */
-static void enc_rxdump(FAR struct enc_driver_s *priv)
-{
- lowsyslog(LOG_DEBUG, "Rx Registers:\n");
- lowsyslog(LOG_DEBUG, " EIE: %02x EIR: %02x\n", enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR));
- lowsyslog(LOG_DEBUG, " ESTAT: %02x ECON1: %02x ECON2: %02x\n", enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1), enc_rdgreg(priv, ENC_ECON2));
- lowsyslog(LOG_DEBUG, " ERXST: %02x %02x\n", enc_rdbreg(priv, ENC_ERXSTH), enc_rdbreg(priv, ENC_ERXSTL));
- lowsyslog(LOG_DEBUG, " ERXND: %02x %02x\n", enc_rdbreg(priv, ENC_ERXNDH), enc_rdbreg(priv, ENC_ERXNDL));
- lowsyslog(LOG_DEBUG, " ERXRDPT: %02x %02x\n", enc_rdbreg(priv, ENC_ERXRDPTH), enc_rdbreg(priv, ENC_ERXRDPTL));
- lowsyslog(LOG_DEBUG, " ERXFCON: %02x EPKTCNT: %02x\n", enc_rdbreg(priv, ENC_ERXFCON), enc_rdbreg(priv, ENC_EPKTCNT));
- lowsyslog(LOG_DEBUG, " MACON1: %02x MACON3: %02x\n", enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3));
- lowsyslog(LOG_DEBUG, " MAMXFL: %02x %02x\n", enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
- lowsyslog(LOG_DEBUG, " MAADR: %02x:%02x:%02x:%02x:%02x:%02x\n", enc_rdbreg(priv, ENC_MAADR1), enc_rdbreg(priv, ENC_MAADR2), enc_rdbreg(priv, ENC_MAADR3), enc_rdbreg(priv, ENC_MAADR4), enc_rdbreg(priv, ENC_MAADR5), enc_rdbreg(priv, ENC_MAADR6));
-}
-#endif
-
-#if 0 /* Sometimes useful */
-static void enc_txdump(FAR struct enc_driver_s *priv)
-{
- lowsyslog(LOG_DEBUG, "Tx Registers:\n");
- lowsyslog(LOG_DEBUG, " EIE: %02x EIR: %02x ESTAT: %02x\n", enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR));
- lowsyslog(LOG_DEBUG, " ESTAT: %02x ECON1: %02x\n", enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1));
- lowsyslog(LOG_DEBUG, " ETXST: %02x %02x\n", enc_rdbreg(priv, ENC_ETXSTH), enc_rdbreg(priv, ENC_ETXSTL));
- lowsyslog(LOG_DEBUG, " ETXND: %02x %02x\n", enc_rdbreg(priv, ENC_ETXNDH), enc_rdbreg(priv, ENC_ETXNDL));
- lowsyslog(LOG_DEBUG, " MACON1: %02x MACON3: %02x MACON4: %02x\n", enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3), enc_rdbreg(priv, ENC_MACON4));
- lowsyslog(LOG_DEBUG, " MACON1: %02x MACON3: %02x MACON4: %02x\n", enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3), enc_rdbreg(priv, ENC_MACON4));
- lowsyslog(LOG_DEBUG, " MABBIPG: %02x MAIPG %02x %02x\n", enc_rdbreg(priv, ENC_MABBIPG), enc_rdbreg(priv, ENC_MAIPGH), enc_rdbreg(priv, ENC_MAIPGL));
- lowsyslog(LOG_DEBUG, " MACLCON1: %02x MACLCON2: %02x\n", enc_rdbreg(priv, ENC_MACLCON1), enc_rdbreg(priv, ENC_MACLCON2));
- lowsyslog(LOG_DEBUG, " MAMXFL: %02x %02x\n", enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
-}
-#endif
-
-/****************************************************************************
- * Function: enc_rdbuffer
- *
- * Description:
- * Read a buffer of data from RX Data Buffer.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * buffer - A pointer to the buffer to read into
- * buflen - The number of bytes to read
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * RX Data pointer is set to the correct address
- *
- ****************************************************************************/
-
-static void enc_rdbuffer(FAR struct enc_driver_s *priv, FAR uint8_t *buffer, size_t buflen)
-{
- DEBUGASSERT(priv && priv->spi);
-
- /* Select ENCX24J600 chip */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);
-
- /* Send the read buffer memory command (ignoring the response) */
-
- (void)SPI_SEND(priv->spi, ENC_RRXDATA);
-
- /* Then read the buffer data */
-
- SPI_RECVBLOCK(priv->spi, buffer, buflen);
-
- /* De-select ENCX24J600 chip. */
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_bmdump(ENC_RRXDATA, buffer, buflen);
-}
-
-/****************************************************************************
- * Function: enc_wrbuffer
- *
- * Description:
- * Write a buffer of data.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * buffer - A pointer to the buffer to write from
- * buflen - The number of bytes to write
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * General Purpose Write pointer is set to the correct address
- *
- ****************************************************************************/
-
-static inline void enc_wrbuffer(FAR struct enc_driver_s *priv, FAR const uint8_t *buffer, size_t buflen)
-{
- DEBUGASSERT(priv && priv->spi);
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, true);;
-
- SPI_SEND(priv->spi, ENC_WGPDATA);
- SPI_SNDBLOCK(priv->spi, buffer, buflen);
-
- SPI_SELECT(priv->spi, SPIDEV_ETHERNET, false);
- enc_bmdump(ENC_WGPDATA, buffer, buflen);
-}
-
-/****************************************************************************
- * Function: enc_rdphy
- *
- * Description:
- * Read 16-bits of PHY data.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * phyaddr - The PHY register address
- *
- * Returned Value:
- * 16-bit value read from the PHY
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static uint16_t enc_rdphy(FAR struct enc_driver_s *priv, uint8_t phyaddr)
-{
- uint16_t data = 0;
-
- /* "To read from a PHY register:
- * 1. Write the address of the PHY register to read from into the MIREGADR
- * register (Register 3-1). Make sure to also set reserved bit 8 of this
- * register.
- */
-
- enc_wrreg(priv, ENC_MIREGADR, phyaddr);
-
- /* 2. Set the MIIRD bit (MICMD<0>, Register 3-2). The read operation begins
- * and the BUSY bit (MISTAT<0>, Register 3-3) is automatically set by
- * hardware.
- */
-
- enc_bfs(priv, ENC_MICMD, MICMD_MIIRD);
-
- /* 3. Wait 25.6 μs. Poll the BUSY (MISTAT<0>) bit to be certain that the
- * operation is complete. While busy, the host controller should not
- * start any MIISCAN operations or write to the MIWR register. When the
- * MAC has obtained the register contents, the BUSY bit will clear
- * itself.
- */
-
- up_udelay(26);
- if (enc_waitreg(priv, ENC_MISTAT, MISTAT_BUSY, 0x00) == OK) {
- /* 4. Clear the MIIRD (MICMD<0>) bit. */
-
- enc_bfc(priv, ENC_MICMD, MICMD_MIIRD);
-
- /* 5. Read the desired data from the MIRD register. For 8-bit interfaces,
- * the order that these bytes are read is unimportant."
- */
-
- data = enc_rdreg(priv, ENC_MIRD);
- }
-
- return data;
-}
-
-/****************************************************************************
- * Function: enc_wrphy
- *
- * Description:
- * write 16-bits of PHY data.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- * phyaddr - The PHY register address
- * phydata - 16-bit data to write to the PHY
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_wrphy(FAR struct enc_driver_s *priv, uint8_t phyaddr, uint16_t phydata)
-{
- /* "To write to a PHY register:
- *
- * 1. Write the address of the PHY register to write to into the MIREGADR
- * register. Make sure to also set reserved bit 8 of this register.
- */
-
- enc_wrreg(priv, ENC_MIREGADR, 0x0100 | phyaddr);
-
- /* 2. Write the 16 bits of data into the MIWR register. The low byte must
- * be written first, followed by the high byte.
- */
-
- enc_wrreg(priv, ENC_MIWR, phydata);
-
- /* 3. Writing to the high byte of MIWR begins the MIIM transaction and the
- * BUSY (MISTAT<0>) bit is automatically set by hardware.
- *
- * The PHY register is written after the MIIM operation completes, which takes
- * 25.6 μs. When the write operation has completed, the BUSY bit clears
- * itself. The host controller should not start any MIISCAN, MIWR or MIIRD
- * operations while the BUSY bit is set.
- */
-
- up_udelay(26);
- enc_waitreg(priv, ENC_MISTAT, MISTAT_BUSY, 0);
-}
-
-/****************************************************************************
- * Function: enc_transmit
- *
- * Description:
- * Start hardware transmission. Called either from:
- *
- * - pkif interrupt when an application responds to the receipt of data
- * by trying to send something, or
- * - From watchdog based polling.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_transmit(FAR struct enc_driver_s *priv)
-{
- struct enc_descr_s *descr;
-
- /* dequeue next packet to transmit */
-
- descr = (struct enc_descr_s *)sq_remfirst(&priv->txqueue);
-
- DEBUGASSERT(descr != NULL);
-
- /* Verify that the hardware is ready to send another packet. The driver
- * starts a transmission process by setting ECON1.TXRTS. When the packet is
- * finished transmitting or is aborted due to an error/cancellation, the
- * ECON1.TXRTS bit will be cleared.
- *
- * NOTE: If we got here, then we have committed to sending a packet.
- * higher level logic must have assured that (1) there is no transmission
- * in progress, and that (2) TX-related interrupts are disabled.
- */
-
- DEBUGASSERT((enc_rdreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0);
-
- /* Set TXStart and TXLen registers. */
-
- enc_wrreg(priv, ENC_ETXST, descr->addr);
- enc_wrreg(priv, ENC_ETXLEN, descr->len);
-
- /* Set TXRTS to send the packet in the transmit buffer */
-
- enc_bfs(priv, ENC_ECON1, ECON1_TXRTS);
-
- /* Setup the TX timeout watchdog (perhaps restarting the timer). Note:
- * Is there a race condition. Could the TXIF interrupt occur before
- * the timer is started?
- */
-
- (void)wd_start(priv->txtimeout, ENC_TXTIMEOUT, enc_txtimeout, 1, (uint32_t)priv);
-
- /* free the descriptor */
-
- sq_addlast((sq_entry_t *) descr, &priv->txfreedescr);
-
- return OK;
-}
-
-/****************************************************************************
- * Function: enc_txenqueue
- *
- * Description:
- * Write packet from d_buf to the enc's SRAM if a free descriptor is available.
- * The filled descriptor is enqueued for transmission.
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * A packet is available in d_buf.
- * Interrupts are enabled but the caller holds the uIP lock.
- *
- ****************************************************************************/
-
-static int enc_txenqueue(FAR struct enc_driver_s *priv)
-{
- int ret = OK;
- struct enc_descr_s *descr;
-
- DEBUGASSERT(priv->dev.d_len > 0);
-
- /* Increment statistics */
-
-#ifdef CONFIG_ENCX24J600_STATS
- priv->stats.txrequests++;
-#endif
-
- descr = (struct enc_descr_s *)sq_remfirst(&priv->txfreedescr);
-
- if (descr != NULL) {
- enc_dumppacket("Write packet to enc SRAM", priv->dev.d_buf, priv->dev.d_len);
-
- /* Copy the packet into the transmit buffer described by the current
- * tx descriptor
- */
-
- enc_cmd(priv, ENC_WGPWRPT, descr->addr);
- enc_wrbuffer(priv, priv->dev.d_buf, priv->dev.d_len);
-
- /* store packet length */
-
- descr->len = priv->dev.d_len;
-
- /* enqueue packet */
-
- sq_addlast((sq_entry_t *) descr, &priv->txqueue);
-
- /* if currently no transmission is active, trigger the transmission */
-
- if ((enc_rdreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0) {
- enc_transmit(priv);
- }
- } else {
- nlldbg("no free descriptors\n");
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-/****************************************************************************
- * Function: enc_txpoll
- *
- * Description:
- * Enqueues uIP packets if available.
- * This is a callback from netif_poll(). netif_poll() may be called:
- *
- * 1. When the preceding TX packet send is complete,
- * 2. When the preceding TX packet send timedout and the interface is reset
- * 3. During normal TX polling
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * Interrupts are enabled but the caller holds the uIP lock.
- *
- ****************************************************************************/
-
-static int enc_txpoll(struct net_driver_s *dev)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
- int ret = OK;
-
- /* If the polling resulted in data that should be sent out on the network,
- * the field d_len is set to a value > 0.
- */
-
- nllvdbg("Poll result: d_len=%d\n", priv->dev.d_len);
-
- if (priv->dev.d_len > 0) {
- /* Look up the destination MAC address and add it to the Ethernet
- * header.
- */
-
-#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(priv->dev.d_flags))
-#endif
- {
- arp_out(&priv->dev);
- }
-#endif /* CONFIG_NET_IPv4 */
-
-#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- else
-#endif
- {
- neighbor_out(&priv->dev);
- }
-#endif /* CONFIG_NET_IPv6 */
-
- /* Send the packet */
-
- ret = enc_txenqueue(priv);
- }
-
- /* If zero is returned, the polling will continue until all connections have
- * been examined.
- */
-
- return ret;
-}
-
-/****************************************************************************
- * Function: enc_linkstatus
- *
- * Description:
- * The current link status can be obtained from the PHSTAT1.LLSTAT or
- * PHSTAT2.LSTAT.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_linkstatus(FAR struct enc_driver_s *priv)
-{
- uint16_t regval;
-
- /* 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
- * FULDPX (MACON2<0>) to match PHYDPX (ESTAT<10>).
- */
-
- regval = enc_rdreg(priv, ENC_ESTAT);
-
- if (regval & ESTAT_PHYLNK) {
- if (regval & ESTAT_PHYDPX) {
- /* Configure full-duplex */
-
- enc_wrreg(priv, ENC_MABBIPG, 0x15);
- enc_bfs(priv, ENC_MACON2, MACON2_FULDPX);
- } else {
- /* Configure half-duplex */
-
- enc_wrreg(priv, ENC_MABBIPG, 0x12);
- enc_bfc(priv, ENC_MACON2, MACON2_FULDPX);
- }
-
- netdev_carrier_on(&priv->dev);
- priv->ifstate = ENCSTATE_RUNNING;
- } else {
- netdev_carrier_off(&priv->dev);
- priv->ifstate = ENCSTATE_UP;
- }
-}
-
-/****************************************************************************
- * Function: enc_txif
- *
- * Description:
- * An TXIF interrupt was received indicating that the last TX packet(s) is
- * done
- *
- * 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_txif(FAR struct enc_driver_s *priv)
-{
- if (sq_empty(&priv->txqueue)) {
- /* If no further xmits are pending, then cancel the TX timeout */
-
- wd_cancel(priv->txtimeout);
-
- /* Poll for TX packets from the networking layer */
-
- netif_poll(&priv->dev, enc_txpoll);
- } else {
- /* process txqueue */
-
- enc_transmit(priv);
- }
-}
-
-/****************************************************************************
- * Function: enc_rxldpkt
- *
- * Description:
- * Load packet from the enc's RX buffer to the driver 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);
-}
-
-/****************************************************************************
- * Function: enc_rxgetdescr
- *
- * Description:
- * Check for a free descriptor in the free list. If no free descriptor is
- * available a pending descriptor will be freed and returned
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * A free rx descriptor
- *
- * Assumptions:
- * Interrupts are enabled but the caller holds the uIP lock.
- *
- ****************************************************************************/
-
-static struct enc_descr_s *enc_rxgetdescr(FAR struct enc_driver_s *priv)
-{
- if (sq_empty(&priv->rxfreedescr)) {
- DEBUGASSERT(sq_peek(&priv->rxqueue) != NULL);
-
- /* Packets are held in the enc's SRAM until the space is needed */
-
- enc_rxrmpkt(priv, (struct enc_descr_s *)sq_peek(&priv->rxqueue));
- }
-
- return (struct enc_descr_s *)sq_remfirst(&priv->rxfreedescr);
-}
-
-/****************************************************************************
- * 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 != NULL) {
- if (descr == (struct enc_descr_s *)sq_peek(&priv->rxqueue)) {
- /* Wrap address properly around */
- addr = (descr->addr - PKTMEM_RX_START + descr->len - 2 + PKTMEM_RX_SIZE)
- % PKTMEM_RX_SIZE + PKTMEM_RX_START;
-
- DEBUGASSERT(addr >= PKTMEM_RX_START && addr < PKTMEM_RX_END);
-
- nllvdbg("ERXTAIL %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->rxfreedescr);
- }
-}
-
-/****************************************************************************
- * Function: enc_rxdispatch
- *
- * Description:
- * Give the newly received packet to uIP.
- *
- * 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_rxdispatch(FAR struct enc_driver_s *priv)
-{
- 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);
-
-#ifdef CONFIG_NET_PKT
- /* When packet sockets are enabled, feed the frame into the packet tap */
-
- pkt_input(&priv->dev);
-#endif
-
- /* We only accept IP packets of the configured type and ARP packets */
-
-#ifdef CONFIG_NET_IPv4
- if (BUF->type == HTONS(ETHTYPE_IP)) {
- nllvdbg("IPv4 frame\n");
-
- /* Handle ARP on input then give the IPv4 packet to the network
- * layer
- */
-
- arp_ipin(&priv->dev);
- ret = ipv4_input(&priv->dev);
-
- if (ret == OK || (clock_systimer() - descr->ts) > ENC_RXTIMEOUT) {
- /* If packet has been successfully 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) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(priv->dev.d_flags))
-#endif
- {
- arp_out(&priv->dev);
- }
-#ifdef CONFIG_NET_IPv6
- else {
- neighbor_out(&priv->dev);
- }
-#endif
-
- /* And send the packet */
-
- enc_txenqueue(priv);
- }
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- if (BUF->type == HTONS(ETHTYPE_IP6)) {
- nllvdbg("Iv6 frame\n");
-
- /* Give the IPv6 packet to the network layer */
-
- ret = ipv6_input(&priv->dev);
-
- if (ret == OK || (clock_systimer() - descr->ts) > ENC_RXTIMEOUT) {
- /* If packet has been successfully 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) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv4
- if (IFF_IS_IPv4(priv->dev.d_flags)) {
- arp_out(&priv->dev);
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- {
- neighbor_out(&priv->dev);
- }
-#endif
-
- /* And send the packet */
-
- enc_txenqueue(priv);
- }
- } else
-#endif
-#ifdef CONFIG_NET_ARP
- if (BUF->type == htons(ETHTYPE_ARP)) {
- nllvdbg("ARP packet received (%02x)\n", BUF->type);
- 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
-#endif
- {
- /* free unsupported packet */
-
- enc_rxrmpkt(priv, descr);
-
- nlldbg("Unsupported packet type dropped (%02x)\n", htons(BUF->type));
- }
-
- descr = next;
- }
-}
-
-/****************************************************************************
- * Function: enc_pktif
- *
- * Description:
- * An interrupt was received indicating the availability of a new RX packet
- *
- * 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_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);
-
- /* Enqueue all pending packets to the RX queue until PKTCNT == 0 or
- * no more descriptors are available.
- */
-
- pktcnt = (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) >> ESTAT_PKTCNT_SHIFT;
-
- while (pktcnt > 0) {
- curpkt = priv->nextpkt;
-
- /* Set the rx data pointer to the start of the received packet (ERXRDPT) */
-
- enc_cmd(priv, ENC_WRXRDPT, curpkt);
-
- /* 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, rsv, 8);
-
- /* 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 pktcnt: %d\n", priv->nextpkt, pktlen, rxstat, pktcnt);
-
- /* We enqueue the packet first and remove it later if its faulty.
- * This way we avoid freeing packets that are not processed yet.
- */
-
- descr = enc_rxgetdescr(priv);
-
- /* 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;
- sq_addlast((sq_entry_t *) descr, &priv->rxqueue);
-
- /* Check if the packet was received OK */
-
- if ((rxstat & RXSTAT_OK) == 0) {
- nlldbg("ERROR: RXSTAT: %08x\n", rxstat);
-
- /* Discard packet */
-
- enc_rxrmpkt(priv, descr);
-
-#ifdef CONFIG_ENCX24J600_STATS
- priv->stats.rxnotok++;
-#endif
- }
-
- /* Check for a usable packet length (4 added for the CRC) */
-
- else if (pktlen > (CONFIG_NET_ETH_MTU + 4) || pktlen <= (ETH_HDRLEN + 4)) {
- nlldbg("Bad packet size dropped (%d)\n", pktlen);
-
- /* Discard packet */
-
- enc_rxrmpkt(priv, descr);
-
-#ifdef CONFIG_ENCX24J600_STATS
- priv->stats.rxpktlen++;
-#endif
- }
-
- /* Decrement PKTCNT */
-
- enc_bfs(priv, ENC_ECON1, ECON1_PKTDEC);
-
- /* Try to process the packet */
-
- enc_rxdispatch(priv);
-
- /* Read out again, maybe there has another packet arrived */
-
- pktcnt = (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) >> ESTAT_PKTCNT_SHIFT;
- }
-}
-
-/****************************************************************************
- * 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)
-{
- struct enc_descr_s *descr;
-
-#if 0
- /* Free the last received packet from the RX queue */
-
- nlldbg("rx abort\n");
- nlldbg("ESTAT: %04x\n", enc_rdreg(priv, ENC_ESTAT));
- nlldbg("EIR: %04x\n", enc_rdreg(priv, ENC_EIR));
- nlldbg("ERXTAIL: %04x\n", enc_rdreg(priv, ENC_ERXTAIL));
- nlldbg("ERXHAED: %04x\n", enc_rdreg(priv, ENC_ERXHEAD));
-
- descr = (struct enc_descr_s *)sq_peek(&priv->rxqueue);
-
- while (descr != NULL) {
- nlldbg("addr: %04x len: %d\n", descr->addr, descr->len);
- descr = (struct enc_descr_s *)sq_next(descr);
- }
-
- DEBUGASSERT(false);
-#endif
-
- descr = (struct enc_descr_s *)sq_peek(&priv->rxqueue);
-
- if (descr != NULL) {
- enc_rxrmpkt(priv, descr);
-
- nlldbg("pending packet freed\n");
- } else {
- /* If no pending packet blocks the reception, reset all buffers */
-
- enc_resetbuffers(priv);
- }
-}
-
-/****************************************************************************
- * Function: enc_irqworker
- *
- * Description:
- * Perform interrupt handling logic outside of the interrupt handler (on
- * the work queue thread).
- *
- * Parameters:
- * arg - The reference to the driver structure (case to void*)
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_irqworker(FAR void *arg)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg;
- net_lock_t lock;
- uint16_t eir;
-
- DEBUGASSERT(priv);
-
- /* Get exclusive access to both uIP and the SPI bus. */
-
- lock = net_lock();
- enc_lock(priv);
-
- /* A good practice is for the host controller to clear the Global Interrupt
- * Enable bit, INTIE (EIE<15>), immediately after an interrupt event. This
- * causes the interrupt pin to return to the non-asserted (high) state. Once
- * the interrupt has been serviced, the INTIE bit is set again to re-enable
- * interrupts. If a new interrupt occurs while servicing another, the act of
- * resetting the global enable bit will cause a new falling edge to occur on
- * the interrupt pin and ensure that the host does not miss any events
- */
-
- enc_bfc(priv, ENC_EIE, EIE_INTIE);
-
- /* Loop until all interrupts have been processed (EIR==0). Note that
- * there is no infinite loop check... if there are always pending interrupts,
- * we are just broken.
- */
-
- while ((eir = enc_rdreg(priv, ENC_EIR) & EIR_ALLINTS) != 0) {
- /* Handle interrupts according to interrupt register register bit
- * settings.
- */
-
- nllvdbg("EIR: %04x\n", eir);
-
- if ((eir & EIR_DMAIF) != 0) { /* DMA interrupt */
- /* Not used by this driver. Just clear the interrupt request. */
-
- enc_bfc(priv, ENC_EIR, EIR_DMAIF);
- }
-
- /* LINKIF: The link change interrupt occurs when the PHY link status
- * changes. This flag is set by hardware when a link has either been
- * established or broken between the device and a remote Ethernet partner.
- * The current link status can be read from PHYLNK (ESTAT<8>). The
- * interrupt should be cleared by software once it has been serviced.
- *
- * To enable the link change interrupt, set LINKIE (EIE<11>).
- */
-
- if ((eir & EIR_LINKIF) != 0) { /* PHY Link Status Change */
- enc_linkstatus(priv); /* Get current link status */
- enc_bfc(priv, ENC_EIR, EIR_LINKIF); /* Clear the LINKIF interrupt */
- }
-
- /* The transmit complete interrupt occurs when the transmission of a
- * frame has ended (whether or not it was successful). This flag is set
- * when TXRTS (ECON1<1>) is cleared. The interrupt should be cleared by
- * software once it has been serviced.
- */
-
- if ((eir & EIR_TXIF) != 0) { /* Transmit Done */
- enc_txif(priv);
- enc_bfc(priv, ENC_EIR, EIR_TXIF);
- }
-
- /* 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.
- *
- * To enable the receive abort interrupt, set RXABTIE (EIE<1>).
- * The corresponding interrupt flag is RXABTIF (EIR<1>).
- */
-
- 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 */
- }
-
- /* The received packet pending interrupt occurs when one or more frames
- * have been received and are ready for software processing. This flag is
- * set when the PKTCNT<7:0> (ESTAT<7:0>) bits are non-zero. This interrupt
- * flag is read-only and will automatically clear when the PKTCNT bits are
- * decremented to zero. For more details about receiving and processing
- * incoming frames, refer to Section 9.0 "Transmitting and Receiving
- * Packets".
- *
- * To enable the received packet pending interrupt, set PKTIE (EIE<6>).
- * The corresponding interrupt flag is PKTIF (EIR<6>).
- */
-
- if ((eir & EIR_PKTIF) != 0 /* RX Packet Pending */
- && (enc_rdreg(priv, ENC_ESTAT) & ESTAT_PKTCNT_MASK) != 0) {
- enc_pktif(priv); /* Handle packet receipt */
-
- /* No clearing necessary, after PKTCNT == 0 the bit is automatically
- * cleared. This means we will loop until all packets are processed.
- */
- }
-#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:
- *
- * * Excessive collisions occurred as defined by the Retransmission
- * Maximum, MAXRET<3:0> bits (MACLCON<3:0>), setting. If this occurs,
- * the COLCNT bits (ETXSTAT<3:0>) will indicate the number of collisions
- * that occurred.
- *
- * * A late collision occurred after 63 bytes were transmitted. If this
- * occurs, LATECOL (ETXSTAT<10>) will be set.
- *
- * * The medium was busy and the packet was deferred. If this occurs,
- * EXDEFER (ETXSTAT<8>) will be set.
- *
- * * The application aborted the transmission by clearing TXRTS
- * (ECON1<1>).
- *
- * The interrupt should be cleared by software once it has been serviced.
- * To enable the transmit abort interrupt, set TXABTIE (EIE<2>).
- */
-
- if ((eir & EIR_TXABTIF) != 0) { /* Transmit Abort */
- priv->stats.txerifs++;
- enc_bfc(priv, ENC_EIR, EIR_TXABTIF); /* Clear the TXABTIF interrupt */
- }
-#endif
- }
-
- /* Enable GPIO interrupts */
-
- priv->lower->enable(priv->lower);
-
- /* Enable Ethernet interrupts */
-
- enc_bfs(priv, ENC_EIE, EIE_INTIE);
-
- /* Release lock on the SPI bus and uIP */
-
- enc_unlock(priv);
- net_unlock(lock);
-}
-
-/****************************************************************************
- * Function: enc_interrupt
- *
- * Description:
- * Hardware interrupt handler
- *
- * Parameters:
- * irq - Number of the IRQ that generated the interrupt
- * context - Interrupt register state save info (architecture-specific)
- *
- * Returned Value:
- * OK on success
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_interrupt(int irq, FAR void *context)
-{
- register FAR struct enc_driver_s *priv = &g_encx24j600[0];
-
- /* In complex environments, we cannot do SPI transfers from the interrupt
- * handler because semaphores are probably used to lock the SPI bus. In
- * this case, we will defer processing to the worker thread. This is also
- * much kinder in the use of system resources and is, therefore, probably
- * a good thing to do in any event.
- */
-
- DEBUGASSERT(work_available(&priv->irqwork));
-
- /* Notice that further GPIO interrupts are disabled until the work is
- * actually performed. This is to prevent overrun of the worker thread.
- * Interrupts are re-enabled in enc_irqworker() when the work is completed.
- */
-
- priv->lower->disable(priv->lower);
- return work_queue(HPWORK, &priv->irqwork, enc_irqworker, (FAR void *)priv, 0);
-}
-
-/****************************************************************************
- * Function: enc_toworker
- *
- * Description:
- * Our TX watchdog timed out. This is the worker thread continuation of
- * the watchdog timer interrupt. Reset the hardware and start again.
- *
- * Parameters:
- * arg - The reference to the driver structure (case to void*)
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_toworker(FAR void *arg)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg;
- net_lock_t lock;
- int ret;
-
- nlldbg("Tx timeout\n");
- DEBUGASSERT(priv);
-
- /* Get exclusive access to uIP. */
-
- lock = net_lock();
-
- /* Increment statistics and dump debug info */
-
-#ifdef CONFIG_ENCX24J600_STATS
- priv->stats.txtimeouts++;
-#endif
-
- /* Then reset the hardware: Take the interface down, then bring it
- * back up
- */
-
- ret = enc_ifdown(&priv->dev);
- DEBUGASSERT(ret == OK);
- ret = enc_ifup(&priv->dev);
- DEBUGASSERT(ret == OK);
- (void)ret;
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&priv->dev, enc_txpoll);
-
- /* Release uIP */
-
- net_unlock(lock);
-}
-
-/****************************************************************************
- * Function: enc_txtimeout
- *
- * Description:
- * Our TX watchdog timed out. Called from the timer interrupt handler.
- * The last TX never completed. Perform work on the worker thread.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_txtimeout(int argc, uint32_t arg, ...)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg;
- int ret;
-
- /* In complex environments, we cannot do SPI transfers from the timout
- * handler because semaphores are probably used to lock the SPI bus. In
- * this case, we will defer processing to the worker thread. This is also
- * much kinder in the use of system resources and is, therefore, probably
- * a good thing to do in any event.
- */
-
- DEBUGASSERT(priv && work_available(&priv->towork));
-
- /* Notice that Tx timeout watchdog is not active so further Tx timeouts
- * can occur until we restart the Tx timeout watchdog.
- */
-
- ret = work_queue(HPWORK, &priv->towork, enc_toworker, (FAR void *)priv, 0);
- (void)ret;
- DEBUGASSERT(ret == OK);
-}
-
-/****************************************************************************
- * Function: enc_pollworker
- *
- * Description:
- * Periodic timer handler continuation.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_pollworker(FAR void *arg)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg;
- net_lock_t lock;
-
- DEBUGASSERT(priv);
-
- /* Get exclusive access to both uIP and the SPI bus. */
-
- lock = net_lock();
- enc_lock(priv);
-
- /* Verify that the hardware is ready to send another packet. The driver
- * start a transmission process by setting ECON1.TXRTS. When the packet is
- * finished transmitting or is aborted due to an error/cancellation, the
- * ECON1.TXRTS bit will be cleared.
- */
-
- if ((enc_rdreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0) {
- /* Yes.. update TCP timing states and poll uIP for new XMIT data. Hmmm..
- * looks like a bug here to me. Does this mean if there is a transmit
- * in progress, we will missing TCP time state updates?
- */
-
- (void)netif_timer(&priv->dev, enc_txpoll, ENC_POLLHSEC);
- }
-
- /* Release lock on the SPI bus and uIP */
-
- enc_unlock(priv);
- net_unlock(lock);
-
- /* Setup the watchdog poll timer again */
-
- (void)wd_start(priv->txpoll, ENC_WDDELAY, enc_polltimer, 1, arg);
-}
-
-/****************************************************************************
- * Function: enc_polltimer
- *
- * Description:
- * Periodic timer handler. Called from the timer interrupt handler.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_polltimer(int argc, uint32_t arg, ...)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)arg;
- int ret;
-
- /* In complex environments, we cannot do SPI transfers from the timout
- * handler because semaphores are probably used to lock the SPI bus. In
- * this case, we will defer processing to the worker thread. This is also
- * much kinder in the use of system resources and is, therefore, probably
- * a good thing to do in any event.
- */
-
- DEBUGASSERT(priv && work_available(&priv->pollwork));
-
- /* Notice that poll watchdog is not active so further poll timeouts can
- * occur until we restart the poll timeout watchdog.
- */
-
- ret = work_queue(HPWORK, &priv->pollwork, enc_pollworker, (FAR void *)priv, 0);
- (void)ret;
- DEBUGASSERT(ret == OK);
-}
-
-/****************************************************************************
- * Function: enc_ifup
- *
- * Description:
- * TinyAra Callback: Bring up the Ethernet interface when an IP address is
- * provided
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_ifup(struct net_driver_s *dev)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
- int ret;
-
- nlldbg("Bringing up: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Initialize Ethernet interface, set the MAC address, and make sure that
- * the ENC28J80 is not in power save mode.
- */
-
- ret = enc_reset(priv);
- if (ret == OK) {
- enc_setmacaddr(priv);
-
- /* Enable interrupts at the ENCX24J600. Interrupts are still disabled
- * at the interrupt controller.
- */
-
- enc_bfc(priv, ENC_EIR, EIR_ALLINTS);
- enc_bfs(priv, ENC_EIE, EIE_INTIE | EIE_LINKIE | EIE_PKTIE | EIE_RXABTIE | EIE_TXIE);
-
-#ifdef CONFIG_ENCX24J600_STATS
- enc_bfs(priv, ENC_EIE, EIE_TXABTIE);
-#endif
-
- /* Enable the receiver */
-
- enc_bfs(priv, ENC_ECON1, ECON1_RXEN);
-
- /* Set and activate a timer process */
-
- (void)wd_start(priv->txpoll, ENC_WDDELAY, enc_polltimer, 1, (uint32_t)priv);
-
- /* Mark the interface up and enable the Ethernet interrupt at the
- * controller
- */
-
- priv->ifstate = ENCSTATE_UP;
- priv->lower->enable(priv->lower);
- }
-
- /* Un-lock the SPI bus */
-
- enc_unlock(priv);
-
- return ret;
-}
-
-/****************************************************************************
- * Function: enc_ifdown
- *
- * Description:
- * TinyAra Callback: Stop the interface.
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_ifdown(struct net_driver_s *dev)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
- irqstate_t flags;
- int ret;
-
- nlldbg("Taking down: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Disable the Ethernet interrupt */
-
- flags = irqsave();
- priv->lower->disable(priv->lower);
-
- /* Cancel the TX poll timer and TX timeout timers */
-
- wd_cancel(priv->txpoll);
- wd_cancel(priv->txtimeout);
-
- /* Reset the device and leave in the power save state */
-
- ret = enc_reset(priv);
- enc_pwrsave(priv);
-
- priv->ifstate = ENCSTATE_DOWN;
- irqrestore(flags);
-
- /* Un-lock the SPI bus */
-
- enc_unlock(priv);
-
- return ret;
-}
-
-/****************************************************************************
- * Function: enc_txavail
- *
- * 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 TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- ****************************************************************************/
-
-static int enc_txavail(struct net_driver_s *dev)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
- irqstate_t flags;
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Ignore the notification if the interface is not yet up */
-
- flags = irqsave();
- if (priv->ifstate == ENCSTATE_RUNNING) {
- /* Check if the hardware is ready to send another packet. The driver
- * starts a transmission process by setting ECON1.TXRTS. When the packet is
- * finished transmitting or is aborted due to an error/cancellation, the
- * ECON1.TXRTS bit will be cleared.
- */
-
- if ((enc_rdreg(priv, ENC_ECON1) & ECON1_TXRTS) == 0) {
- /* The interface is up and TX is idle; poll uIP for new XMIT data */
-
- (void)netif_poll(&priv->dev, enc_txpoll);
- }
- }
-
- /* Un-lock the SPI bus */
-
- irqrestore(flags);
- enc_unlock(priv);
-
- 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 TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- ****************************************************************************/
-
-static int enc_rxavail(struct net_driver_s *dev)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
-
- if (!sq_empty(&priv->rxqueue)) {
- nllvdbg("RX queue not empty, trying to dispatch\n");
- enc_rxdispatch(priv);
- }
-
- return OK;
-}
-
-/****************************************************************************
- * Function: enc_addmac
- *
- * Description:
- * TinyAra Callback: Add the specified MAC address to the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be added
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int enc_addmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Add the MAC address to the hardware multicast routing table */
-
-#warning "Multicast MAC support not implemented"
-
- /* Un-lock the SPI bus */
-
- enc_unlock(priv);
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: enc_rmmac
- *
- * Description:
- * TinyAra Callback: Remove the specified MAC address from the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be removed
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int enc_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct enc_driver_s *priv = (FAR struct enc_driver_s *)dev->d_private;
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Add the MAC address to the hardware multicast routing table */
-
-#warning "Multicast MAC support not implemented"
-
- /* Un-lock the SPI bus */
-
- enc_unlock(priv);
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: enc_pwrsave
- *
- * Description:
- * The ENCX24J600 may be placed in Power-Down mode through the command
- * interface. In this mode, the device will no longer be able to transmit or
- * receive any packets or perform DMA operations. However, most registers, and
- * all buffer memories, retain their states and remain accessible by the host
- * controller. The clock driver also remains operational, leaving the CLKOUT
- * function unaffected. However, the MAC/MII and PHY registers all become
- * inaccessible, and the PHY registers lose their current states.
- *
- * 1. Turn off the Modular Exponentiation and AES engines by clearing
- * CRYPTEN (EIR<15>).
- * 2. Turn off packet reception by clearing RXEN (ECON1<0>).
- * 3. Wait for any in-progress receptions to complete by polling
- * RXBUSY (ESTAT<13>) until it is clear.
- * 4. Wait for any current transmission operation to complete by verifying
- * that TXRTS (ECON1<1>) is clear.
- * 5. Power-down the PHY by setting the PSLEEP bit (PHCON1<11>).
- * 6. Power-down the Ethernet interface by clearing
- * ETHEN and STRCH (ECON2<15,14>). Disabling the LED stretching behavior is
- * necessary to ensure no LEDs get trapped in a perpetually illuminated
- * state in the event they are being stretched on when ETHEN is cleared.
- *
- * Note:
- * Instead of providing a powerup function, the job is done by enc_reset.
- * enc_ifup calls it anyway.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_pwrsave(FAR struct enc_driver_s *priv)
-{
- uint16_t regval;
-
- nllvdbg("Set PWRSV\n");
-
- /* 1. Turn off AES */
-
- enc_bfc(priv, ENC_EIR, EIR_CRYPTEN);
-
- /* 2. Turn off packet reception */
-
- enc_bfc(priv, ENC_ECON1, ECON1_RXEN);
-
- /* 3. Wait for pending reception to complete */
-
- enc_waitreg(priv, ENC_ESTAT, ESTAT_RXBUSY, 0);
-
- /* 4. Wait for any current transmissions to complete */
-
- enc_waitreg(priv, ENC_ECON1, ECON1_TXRTS, 0);
-
- /* 5. Power down the PHY */
-
- regval = enc_rdphy(priv, ENC_PHCON1);
- regval |= PHCON1_PSLEEP;
- enc_wrphy(priv, ENC_PHCON1, regval);
-
- /* 6. Power down the Ethernet interface */
-
- enc_bfc(priv, ENC_ECON2, ECON2_ETHEN | ECON2_STRCH);
-}
-
-/****************************************************************************
- * Function: enc_ldmacaddr
- *
- * Description:
- * Load the MAC address from the ENCX24j600 and write it to the device
- * structure.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_ldmacaddr(FAR struct enc_driver_s *priv)
-{
- uint16_t regval;
- uint8_t *mac = priv->dev.d_mac.ether_addr_octet;
-
- nvdbg("Using ENCX24J600's built in MAC address\n");
-
- regval = enc_rdreg(priv, ENC_MAADR1);
- mac[0] = regval & 0xff;
- mac[1] = regval >> 8;
-
- regval = enc_rdreg(priv, ENC_MAADR2);
- mac[2] = regval & 0xff;
- mac[3] = regval >> 8;
-
- regval = enc_rdreg(priv, ENC_MAADR3);
- mac[4] = regval & 0xff;
- mac[5] = regval >> 8;
-}
-
-/****************************************************************************
- * Function: enc_setmacaddr
- *
- * Description:
- * Set the MAC address to the configured value. This is done after ifup
- * or after a TX timeout. Note that this means that the interface must
- * be down before configuring the MAC addr.
- * If the MAC address is 0 in all digits, the ENCX24J600's MAC is read out.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_setmacaddr(FAR struct enc_driver_s *priv)
-{
- uint8_t *mac = priv->dev.d_mac.ether_addr_octet;
- struct ether_addr zmac;
-
- memset(&zmac, 0, sizeof(zmac));
-
- if (memcmp(&priv->dev.d_mac, &zmac, sizeof(zmac)) == 0) {
- /* No user defined MAC address. Read it from the device. */
-
- enc_ldmacaddr(priv);
- } else {
- /* There is a user defined mac address. Write it to the ENCXJ600 */
-
- nvdbg("Using an user defined MAC address\n");
-
- enc_wrreg(priv, ENC_MAADR1, (uint16_t)mac[1] << 8 | (uint16_t)mac[0]);
- enc_wrreg(priv, ENC_MAADR2, (uint16_t)mac[3] << 8 | (uint16_t)mac[2]);
- enc_wrreg(priv, ENC_MAADR3, (uint16_t)mac[5] << 8 | (uint16_t)mac[4]);
- }
-}
-
-/****************************************************************************
- * Function: enc_resetbuffers
- *
- * Description:
- * Initializes the RX/TX queues and configures the enc's RX/TX buffers.
- * Called on general reset and on rxabt interrupt.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static void enc_resetbuffers(FAR struct enc_driver_s *priv)
-{
- int i;
- /* Initialize receive and transmit buffers */
-
- priv->nextpkt = PKTMEM_RX_START;
- enc_wrreg(priv, ENC_ERXST, PKTMEM_RX_START);
-
- /* Program the Tail Pointer, ERXTAIL, to the last even address of the buffer */
-
- enc_wrreg(priv, ENC_ERXTAIL, PKTMEM_RX_END - 2);
-
- sq_init(&priv->txfreedescr);
- sq_init(&priv->rxfreedescr);
- sq_init(&priv->txqueue);
- sq_init(&priv->rxqueue);
-
- /* For transmition we preinitialize the descriptors to aligned NET_BUFFSIZE */
-
- for (i = 0; i < ENC_NTXDESCR; i++) {
- priv->txdescralloc[i].addr = PKTMEM_START + PKTMEM_ALIGNED_BUFSIZE * i;
- sq_addlast((sq_entry_t *)&priv->txdescralloc[i], &priv->txfreedescr);
- }
-
- /* Receive descriptors addresses are set on reception */
-
- for (i = 0; i < CONFIG_ENCX24J600_NRXDESCR; i++) {
- sq_addlast((sq_entry_t *)&priv->rxdescralloc[i], &priv->rxfreedescr);
- }
-}
-
-/****************************************************************************
- * Function: enc_reset
- *
- * Description:
- * Stop, reset, re-initialize, and restart the ENCX24J600. This is done
- * initially, on ifup, and after a TX timeout.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int enc_reset(FAR struct enc_driver_s *priv)
-{
- int ret;
- uint16_t regval;
-
- nllvdbg("Reset\n");
-
- do {
- enc_wrreg(priv, ENC_EUDAST, 0x1234);
- } while (enc_rdreg(priv, ENC_EUDAST) != 0x1234);
-
- /* Wait for clock to become ready */
-
- ret = enc_waitreg(priv, ENC_ESTAT, ESTAT_CLKRDY, ESTAT_CLKRDY);
-
- if (ret != OK) {
- nlldbg("ERROR: encx24j600 clock failed to become ready\n");
- return -ENODEV;
- }
-
- /* Reset the ENCX24J600 */
-
- enc_setethrst(priv);
-
- /* Check if EUDAST has been reset to 0 */
-
- regval = enc_rdreg(priv, ENC_EUDAST);
-
- if (regval != 0x0000) {
- nlldbg("ERROR: encx24j600 seems not to be reset properly\n");
- return -ENODEV;
- }
-
- /**
- * Wait at least 256 μs for the PHY registers and PHY status bits to become
- * available.
- */
- up_udelay(256);
-
- /* Initialize RX/TX buffers */
-
- enc_resetbuffers(priv);
-
-#if 0
- /* When restarting auto-negotiation, the ESTAT_PHYLINK gets set but the link
- * seems not to be ready. Because auto-negotiation is enabled by default
- * (but with different PHANA_* settings) I did not investigate that further.
- */
-
- /* "Typically, when using auto-negotiation, users should write 0x05E1 to PHANA
- * to advertise flow control capability."
- */
-
- enc_wrphy(priv, ENC_PHANA, PHANA_ADPAUS0 | PHANA_AD10FD | PHANA_AD10 | PHANA_AD100FD | PHANA_AD100 | PHANA_ADIEEE0);
-
- /* Restart auto-negotiation */
-
- enc_wrphy(priv, ENC_PHCON1, PHCON1_RENEG);
-
- do {
- regval = enc_rdphy(priv, ENC_PHSTAT1);
- } while ((regval & PHSTAT1_ANDONE) != 0);
-
- nllvdbg("Auto-negotation completed\n");
-
-#endif
-
- enc_linkstatus(priv);
-
- /* Set the maximum packet size which the controller will accept */
-
- enc_wrreg(priv, ENC_MAMXFL, CONFIG_NET_ETH_MTU + 4);
-
- ret = enc_waitreg(priv, ENC_ESTAT, ESTAT_PHYLNK, ESTAT_PHYLNK);
-
- if (ret == OK) {
- enc_linkstatus(priv);
- }
-#if 0
- if (ret != OK) {
- nlldbg("ERROR: encx24j600 failed to establish link\n");
- return -ENODEV;
- }
-#endif
-
- return OK;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: enc_initialize
- *
- * Description:
- * Initialize the Ethernet driver. The ENCX24J600 device is assumed to be
- * in the post-reset state upon entry to this function.
- *
- * Parameters:
- * spi - A reference to the platform's SPI driver for the ENCX24J600
- * lower - The MCU-specific interrupt used to control low-level MCU
- * functions (i.e., ENCX24J600 GPIO interrupts).
- * devno - If more than one ENCX24J600 is supported, then this is the
- * zero based number that identifies the ENCX24J600;
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-int enc_initialize(FAR struct spi_dev_s *spi, FAR const struct enc_lower_s *lower, unsigned int devno)
-{
- FAR struct enc_driver_s *priv;
-
- DEBUGASSERT(devno < CONFIG_ENCX24J600_NINTERFACES);
- priv = &g_encx24j600[devno];
-
- /* Initialize the driver structure */
-
- memset(g_encx24j600, 0, CONFIG_ENCX24J600_NINTERFACES * sizeof(struct enc_driver_s));
- 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 */
-#endif
- priv->dev.d_private = priv; /* Used to recover private state from dev */
-
- /* Create a watchdog for timing polling for and timing of transmisstions */
-
- priv->txpoll = wd_create(); /* Create periodic poll timer */
- priv->txtimeout = wd_create(); /* Create TX timeout timer */
- priv->spi = spi; /* Save the SPI instance */
- priv->lower = lower; /* Save the low-level MCU interface */
-
- /* The interface should be in the down state. However, this function is called
- * too early in initalization to perform the ENCX24J600 reset in enc_ifdown. We
- * are depending upon the fact that the application level logic will call enc_ifdown
- * later to reset the ENCX24J600.
- */
-
- priv->ifstate = ENCSTATE_UNINIT;
-
- /* Attach the interrupt to the driver (but don't enable it yet) */
-
- if (lower->attach(lower, enc_interrupt)) {
- /* We could not attach the ISR to the interrupt */
-
- return -EAGAIN;
- }
-
- /* Configure SPI for the ENCX24J600 */
-
- enc_configspi(priv->spi);
-
- /* Lock the SPI bus so that we have exclusive access */
-
- enc_lock(priv);
-
- /* Load the MAC address */
-
- enc_ldmacaddr(priv);
-
- /* Power down the device */
-
- enc_pwrsave(priv);
-
- /* Unlock the SPI bus */
-
- enc_unlock(priv);
-
- /* Register the device with the OS so that socket IOCTLs can be performed */
-
- return netdev_register(&priv->dev, NET_LL_ETHERNET);
-}
-
-/****************************************************************************
- * Function: enc_stats
- *
- * Description:
- * Return accumulated ENCX24J600 statistics. Statistics are cleared after
- * being returned.
- *
- * Parameters:
- * devno - If more than one ENCX24J600 is supported, then this is the
- * zero based number that identifies the ENCX24J600;
- * stats - The user-provided location to return the statistics.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ENCX24J600_STATS
-int enc_stats(unsigned int devno, struct enc_stats_s *stats)
-{
- FAR struct enc_driver_s *priv;
- irqstate_t flags;
-
- DEBUGASSERT(devno < CONFIG_ENCX24J600_NINTERFACES);
- priv = &g_encx24j600[devno];
-
- /* Disable the Ethernet interrupt */
-
- flags = irqsave();
- memcpy(stats, &priv->stats, sizeof(struct enc_stats_s));
- memset(&priv->stats, 0, sizeof(struct enc_stats_s));
- irqrestore(flags);
- return OK;
-}
-#endif
-#endif /* CONFIG_NET && CONFIG_ENCX24J600_NET */
+++ /dev/null
-/****************************************************************************
- * drivers/net/encx24j600.h
- *
- * Copyright (C) 2013 UVC Ingenieure. All rights reserved.
- * Author: Max Holtberg <mh@uvc.de>
- *
- * References:
- * - ENC424J600/624J600 Data Sheet, Stand-Alone 10/100 Ethernet Controller
- * with SPI or Parallel Interface, DS39935C, 2010 Microchip Technology Inc.
- *
- * 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-#ifndef __DRIVERS_NET_ENCX24J600_H
-#define __DRIVERS_NET_ENCX24J600_H
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* ENCX24J600 Commands ********************************************************/
-
-/* The SPI opcodes are divided into four families:
- *
- * Single Byte: Direct opcode instructions; designed for task-oriented SFR
- * operations with no data returned
- *
- * Two-Byte: Direct opcode instruction; designed for SFR operation with byte
- * data returned
- *
- * Three-Byte: Opcode with word length argument; includes read and write
- * operations, designed for pointer manipulation with word length data returned
- *
- * N-Byte: Opcode with one or more bytes of argument; includes read and write
- * operations designed for general memory space access with one or more bytes of
- * data returned
- */
-
-/* Single-Byte Instructions */
-
-/* Because all single byte instructions are fixed length with no optional
- * parameters, it is possible to execute any instruction immediately following
- * the execution of any single byte instruction without deasserting the chip
- * select line in between.
- */
-
-#define ENC_B0SEL (0xc0) /* Selects SFR Bank 0 */
-#define ENC_B1SEL (0xc2) /* Selects SFR Bank 1 */
-#define ENC_B2SEL (0xc4) /* Selects SFR Bank 2 */
-#define ENC_B3SEL (0xc6) /* Selects SFR Bank 3 */
-#define ENC_SETETHRST (0xca) /* Issues System Reset by setting ETHRST (ECON2<4>) */
-#define ENC_FCDISABLE (0xe0) /* Disables flow control (sets ECON1<7:6> = 00) */
-#define ENC_FCSINGLE (0xe2) /* Transmits a single pause frame (sets ECON1<7:6> = 01) */
-#define ENC_FCMULTIPLE (0xe4) /* Enables flow control with periodic pause frames (sets ECON1<7:6> = 10) */
-#define ENC_FCCLEAR (0xe6) /* Terminates flow control with a final pause frame (sets ECON1<7:6> = 11) */
-#define ENC_SETPKTDEC (0xcc) /* Decrements PKTCNT by setting PKTDEC (ECON1<8>) */
-#define ENC_DMASTOP (0xd2) /* Stops current DMA operation by clearing DMAST (ECON1<5>) */
-#define ENC_DMACKSUM (0xd8) /* Starts DMA and checksum operation (sets ECON1<5:2> = 1000) */
-#define ENC_DMACKSUMS (0xda) /* Starts DMA checksum operation with seed (sets ECON1<5:2> = 1010) */
-#define ENC_DMACOPY (0xdc) /* Starts DMA copy and checksum operation (sets ECON1<5:2> = 1100) */
-#define ENC_DMACOPYS (0xde) /* Starts DMA copy and checksum operation with seed (sets ECON1<5:2> = 1110) */
-#define ENC_SETTXRTS (0xd4) /* Sets TXRTS (ECON1<1>), sends an Ethernet packet */
-#define ENC_ENABLERX (0xe8) /* Enables packet reception by setting RXEN (ECON1<0>) */
-#define ENC_DISABLERX (0xea) /* Disables packet reception by clearing RXEN (ECON1<0>) */
-#define ENC_SETEIE (0xec) /* Enable Ethernet Interrupts by setting INT (ESTAT<15>) */
-#define ENC_CLREIE (0xee) /* Disable Ethernet Interrupts by clearing INT (ESTAT<15>) */
-
-/* Two-Byte Instructions */
-
-/* There is only one instruction in the ENCX24J600 command set which uses two
- * SPI bytes. The Read Bank Select opcode, RBSEL, reads the internal SFR bank
- * select state and returns the value to the host controller.
- */
-
-#define ENC_RBSEL (0xc8)
-
-/* Three-Byte Instructions */
-
-#define ENC_WGPRDPT (0x60) /* Write General Purpose Buffer Read Pointer (EGPRDPT) */
-#define ENC_RGPRDPT (0x62) /* Read General Purpose Buffer Read Pointer (EGPRDPT) */
-#define ENC_WRXRDPT (0x64) /* Write Receive Buffer Read Pointer (ERXRDPT) */
-#define ENC_RRXRDPT (0x66) /* Read Receive Buffer Read Pointer (ERXRDPT) */
-#define ENC_WUDARDPT (0x68) /* Write User-Defined Area Read Pointer (EUDARDPT) */
-#define ENC_RUDARDPT (0x6a) /* Read User-Defined Area Read Pointer (EUDARDPT) */
-#define ENC_WGPWRPT (0x6c) /* Write General Purpose Buffer Write Pointer (EGPWRPT) */
-#define ENC_RGPWRPT (0x6e) /* Read General Purpose Buffer Write Pointer (EGPWRPT) */
-#define ENC_WRXWRPT (0x70) /* Write Receive Buffer Write Pointer (ERXWRPT) */
-#define ENC_RRXWRPT (0x72) /* Read Receive Buffer Write Pointer (ERXWRPT) */
-#define ENC_WUDAWRPT (0x78) /* Write User-Defined Area Write Pointer (EUDAWRPT) */
-#define ENC_RUDAWRPT (0x76) /* Read User-Defined Area Write Pointer (EUDAWRPT) */
-
-/* Banked N-Byte Instructions */
-
-#define ENC_RCR (0x00) /* Read Control Register
- 000 | aaaaa | (Register value returned)) */
-#define ENC_WCR (0x40) /* Write Control Register
- 010 | aaaaa | dddddddd */
-#define ENC_BFS (0x80) /* Bit Field Set
- 100 | aaaaa | dddddddd */
-#define ENC_BFC (0xa0) /* Bit Field Clear
- 101 | aaaaa | dddddddd */
-
-/* Unbanked N-Byte Instructions */
-
-#define ENC_RCRU (0x20) /* Read Control Register(s), Unbanked */
-#define ENC_WCRU (0x22) /* Write Control Register(s), Unbanked */
-#define ENC_BFSU (0x24) /* Bit Field(s) Set, Unbanked */
-#define ENC_BFCU (0x26) /* Bit Field(s) Clear, Unbanked */
-
-/* SRAM Access Instructions */
-
-#define ENC_RGPDATA (0x28) /* Read Data from EGPDATA */
-#define ENC_WGPDATA (0x2a) /* Write Data from EGPDATA */
-#define ENC_RRXDATA (0x2c) /* Read Data from ERXDATA */
-#define ENC_WRXDATA (0x2e) /* Write Data from ERXDATA */
-#define ENC_RUDADATA (0x30) /* Read Data from EUDADATA */
-#define ENC_WUDADATA (0x32) /* Write Data from EUDADATA */
-
-/* Banked Control Registers *************************************************/
-/* Registers are described by 16 bit values. The high byte describes the bank
- * by the appropiate bank selection command.
- * For registers which are available on all banks the comnmand is set to 0.
- * Unbanked registers are identified by 0x01.
- */
-
-#define ENC_ADDR_SHIFT (0)
-#define ENC_ADDR_MASK (0xff << ENC_ADDR_SHIFT)
-#define ENC_BANK_SHIFT (8)
-#define ENC_BANK_MASK (0xff << ENC_BANK_SHIFT)
-
-#define REGADDR(a, b) ((b) << ENC_BANK_SHIFT | (a) << ENC_ADDR_SHIFT)
-#define GETADDR(a) (((a) & ENC_ADDR_MASK) >> ENC_ADDR_SHIFT)
-#define GETBANK(a) (((a) & ENC_BANK_MASK) >> ENC_BANK_SHIFT)
-
-/* Bank 0 Control Register Addresses */
-
-#define ENC_ETXST REGADDR(0x00, ENC_B0SEL)
-#define ENC_ETXLEN REGADDR(0x02, ENC_B0SEL)
-#define ENC_ERXST REGADDR(0x04, ENC_B0SEL)
-#define ENC_ERXTAIL REGADDR(0x06, ENC_B0SEL)
-#define ENC_ERXHEAD REGADDR(0x08, ENC_B0SEL)
-#define ENC_EDMAST REGADDR(0x0a, ENC_B0SEL)
-#define ENC_EDMALEN REGADDR(0x0c, ENC_B0SEL)
-#define ENC_EDMADST REGADDR(0x0e, ENC_B0SEL)
-#define ENC_EDMACS REGADDR(0x10, ENC_B0SEL)
-#define ENC_ETXSTAT REGADDR(0x12, ENC_B0SEL)
-#define ENC_ETXWIRE REGADDR(0x14, ENC_B0SEL)
-
-/* Bank 1 Contro Register Addresses */
-
-#define ENC_EHT1 REGADDR(0x00, ENC_B1SEL)
-#define ENC_EHT2 REGADDR(0x02, ENC_B1SEL)
-#define ENC_EHT3 REGADDR(0x04, ENC_B1SEL)
-#define ENC_EHT4 REGADDR(0x06, ENC_B1SEL)
-#define ENC_EPMM1 REGADDR(0x08, ENC_B1SEL)
-#define ENC_EPMM2 REGADDR(0x0a, ENC_B1SEL)
-#define ENC_EPMM3 REGADDR(0x0c, ENC_B1SEL)
-#define ENC_EPMM4 REGADDR(0x0e, ENC_B1SEL)
-#define ENC_EPMCS REGADDR(0x10, ENC_B1SEL)
-#define ENC_EPMO REGADDR(0x12, ENC_B1SEL)
-#define ENC_ERXFCON REGADDR(0x14, ENC_B1SEL)
-
-/* Bank 2 Control Register Addresses */
-
-#define ENC_MACON1 REGADDR(0x00, ENC_B2SEL)
-#define ENC_MACON2 REGADDR(0x02, ENC_B2SEL)
-#define ENC_MABBIPG REGADDR(0x04, ENC_B2SEL)
-#define ENC_MAIPG REGADDR(0x06, ENC_B2SEL)
-#define ENC_MACLCON REGADDR(0x08, ENC_B2SEL)
-#define ENC_MAMXFL REGADDR(0x0a, ENC_B2SEL)
-/* 0x0c - 0x11 reserved */
-#define ENC_MICMD REGADDR(0x12, ENC_B2SEL)
-#define ENC_MIREGADR REGADDR(0x14, ENC_B2SEL)
-
-/* MAC Control Register 1 Bit Definitions */
-
-#define MACON1_PASSALL (1 << 1)
-#define MACON1_RXPAUS (1 << 2)
-#define MACON1_LOOPBK (1 << 4)
-
-/* MAC Control Register 2 Bit Definitions */
-
-#define MACON2_FULDPX (1 << 0) /* MAC Full-Duplex Enable bit */
-#define MACON2_HFRMEN (1 << 2) /* Huge Frame Enable bit */
-#define MACON2_PHDREN (1 << 3) /* Proprietary Header Enable bit */
-#define MACON2_TXCRCEN (1 << 4) /* Transmit CRC Enable bit */
-#define MACON2_PADCFG0 (1 << 5) /* Automatic Pad and CRC Configuration bits */
-#define MACON2_PADCFG1 (1 << 6)
-#define MACON2_PADCFG2 (1 << 7)
-#define MACON2_NOBKOFF (1 << 12) /* No Backoff Enable bit (applies to half duplex only) */
-#define MACON2_BPEN (1 << 13) /* No Backoff During Back Pressure Enable bit (applies to half duplex only) */
-#define MACON2_DEFER (1 << 14) /* Defer Transmission Enable bit (applies to half duplex only) */
-
-/* MII Management Command Register Bit Definitions */
-
-#define MICMD_MIIRD (1 << 0) /* MII Read Enable bit */
-#define MICMD_MIISCAN (1 << 1) /* MII Scan Enable bit */
-
-/* MII Management Status Register Bit Definitions */
-
-#define MISTAT_BUSY (1 << 0) /* MII Management Busy Status bit */
-#define MISTAT_SCAN (1 << 1) /* MII Management Scan Status bit */
-#define MISTAT_NVALID (1 << 2) /* MII Management Read Data Not Valid Status bit */
-
-/* Bank 3 Control Register Addresses */
-
-#define ENC_MAADR3 REGADDR(0x00, ENC_B3SEL)
-#define ENC_MAADR2 REGADDR(0x02, ENC_B3SEL)
-#define ENC_MAADR1 REGADDR(0x04, ENC_B3SEL)
-#define ENC_MIWR REGADDR(0x06, ENC_B3SEL)
-#define ENC_MIRD REGADDR(0x08, ENC_B3SEL)
-#define ENC_MISTAT REGADDR(0x0a, ENC_B3SEL)
-#define ENC_EPAUS REGADDR(0x0c, ENC_B3SEL)
-#define ENC_ECON2 REGADDR(0x0e, ENC_B3SEL)
-#define ENC_ERXWM REGADDR(0x10, ENC_B3SEL)
-#define ENC_EIE REGADDR(0x12, ENC_B3SEL)
-#define ENC_EIDLED REGADDR(0x14, ENC_B3SEL)
-
-/* Ethernet Control Register Bit Definitions */
-
-#define ECON2_AESLEN0 (1 << 0) /* AES Key Length Control bits */
-#define ECON2_AESLEN1 (1 << 1) /* Modular Exponentiation Length Control bits */
-#define ECON2_MODLEN0 (1 << 2)
-#define ECON2_MODLEN1 (1 << 3)
-#define ECON2_ETHRST (1 << 4) /* Master Ethernet Reset bit */
-#define ECON2_RXRST (1 << 5) /* Receive Logic Reset bit */
-#define ECON2_TXRST (1 << 6) /* Transmit Logic Reset bit */
-#define ECON2_AUTOFC (1 << 7) /* Automatic Flow Control Enable bit */
-#define ECON2_COCON_SHIFT (8) /* CLKOUT Frequency Control bits */
-#define ECON2_COCON_MASK (0x0f << ECON2_COCON_SHIFT)
-#define ECON2_SHA1MD5 (1 << 12) /* SHA-1/MD5 Hash Control bit */
-#define ECON2_TXMAC (1 << 13) /* Automatically Transmit MAC Address Enable bit */
-#define ECON2_STRCH (1 << 14) /* LED Stretching Enable bit */
-#define ECON2_ETHEN (1 << 15) /* Ethernet Enable bit */
-
-/* Ethernet Interrupt Enable Register Bit Definitions */
-
-#define EIE_PCFULIE (1 << 0) /* Packet Counter Full Interrupt Enable bit */
-#define EIE_RXABTIE (1 << 1) /* Receive Abort Interrupt Enable bit */
-#define EIE_TXABTIE (1 << 2) /* Transmit Abort Interrupt Enable bit */
-#define EIE_TXIE (1 << 3) /* Transmit Done Interrupt Enable bit */
-#define EIE_DMAIE (1 << 5) /* DMA Interrupt Enable bit */
-#define EIE_PKTIE (1 << 6) /* RX Packet Pending Interrupt Enable bit */
-#define EIE_LINKIE (1 << 11) /* PHY Link Status Change Interrupt Enable bit */
-#define EIE_AESIE (1 << 12) /* AES Encrypt/Decrypt Interrupt Enable bit */
-#define EIE_HASHIE (1 << 13) /* MD5/SHA-1 Hash Interrupt Enable bit */
-#define EIE_MODEXIE (1 << 14) /* Modular Exponentiation Interrupt Enable bit */
-#define EIE_INTIE (1 << 15) /* INT Global Interrupt Enable bit */
-
-/**
- * The last 10 bytes (16h to 1Fh) of all SPI banks point to a common set of five
- * registers: EUDAST, EUDAND, ESTAT, EIR and ECON1. These are key registers used
- * in controlling and monitoring the operation of the device. Their common
- * banked addresses allow easy access without switching the bank.
- */
-
-/* Common Register Addresses */
-
-#define ENC_EUDAST REGADDR(0x16, 0x00) /* User-Defined Area Start Pointer (EUDAST<7:0>) */
-#define ENC_EUDAND REGADDR(0x18, 0x00) /* User-Defined Area End Pointer (EUDAND<7:0>) */
-#define ENC_ESTAT REGADDR(0x1a, 0x00)
-#define ENC_EIR REGADDR(0x1c, 0x00)
-#define ENC_ECON1 REGADDR(0x1e, 0x00)
-
-/* Ethernet Status Register Bit Definitions */
-
-#define ESTAT_PKTCNT_SHIFT (0) /* Receive Packet Count bits */
-#define ESTAT_PKTCNT_MASK (0xff)
-#define ESTAT_PHYLNK (1 << 8) /* PHY Linked Status bit */
-#define ESTAT_PHYDPX (1 << 10) /* PHY Full Duplex Status bit */
-#define ESTAT_CLKRDY (1 << 12) /* Clock Ready Status bit */
-#define ESTAT_RXBUSY (1 << 13) /* Receive Logic Active Status bit */
-#define ESTAT_FCIDLE (1 << 14) /* Flow Control Idle Status bit */
-#define ESTAT_INT (1 << 15) /* Interrupt Pending Status bit */
-
-/* Ethernet Interrupt Flag Register Bit Definitions */
-
-#define EIR_PCFULIF (1 << 0) /* Packet Counter Full Interrupt Flag bit */
-#define EIR_RXABTIF (1 << 1) /* Receive Abort Interrupt Flag bit */
-#define EIR_TXABTIF (1 << 2) /* Transmit Abort Interrupt Flag bit */
-#define EIR_TXIF (1 << 3) /* Transmit Done Interrupt Flag bit */
-#define EIR_DMAIF (1 << 5) /* DMA Interrupt Flag bit */
-#define EIR_PKTIF (1 << 6) /* RX Packet Pending Interrupt Flag bit */
-#define EIR_LINKIF (1 << 11) /* PHY Link Status Change Interrupt Flag bit */
-#define EIR_AESIF (1 << 12) /* AES Encrypt/Decrypt Interrupt Flag bit */
-#define EIR_HASHIF (1 << 13) /* MD5/SHA-1 Hash Interrupt Flag bit */
-#define EIR_MODEXIF (1 << 14) /* Modular Exponentiation Interrupt Flag bit */
-#define EIR_CRYPTEN (1 << 15) /* Modular Exponentiation and AES Cryptographic Modules Enable bit */
-#define EIR_ALLINTS (0xf86f)
-
-/* Ethernet Control Register 1 Bit Definitions */
-
-#define ECON1_RXEN (1 << 0) /* Receive Enable bit */
-#define ECON1_TXRTS (1 << 1) /* Transmit Request to Send Status/Control bit */
-#define ECON1_DMANOCS (1 << 2) /* DMA No Checksum Control bit */
-#define ECON1_DMACSSD (1 << 3) /* DMA Checksum Seed Control bit */
-#define ECON1_DMACPY (1 << 4) /* DMA Copy Control bit */
-#define ECON1_DMAST (1 << 5) /* DMA Start bit */
-#define ECON1_FCOP0 (1 << 6) /* Flow Control Operation Control/Status bits */
-#define ECON1_FCOP1 (1 << 7) /* Flow Control Operation Control/Status bits */
-#define ECON1_PKTDEC (1 << 8) /* RX Packet Counter Decrement Control bit */
-#define ECON1_AESOP0 (1 << 9) /* AES Operation Control bits */
-#define ECON1_AESOP1 (1 << 10) /* AES Operation Control bits */
-#define ECON1_AESST (1 << 11) /* AES Encrypt/Decrypt Start bit */
-#define ECON1_HASHLST (1 << 12) /* MD5/SHA-1 Hash Last Block Control bit */
-#define ECON1_HASHOP (1 << 13) /* MD5/SHA-1 Hash Operation Control bit */
-#define ECON1_HASHEN (1 << 14) /* MD5/SHA-1 Hash Enable bit */
-#define ECON1_MODEXST (1 << 15) /* Modular Exponentiation Start bit */
-
-/* Unbanked Register Addresses */
-
-#if 0
-/* Disabled to prevent accidental use. All unbanked operations are implemented
- * using the specific manipulation commands.
- */
-#define ENC_EGPDATA 0x80
-#define ENC_ERXDATA 0x82
-#define ENC_EUDADATA 0x84
-#define ENC_EGPRDPT 0x86
-#define ENC_EGPWRPT 0x88
-#define ENC_ERXRDPT 0x8a
-#define ENC_ERXWRPT 0x8c
-#define ENC_EUDARDPT 0x8e
-#define ENC_EUDAWRPT 0x90
-#endif
-
-/* PHY Registers ************************************************************/
-
-#define ENC_PHCON1 0x00
-#define ENC_PHSTAT1 0x01
-#define ENC_PHANA 0x04
-#define ENC_PHANLPA 0x05
-#define ENC_PHANE 0x06
-#define ENC_PHCON2 0x11
-#define ENC_PHSTAT2 0x1b
-#define ENC_PHSTAT3 0x1f
-
-/* PHY Control Register 1 Bit Definitions */
-
-#define PHCON1_PFULDPX (1 << 8) /* PHY Duplex Select Control bit */
-#define PHCON1_RENEG (1 << 9) /* Restart Auto-Negotiation Control bit */
-#define PHCON1_PSLEEP (1 << 11) /* PHY Sleep Enable bit */
-#define PHCON1_ANEN (1 << 12) /* PHY Auto-Negotiation Enable bit */
-#define PHCON1_SPD100 (1 << 13) /* PHY Speed Select Control bit */
-#define PHCON1_PLOOPBK (1 << 14) /* PHY Loopback Enable bit */
-#define PHCON1_PRST (1 << 15) /* PHY Reset bit */
-
-/* PHY Status Register 1 Bit Definitions */
-
-#define PHSTAT1_EXTREGS (1 << 0) /* Extended Capabilities Registers Present Status bit */
-#define PHSTAT1_LLSTAT (1 << 2) /* Latching Link Status bit */
-#define PHSTAT1_ANABLE (1 << 3) /* Auto-Negotiation Ability Status bit */
-#define PHSTAT1_LRFAULT (1 << 4) /* Latching Remote Fault Condition Status bit */
-#define PHSTAT1_ANDONE (1 << 5) /* Auto-Negotiation Done Status bit */
-#define PHSTAT1_HALF10 (1 << 11) /* 10Base-T Half-Duplex Ability Status bit */
-#define PHSTAT1_FULL10 (1 << 12) /* 10Base-T Full-Duplex Ability Status bit */
-#define PHSTAT1_HALF100 (1 << 13) /* 100Base-TX Half-Duplex Ability Status bit */
-#define PHSTAT1_FULL100 (1 << 13) /* 100Base-TX Full-Duplex Ability Status bit */
-
-/* PHY Auto-Negotiation Advertisement Register Bit Definitions */
-
-#define PHANA_ADIEEE0 (1 << 0)
-#define PHANA_ADIEEE1 (1 << 1)
-#define PHANA_ADIEEE2 (1 << 2)
-#define PHANA_ADIEEE3 (1 << 3)
-#define PHANA_ADIEEE4 (1 << 4)
-#define PHANA_AD10 (1 << 5) /* Advertise 10Base-T Half-Duplex Ability bit */
-#define PHANA_AD10FD (1 << 6) /* Advertise 10Base-T Full-Duplex Ability bit */
-#define PHANA_AD100 (1 << 7) /* Advertise 100Base-TX Half-Duplex Ability bit */
-#define PHANA_AD100FD (1 << 8) /* Advertise 100Base-TX Full-Duplex Ability bit */
-/* Advertise PAUSE Flow Control Ability bits */
-/* 11 = Local device supports both symmetric PAUSE and asymmetric PAUSE toward local device */
-/* 10 = Local device supports asymmetric PAUSE toward link partner only */
-/* 01 = Local device supports symmetric PAUSE only (Normal Flow Control mode) */
-/* 00 = Local device does not support PAUSE flow control */
-#define PHANA_ADPAUS0 (1 << 10)
-#define PHANA_ADPAUS1 (1 << 11)
-#define PHANA_ADFAULT (1 << 13) /* Advertise Remote Fault Condition bit */
-#define PHANA_ADNP (1 << 15) /* Advertise Next Page Ability bit */
-
-/* Packet Memory ************************************************************/
-
-/* 24-Kbyte Transmit/Receive Packet Dual Port SRAM */
-
-#define PKTMEM_START 0x0000
-#define PKTMEM_SIZE 0x6000
-
-/* RX Status Bit Definitions ************************************************/
-
-#define RXSTAT_OK (1 << 7)
-
-#endif /* __DRIVERS_NET_ENCX24J600_H */
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2016 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/****************************************************************************
- * drivers/net/vnet.c
- *
- * Copyright (C) 2011 Yu Qiang. All rights reserved.
- * Author: Yu Qiang <yuq825@gmail.com>
- *
- * This file is a part of NuttX:
- *
- * Copyright (C) 2011, 2014 Gregory Nutt. 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. Neither the name NuttX 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.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <tinyara/config.h>
-#if defined(CONFIG_NET) && defined(CONFIG_NET_VNET)
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <time.h>
-#include <string.h>
-#include <debug.h>
-#include <errno.h>
-
-#include <arpa/inet.h>
-
-#include <tinyara/arch.h>
-#include <tinyara/irq.h>
-#include <tinyara/wdog.h>
-#include <tinyara/net/arp.h>
-#include <tinyara/net/netdev.h>
-
-#ifdef CONFIG_NET_PKT
-#include <tinyara/net/pkt.h>
-#endif
-
-#include <rgmp/vnet.h>
-#include <rgmp/stdio.h>
-
-/****************************************************************************
- * Definitions
- ****************************************************************************/
-
-/* CONFIG_VNET_NINTERFACES determines the number of physical interfaces
- * that will be supported.
- */
-
-#ifndef CONFIG_VNET_NINTERFACES
-#define CONFIG_VNET_NINTERFACES 1
-#endif
-
-/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */
-
-#define VNET_WDDELAY (1*CLK_TCK)
-#define VNET_POLLHSEC (1*2)
-
-/* TX timeout = 1 minute */
-
-#define VNET_TXTIMEOUT (60*CLK_TCK)
-
-/* This is a helper pointer for accessing the contents of the Ethernet header */
-
-#define BUF ((struct eth_hdr_s *)vnet->sk_dev.d_buf)
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-/* The vnet_driver_s encapsulates all state information for a single hardware
- * interface
- */
-
-struct vnet_driver_s {
- bool sk_bifup; /* true:ifup false:ifdown */
- WDOG_ID sk_txpoll; /* TX poll timer */
- //WDOG_ID sk_txtimeout; /* TX timeout timer */
-
- /* This holds the information visible to uIP/TinyAra */
-
- struct rgmp_vnet *vnet;
- struct net_driver_s sk_dev; /* Interface understood by uIP */
-};
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static struct vnet_driver_s g_vnet[CONFIG_VNET_NINTERFACES];
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/* Common TX logic */
-
-static int vnet_transmit(FAR struct vnet_driver_s *vnet);
-static int vnet_txpoll(struct net_driver_s *dev);
-
-/* Interrupt handling */
-
-static void vnet_txdone(FAR struct vnet_driver_s *vnet);
-
-/* Watchdog timer expirations */
-
-static void vnet_polltimer(int argc, uint32_t arg, ...);
-static void vnet_txtimeout(int argc, uint32_t arg, ...);
-
-/* TinyAra callback functions */
-
-static int vnet_ifup(struct net_driver_s *dev);
-static int vnet_ifdown(struct net_driver_s *dev);
-static int vnet_txavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_IGMP
-static int vnet_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-static int vnet_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac);
-#endif
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: vnet_transmit
- *
- * Description:
- * Start hardware transmission. Called either from the txdone interrupt
- * handling or from watchdog based polling.
- *
- * Parameters:
- * vnet - Reference to the driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
- *
- ****************************************************************************/
-
-static int vnet_transmit(FAR struct vnet_driver_s *vnet)
-{
- int err;
-
- /* Verify that the hardware is ready to send another packet. If we get
- * here, then we are committed to sending a packet; Higher level logic
- * must have assured that there is not transmission in progress.
- */
-
- /* Increment statistics */
-
- /* Send the packet: address=vnet->sk_dev.d_buf, length=vnet->sk_dev.d_len */
-
- err = vnet_xmit(vnet->vnet, (char *)vnet->sk_dev.d_buf, vnet->sk_dev.d_len);
- if (err) {
- /* Setup the TX timeout watchdog (perhaps restarting the timer) */
-
- //(void)wd_start(vnet->sk_txtimeout, VNET_TXTIMEOUT, vnet_txtimeout, 1, (uint32_t)vnet);
-
- /* When vnet_xmit fail, it means TX buffer is full. Watchdog
- * is of no use here because no TX done INT will happen. So
- * we reset the TX buffer directly.
- */
-
-#ifdef CONFIG_DEBUG
- cprintf("VNET: TX buffer is full\n");
-#endif
- return ERROR;
- } else {
- /* This step may be unnecessary here */
-
- vnet_txdone(vnet);
- }
-
- return OK;
-}
-
-/****************************************************************************
- * Function: vnet_txpoll
- *
- * Description:
- * The transmitter is available, check if uIP has any outgoing packets ready
- * to send. This is a callback from netif_poll(). netif_poll() may be called:
- *
- * 1. When the preceding TX packet send is complete,
- * 2. When the preceding TX packet send timesout and the interface is reset
- * 3. During normal TX polling
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * OK on success; a negated errno on failure
- *
- * Assumptions:
- * May or may not be called from an interrupt handler. In either case,
- * global interrupts are disabled, either explicitly or indirectly through
- * interrupt handling logic.
- *
- ****************************************************************************/
-
-static int vnet_txpoll(struct net_driver_s *dev)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
-
- /* If the polling resulted in data that should be sent out on the network,
- * the field d_len is set to a value > 0.
- */
-
- if (vnet->sk_dev.d_len > 0) {
- /* Look up the destination MAC address and add it to the Ethernet
- * header.
- */
-
-#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(vnet->sk_dev.d_flags))
-#endif
- {
- arp_out(&vnet->sk_dev);
- }
-#endif /* CONFIG_NET_IPv4 */
-
-#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- else
-#endif
- {
- neighbor_out(&vnet->sk_dev);
- }
-#endif /* CONFIG_NET_IPv6 */
-
- /* Send the packet */
-
- vnet_transmit(vnet);
-
- /* Check if there is room in the device to hold another packet. If not,
- * return a non-zero value to terminate the poll.
- */
-
- if (vnet_is_txbuff_full(vnet->vnet)) {
- return 1;
- }
- }
-
- /* If zero is returned, the polling will continue until all connections have
- * been examined.
- */
-
- return 0;
-}
-
-/****************************************************************************
- * Function: rtos_vnet_recv
- *
- * Description:
- * An interrupt was received indicating the availability of a new RX packet
- *
- * Parameters:
- * vnet - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by interrupt handling logic.
- *
- ****************************************************************************/
-
-void rtos_vnet_recv(struct rgmp_vnet *rgmp_vnet, char *data, int len)
-{
- struct vnet_driver_s *vnet = rgmp_vnet->priv;
-
- do {
- /* Check for errors and update statistics */
-
- /* Check if the packet is a valid size for the uIP buffer configuration */
-
- if (len > CONFIG_NET_ETH_MTU || len < 14) {
-#ifdef CONFIG_DEBUG
- cprintf("VNET: receive invalid packet of size %d\n", len);
-#endif
- return;
- }
-
- /* Copy the data data from the hardware to vnet->sk_dev.d_buf. Set
- * amount of data in vnet->sk_dev.d_len
- */
-
- memcpy(vnet->sk_dev.d_buf, data, len);
- vnet->sk_dev.d_len = len;
-
-#ifdef CONFIG_NET_PKT
- /* When packet sockets are enabled, feed the frame into the packet tap */
-
- pkt_input(&vnet->sk_dev);
-#endif
-
- /* We only accept IP packets of the configured type and ARP packets */
-
-#ifdef CONFIG_NET_IPv4
- if (BUF->type == HTONS(ETHTYPE_IP)) {
- nllvdbg("IPv4 frame\n");
-
- /* Handle ARP on input then give the IPv4 packet to the network
- * layer
- */
-
- arp_ipin(&vnet->sk_dev);
- ipv4_input(&vnet->sk_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 (vnet->sk_dev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv6
- if (IFF_IS_IPv4(vnet->sk_dev.d_flags))
-#endif
- {
- arp_out(&vnet->sk_dev);
- }
-#ifdef CONFIG_NET_IPv6
- else {
- neighbor_out(&vnet->sk_dev);
- }
-#endif
-
- /* And send the packet */
-
- vnet_transmit(vnet);
- }
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- if (BUF->type == HTONS(ETHTYPE_IP6)) {
- nllvdbg("Iv6 frame\n");
-
- /* Give the IPv6 packet to the network layer */
-
- ipv6_input(&vnet->sk_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 (vnet->sk_dev.d_len > 0) {
- /* Update the Ethernet header with the correct MAC address */
-
-#ifdef CONFIG_NET_IPv4
- if (IFF_IS_IPv4(vnet->sk_dev.d_flags)) {
- arp_out(&vnet->sk_dev);
- } else
-#endif
-#ifdef CONFIG_NET_IPv6
- {
- neighbor_out(&vnet->sk_dev);
- }
-#endif
-
- /* And send the packet */
-
- vnet_transmit(vnet);
- }
- } else
-#endif
-#ifdef CONFIG_NET_ARP
- if (BUF->type == htons(ETHTYPE_ARP)) {
- arp_arpin(&vnet->sk_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 (vnet->sk_dev.d_len > 0) {
- vnet_transmit(vnet);
- }
- }
-#endif
- } while (0); /* While there are more packets to be processed */
-}
-
-/****************************************************************************
- * Function: vnet_txdone
- *
- * Description:
- * An interrupt was received indicating that the last TX packet(s) is done
- *
- * Parameters:
- * vnet - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void vnet_txdone(FAR struct vnet_driver_s *vnet)
-{
- /* Check for errors and update statistics */
-
- /* If no further xmits are pending, then cancel the TX timeout and
- * disable further Tx interrupts.
- */
-
- //wd_cancel(vnet->sk_txtimeout);
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&vnet->sk_dev, vnet_txpoll);
-}
-
-/****************************************************************************
- * Function: vnet_txtimeout
- *
- * Description:
- * Our TX watchdog timed out. Called from the timer interrupt handler.
- * The last TX never completed. Reset the hardware and start again.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void vnet_txtimeout(int argc, uint32_t arg, ...)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)arg;
-
- /* Increment statistics and dump debug info */
-
- /* Then reset the hardware */
-
- /* Then poll uIP for new XMIT data */
-
- (void)netif_poll(&vnet->sk_dev, vnet_txpoll);
-}
-
-/****************************************************************************
- * Function: vnet_polltimer
- *
- * Description:
- * Periodic timer handler. Called from the timer interrupt handler.
- *
- * Parameters:
- * argc - The number of available arguments
- * arg - The first argument
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by the watchdog logic.
- *
- ****************************************************************************/
-
-static void vnet_polltimer(int argc, uint32_t arg, ...)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)arg;
-
- /* Check if there is room in the send another TX packet. We cannot perform
- * the TX poll if he are unable to accept another packet for transmission.
- */
-
- if (vnet_is_txbuff_full(vnet->vnet)) {
-#ifdef CONFIG_DEBUG
- cprintf("VNET: TX buffer is full\n");
-#endif
- return;
- }
-
- /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm..
- * might be bug here. Does this mean if there is a transmit in progress,
- * we will missing TCP time state updates?
- */
-
- (void)netif_timer(&vnet->sk_dev, vnet_txpoll, VNET_POLLHSEC);
-
- /* Setup the watchdog poll timer again */
-
- (void)wd_start(vnet->sk_txpoll, VNET_WDDELAY, vnet_polltimer, 1, arg);
-}
-
-/****************************************************************************
- * Function: vnet_ifup
- *
- * Description:
- * TinyAra Callback: Bring up the Ethernet interface when an IP address is
- * provided
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int vnet_ifup(struct net_driver_s *dev)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
-
- ndbg("Bringing up: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24);
-
- /* Initialize PHYs, the Ethernet interface, and setup up Ethernet interrupts */
-
- /* Set and activate a timer process */
-
- (void)wd_start(vnet->sk_txpoll, VNET_WDDELAY, vnet_polltimer, 1, (uint32_t)vnet);
-
- vnet->sk_bifup = true;
- return OK;
-}
-
-/****************************************************************************
- * Function: vnet_ifdown
- *
- * Description:
- * TinyAra Callback: Stop the interface.
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-static int vnet_ifdown(struct net_driver_s *dev)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
- irqstate_t flags;
-
- /* Disable the Ethernet interrupt */
-
- flags = irqsave();
-
- /* Cancel the TX poll timer and TX timeout timers */
-
- wd_cancel(vnet->sk_txpoll);
- //wd_cancel(vnet->sk_txtimeout);
-
- /* Put the EMAC is its reset, non-operational state. This should be
- * a known configuration that will guarantee the vnet_ifup() always
- * successfully brings the interface back up.
- */
-
- /* Mark the device "down" */
-
- vnet->sk_bifup = false;
- irqrestore(flags);
- return OK;
-}
-
-/****************************************************************************
- * Function: vnet_txavail
- *
- * 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 TinyAra driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Called in normal user mode
- *
- ****************************************************************************/
-
-static int vnet_txavail(struct net_driver_s *dev)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
- irqstate_t flags;
-
- /* Disable interrupts because this function may be called from interrupt
- * level processing.
- */
-
- flags = irqsave();
-
- /* Ignore the notification if the interface is not yet up */
-
- if (vnet->sk_bifup) {
- /* Check if there is room in the hardware to hold another outgoing packet. */
-
- if (vnet_is_txbuff_full(vnet->vnet)) {
-#ifdef CONFIG_DEBUG
- cprintf("VNET: TX buffer is full\n");
-#endif
- goto out;
- }
-
- /* If so, then poll uIP for new XMIT data */
-
- (void)netif_poll(&vnet->sk_dev, vnet_txpoll);
- }
-
-out:
- irqrestore(flags);
- return OK;
-}
-
-/****************************************************************************
- * Function: vnet_addmac
- *
- * Description:
- * TinyAra Callback: Add the specified MAC address to the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be added
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int vnet_addmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
-
- /* Add the MAC address to the hardware multicast routing table */
-
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Function: vnet_rmmac
- *
- * Description:
- * TinyAra Callback: Remove the specified MAC address from the hardware multicast
- * address filtering
- *
- * Parameters:
- * dev - Reference to the TinyAra driver state structure
- * mac - The MAC address to be removed
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_IGMP
-static int vnet_rmmac(struct net_driver_s *dev, FAR const uint8_t *mac)
-{
- FAR struct vnet_driver_s *vnet = (FAR struct vnet_driver_s *)dev->d_private;
-
- /* Add the MAC address to the hardware multicast routing table */
-
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: vnet_initialize
- *
- * Description:
- * Initialize the Ethernet controller and driver
- *
- * Parameters:
- * intf - In the case where there are multiple EMACs, this value
- * identifies which EMAC is to be initialized.
- *
- * Returned Value:
- * OK on success; Negated errno on failure.
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-int vnet_init(struct rgmp_vnet *vnet)
-{
- struct vnet_driver_s *priv;
- static int i = 0;
-
- if (i >= CONFIG_VNET_NINTERFACES) {
- return -1;
- }
-
- priv = &g_vnet[i++];
-
- /* Initialize the driver structure */
-
- memset(priv, 0, sizeof(struct vnet_driver_s));
- priv->sk_dev.d_ifup = vnet_ifup; /* I/F down callback */
- priv->sk_dev.d_ifdown = vnet_ifdown; /* I/F up (new IP address) callback */
- priv->sk_dev.d_txavail = vnet_txavail; /* New TX data callback */
-#ifdef CONFIG_NET_IGMP
- priv->sk_dev.d_addmac = vnet_addmac; /* Add multicast MAC address */
- priv->sk_dev.d_rmmac = vnet_rmmac; /* Remove multicast MAC address */
-#endif
- priv->sk_dev.d_private = (void *)priv; /* Used to recover private state from dev */
-
- /* Create a watchdog for timing polling for and timing of transmisstions */
-
- priv->sk_txpoll = wd_create(); /* Create periodic poll timer */
- //priv->sk_txtimeout = wd_create(); /* Create TX timeout timer */
-
- priv->vnet = vnet;
- vnet->priv = priv;
-
- /* Register the device with the OS */
-
- (void)netdev_register(&priv->sk_dev), NET_LL_ETHERNET;
-
- return 0;
-}
-
-#endif /* CONFIG_NET && CONFIG_NET_VNET */