summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapps/ChangeLog.txt4
-rw-r--r--apps/nshlib/nsh_netcmds.c44
-rw-r--r--apps/nshlib/nsh_parse.c2
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/Documentation/NuttShell.html49
-rw-r--r--nuttx/arch/rgmp/src/nuttx.c10
-rw-r--r--nuttx/arch/rgmp/src/rgmp.c15
-rw-r--r--nuttx/configs/rgmp/default/defconfig19
-rw-r--r--nuttx/configs/rgmp/nsh/defconfig19
-rw-r--r--nuttx/drivers/net/Make.defs4
-rw-r--r--nuttx/drivers/net/e1000.c1044
-rw-r--r--nuttx/drivers/net/e1000.h123
-rw-r--r--nuttx/drivers/net/vnet.c3
-rw-r--r--nuttx/lib/net/Make.defs2
-rw-r--r--nuttx/lib/net/lib_inetaddr.c74
15 files changed, 1395 insertions, 23 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index a17488542..495268cb7 100755
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -49,3 +49,7 @@
on initial check-in.
6.4 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
+
+ * nshlib/nsh_netcmds.c: If a network device name and IP address are provided
+ with the ifconfig command, then this command will now set the network address.
+
diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c
index 1bd1e93e4..6e210c020 100644
--- a/apps/nshlib/nsh_netcmds.c
+++ b/apps/nshlib/nsh_netcmds.c
@@ -466,8 +466,48 @@ int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
#ifndef CONFIG_NSH_DISABLE_IFCONFIG
int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- netdev_foreach(ifconfig_callback, vtbl);
- uip_statistics(vtbl);
+ struct in_addr addr;
+ in_addr_t ip;
+
+ /* With one or no arguments, ifconfig simply shows the status of ethernet
+ * device:
+ *
+ * ifconfig
+ * ifconfig [nic_name]
+ */
+
+ if (argc <= 2)
+ {
+ netdev_foreach(ifconfig_callback, vtbl);
+ uip_statistics(vtbl);
+ return OK;
+ }
+
+ /* If both the network interface name and an IP address are supplied as
+ * arguments, then ifconfig will set the address of the ethernet device:
+ *
+ * ifconfig nic_name ip_address
+ */
+
+ /* Set host ip address */
+
+ ip = addr.s_addr = inet_addr(argv[2]);
+ uip_sethostaddr(argv[1], &addr);
+
+ /* Set gateway */
+
+ ip = NTOHL(ip);
+ ip &= ~0x000000ff;
+ ip |= 0x00000001;
+
+ addr.s_addr = HTONL(ip);
+ uip_setdraddr(argv[1], &addr);
+
+ /* Set netmask */
+
+ addr.s_addr = inet_addr("255.255.255.0");
+ uip_setnetmask(argv[1], &addr);
+
return OK;
}
#endif
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index ef861b2de..f6a778a03 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -191,7 +191,7 @@ static const struct cmdmap_s g_cmdmap[] =
#ifdef CONFIG_NET
# ifndef CONFIG_NSH_DISABLE_IFCONFIG
- { "ifconfig", cmd_ifconfig, 1, 1, NULL },
+ { "ifconfig", cmd_ifconfig, 1, 3, "[nic_name [ip]]" },
# endif
#endif
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 998a0acfa..7b700a0d2 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -1764,3 +1764,9 @@
* lib/drivers/cc1101: Add initial, functional CC1101 wireless driver
(contributed by Uros Platise)
+ * arch/mips and configs/pcblogic-pic32mx: The MicroChip PIC32MX port is now
+ code complete and ready to begin testing.
+ * drivers/net/e1000.c/h: A PCI-based E1000 ethernet driver submitted
+ by Yu Qiang.
+ * lib/net/lib_inetaddr.c: An implementatino of the inet_addr() function
+ submitted y Yu Qiang. \ No newline at end of file
diff --git a/nuttx/Documentation/NuttShell.html b/nuttx/Documentation/NuttShell.html
index d1dd3d922..80c653739 100644
--- a/nuttx/Documentation/NuttShell.html
+++ b/nuttx/Documentation/NuttShell.html
@@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttShell (NSH)</i></font></big></h1>
- <p>Last Updated: March 18, 2011</p>
+ <p>Last Updated: May 21, 2011</p>
</td>
</tr>
</table>
@@ -603,7 +603,7 @@ mount -t vfat /dev/ram1 /tmp
The behavior of this script depends upon three things:
<ul>
<li>The configuration settings then installed configuration.
- <li>The <code>genromfs<code> tool (available from <a href="http://romfs.sourceforge.net">http://romfs.sourceforge.net</a>).
+ <li>The <code>genromfs</code> tool (available from <a href="http://romfs.sourceforge.net">http://romfs.sourceforge.net</a>).
<li>The file <code>apps/nshlib/rcS.template</code>
(OR, if <code>CONFIG_NSH_ARCHROMFS</code> is defined <code>include/arch/board/rcs.template</code>.
</ul>
@@ -620,7 +620,7 @@ mount -t vfat /dev/ram1 /tmp
<p>
<b>NOTE</b>:
<code>apps/nshlib/rcS.template</code> generates the standard, default <code>nsh_romfsimg.h</code> file.
- If <code>CONFIG_NSH_ARCHROMFS<code> is defined in the NuttX configuration file, then a custom, board-specific <code>nsh_romfsimg.h</code> file residing in <code>configs/&lt;board&gt;/include</code> will be used.
+ If <code>CONFIG_NSH_ARCHROMFS</code> is defined in the NuttX configuration file, then a custom, board-specific <code>nsh_romfsimg.h</code> file residing in <code>configs/&lt;board&gt;/include</code> will be used.
NOTE when the OS is configured, <code>include/arch/board</code> will be linked to <code>configs/&lt;board&gt;/include</code>.
</p>
<p>
@@ -985,21 +985,46 @@ help
<p><b>Command Syntax:</b></p>
<ul><pre>
-ifconfig
+ifconfig [nic_name [ip_address]]
</pre></ul>
<p>
<b>Synopsis</b>.
- Show the current configuration of the network, for example:
+ Two forms of the <code>ifconfig</code>command are supported:
</p>
-<ul><pre>
+<ol>
+ <li>
+ <p>
+ With one or no arguments, <code>ifconfig</code> will shows the
+ current configuration of the network and, perhaps, the status of ethernet
+ device:
+ </p>
+ <ul><pre>
+ifconfig
+ifconfig [nic_name]
+</pre></ul>
+ <p>
+ As an example:
+ </p>
+ <ul><pre>
nsh&gt; ifconfig
eth0 HWaddr 00:18:11:80:10:06
IPaddr:10.0.0.2 DRaddr:10.0.0.1 Mask:255.255.255.0
</pre></ul>
-<p>
- if uIP statistics are enabled (<code>CONFIG_NET_STATISTICS</code>), then
- this command will also show the detailed state of uIP.
-</p>
+ <p>
+ If uIP statistics are enabled (<code>CONFIG_NET_STATISTICS</code>), then
+ this command will also show the detailed state of uIP.
+ </p>
+ </li>
+ <li>
+ <p>
+ If both the network interface name and an IP address are supplied as arguments,
+ then <code>ifconfig</code> will set the address of the ethernet device:
+ </p>
+ <ul><pre>
+ifconfig nic_name ip_address
+</pre><ul>
+ </li>
+</ol>
<table width ="100%">
<tr bgcolor="#e4e4e4">
@@ -1631,7 +1656,7 @@ sh &lt;script-path&gt;
<p>
<b>Synopsis</b>.
Execute the sequence of NSH commands in the file referred
- to by <code>&lt;script-path&gt;.
+ to by <code>&lt;script-path&gt;</code>.
</p>
<table width ="100%">
@@ -1696,7 +1721,7 @@ unset &lt;name&gt;
<p>
<b>Synopsis</b>.
Remove the value associated with the environment variable
- <code>&lt;name&gt;. Example:
+ <code>&lt;name&gt;</code>. Example:
</p>
<ul><pre>
nsh&gt; echo $foobar
diff --git a/nuttx/arch/rgmp/src/nuttx.c b/nuttx/arch/rgmp/src/nuttx.c
index ba5ffdd9b..b81fc98dd 100644
--- a/nuttx/arch/rgmp/src/nuttx.c
+++ b/nuttx/arch/rgmp/src/nuttx.c
@@ -85,6 +85,7 @@ void up_initialize(void)
extern pidhash_t g_pidhash[];
extern void up_register_bridges(void);
extern void vnet_initialize(void);
+ extern void e1000_mod_init(void);
// intialize the current_task to g_idletcb
current_task = g_pidhash[PIDHASH(0)].tcb;
@@ -92,12 +93,19 @@ void up_initialize(void)
// setup console
up_register_bridges();
- // setup net device
+#ifdef CONFIG_NET_VNET
+ // setup vnet device
vnet_initialize();
+#endif
// setup COM device
up_serialinit();
+#ifdef CONFIG_NET_E1000
+ // setup e1000
+ e1000_mod_init();
+#endif
+
// enable interrupt
sti();
}
diff --git a/nuttx/arch/rgmp/src/rgmp.c b/nuttx/arch/rgmp/src/rgmp.c
index 904729d51..6cc7aceb4 100644
--- a/nuttx/arch/rgmp/src/rgmp.c
+++ b/nuttx/arch/rgmp/src/rgmp.c
@@ -154,4 +154,19 @@ int rtos_sem_down(void *sem)
return sem_wait(sem);
}
+void rtos_stop_running(void)
+{
+ extern void e1000_mod_exit(void);
+
+ cli();
+
+#ifdef CONFIG_NET_E1000
+ e1000_mod_exit();
+#endif
+
+ while(1) {
+ asm volatile("hlt");
+ }
+}
+
diff --git a/nuttx/configs/rgmp/default/defconfig b/nuttx/configs/rgmp/default/defconfig
index 772a1671f..198a0ddcb 100644
--- a/nuttx/configs/rgmp/default/defconfig
+++ b/nuttx/configs/rgmp/default/defconfig
@@ -385,13 +385,28 @@ CONFIG_HEAP_BASE=
CONFIG_HEAP_SIZE=
-#
+##########################################
# RGMP specific configuration
+##########################################
+
+#
+# VNET
#
CONFIG_NET_VNET=y
CONFIG_VNET_NINTERFACES=1
+
+#
+# Serial port
+#
CONFIG_COM1=y
CONFIG_COM2=y
CONFIG_COM3=n
CONFIG_COM4=n
-CONFIG_E1000=n
+
+#
+# E1000
+#
+CONFIG_NET_E1000=n
+CONFIG_E1000_N_TX_DESC=128
+CONFIG_E1000_N_RX_DESC=128
+CONFIG_E1000_BUFF_SIZE=0x800
diff --git a/nuttx/configs/rgmp/nsh/defconfig b/nuttx/configs/rgmp/nsh/defconfig
index d8db04caa..081204024 100644
--- a/nuttx/configs/rgmp/nsh/defconfig
+++ b/nuttx/configs/rgmp/nsh/defconfig
@@ -415,13 +415,28 @@ CONFIG_HEAP_BASE=
CONFIG_HEAP_SIZE=
-#
+##########################################
# RGMP specific configuration
+##########################################
+
+#
+# VNET
#
CONFIG_NET_VNET=y
CONFIG_VNET_NINTERFACES=1
+
+#
+# Serial port
+#
CONFIG_COM1=y
CONFIG_COM2=y
CONFIG_COM3=n
CONFIG_COM4=n
-CONFIG_E1000=n \ No newline at end of file
+
+#
+# E1000
+#
+CONFIG_NET_E1000=n
+CONFIG_E1000_N_TX_DESC=128
+CONFIG_E1000_N_RX_DESC=128
+CONFIG_E1000_BUFF_SIZE=0x800
diff --git a/nuttx/drivers/net/Make.defs b/nuttx/drivers/net/Make.defs
index eba3e5078..ab256cd8a 100644
--- a/nuttx/drivers/net/Make.defs
+++ b/nuttx/drivers/net/Make.defs
@@ -55,6 +55,10 @@ 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
diff --git a/nuttx/drivers/net/e1000.c b/nuttx/drivers/net/e1000.c
new file mode 100644
index 000000000..97b51a745
--- /dev/null
+++ b/nuttx/drivers/net/e1000.c
@@ -0,0 +1,1044 @@
+/****************************************************************************
+ * 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 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 <nuttx/config.h>
+#include <nuttx/kmalloc.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <time.h>
+#include <debug.h>
+#include <wdog.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <net/uip/uip.h>
+#include <net/uip/uip-arp.h>
+#include <net/uip/uip-arch.h>
+
+#include <rgmp/pmap.h>
+#include <rgmp/pci.h>
+#include <rgmp/string.h>
+#include <rgmp/x86.h>
+#include <rgmp/stdio.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 uip_eth_hdr *)e1000->uip_dev.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;
+ unsigned char src_mac[6];
+ unsigned char dst_mac[6];
+ int irq;
+ struct irq_action int_desc;
+ struct tx_ring tx_ring;
+ struct rx_ring rx_ring;
+ struct e1000_dev *next;
+
+ // NuttX 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/NuttX */
+
+ struct uip_driver_s uip_dev; /* Interface understood by uIP */
+};
+
+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_uiptxpoll(struct uip_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, ...);
+
+/* NuttX callback functions */
+
+static int e1000_ifup(struct uip_driver_s *dev);
+static int e1000_ifdown(struct uip_driver_s *dev);
+static int e1000_txavail(struct uip_driver_s *dev);
+#ifdef CONFIG_NET_IGMP
+static int e1000_addmac(struct uip_driver_s *dev, const uint8_t *mac);
+static int e1000_rmmac(struct uip_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 ********************************/
+
+static 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 |= (1<<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(2000);
+ e1000_outl(dev, E1000_CTRL_EXT, 0x001401C0);
+}
+
+static void e1000_turn_on(struct e1000_dev *dev)
+{
+ int tx_control, 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);
+}
+
+static void e1000_turn_off(struct e1000_dev *dev)
+{
+ int tx_control, 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);
+}
+
+static void e1000_init(struct e1000_dev *dev)
+{
+ uint32_t rxd_phys, txd_phys, kmem_phys;
+ uint32_t rx_control, 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(dev->tx_ring.desc);
+ kmem_phys = PADDR(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(dev->rx_ring.desc);
+ kmem_phys = PADDR(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->uip_dev.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->uip_dev.d_buf, e1000->uip_dev.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_uiptxpoll
+ *
+ * Description:
+ * The transmitter is available, check if uIP has any outgoing packets ready
+ * to send. This is a callback from uip_poll(). uip_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 NuttX 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_uiptxpoll(struct uip_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->uip_dev.d_len > 0) {
+ uip_arp_out(&e1000->uip_dev);
+ 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_BUFSIZE || cnt < 14) {
+ cprintf("NIC READ: invalid package size\n");
+ goto next;
+ }
+
+ /* Copy the data data from the hardware to e1000->uip_dev.d_buf. Set
+ * amount of data in e1000->uip_dev.d_len
+ */
+
+ // now we try to copy these data-bytes to the UIP buffer
+ memcpy(e1000->uip_dev.d_buf, cp, cnt);
+ e1000->uip_dev.d_len = cnt;
+
+ /* We only accept IP packets of the configured type and ARP packets */
+
+#ifdef CONFIG_NET_IPv6
+ if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
+#else
+ if (BUF->type == HTONS(UIP_ETHTYPE_IP))
+#endif
+ {
+ uip_arp_ipin(&e1000->uip_dev);
+ uip_input(&e1000->uip_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 (e1000->uip_dev.d_len > 0) {
+ uip_arp_out(&e1000->uip_dev);
+ e1000_transmit(e1000);
+ }
+ }
+ else if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
+ uip_arp_arpin(&e1000->uip_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 (e1000->uip_dev.d_len > 0) {
+ e1000_transmit(e1000);
+ }
+ }
+
+ 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)uip_poll(&e1000->uip_dev, e1000_uiptxpoll);
+}
+
+/****************************************************************************
+ * 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)uip_timer(&e1000->uip_dev, e1000_uiptxpoll, E1000_POLLHSEC);
+
+ /* Setup the watchdog poll timer again */
+
+ (void)wd_start(e1000->txpoll, E1000_WDDELAY, e1000_polltimer, 1, arg);
+}
+
+/****************************************************************************
+ * Function: e1000_ifup
+ *
+ * Description:
+ * NuttX Callback: Bring up the Ethernet interface when an IP address is
+ * provided
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int e1000_ifup(struct uip_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:
+ * NuttX Callback: Stop the interface.
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int e1000_ifdown(struct uip_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 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 NuttX driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Called in normal user mode
+ *
+ ****************************************************************************/
+
+static int e1000_txavail(struct uip_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)uip_poll(&e1000->uip_dev, e1000_uiptxpoll);
+ }
+
+ irqrestore(flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Function: e1000_addmac
+ *
+ * Description:
+ * NuttX Callback: Add the specified MAC address to the hardware multicast
+ * address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be added
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IGMP
+static int e1000_addmac(struct uip_driver_s *dev, const uint8_t *mac)
+{
+ struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
+
+ /* Add the MAC address to the hardware multicast routing table */
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: e1000_rmmac
+ *
+ * Description:
+ * NuttX Callback: Remove the specified MAC address from the hardware multicast
+ * address filtering
+ *
+ * Parameters:
+ * dev - Reference to the NuttX driver state structure
+ * mac - The MAC address to be removed
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IGMP
+static int e1000_rmmac(struct uip_driver_s *dev, const uint8_t *mac)
+{
+ struct e1000_dev *e1000 = (struct e1000_dev *)dev->d_private;
+
+ /* Add the MAC address to the hardware multicast routing table */
+
+ return OK;
+}
+#endif
+
+irqreturn_t e1000_interrupt_handler(struct Trapframe *tf, 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))
+ uip_poll(&e1000->uip_dev, e1000_uiptxpoll);
+
+
+ // 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 pci_cmd, size;
+ int err, irq;
+ void *kmem, *omem;
+ struct e1000_dev *dev;
+
+ // alloc e1000_dev memory
+ dev = kzalloc(sizeof(struct e1000_dev));
+ if (dev == NULL)
+ return -1;
+
+ // enable device
+ err = pci_enable_device(addr, PCI_RESOURCE_MEM);
+ if (err)
+ 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;
+
+ // make sure the controller's Bus Master capability is enabled
+ pci_cmd = pci_config_readl(addr, PCI_COMMAND);
+ pci_cmd |= (1<<2);
+ pci_config_writel(addr, PCI_COMMAND, pci_cmd);
+
+ // MAC address
+ memset(dev->dst_mac, 0xFF, 6);
+ memcpy(dev->src_mac, (void *)(dev->io_mem_base+E1000_RA), 6);
+
+ // get e1000 IRQ
+ irq = pci_read_irq(addr);
+ dev->irq = irq;
+ dev->int_desc.handler = e1000_interrupt_handler;
+ dev->int_desc.dev_id = dev;
+ err = rgmp_request_irq(irq, &dev->int_desc, IDC_SHARE);
+ if (err)
+ 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.
+ 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->uip_dev.d_ifup = e1000_ifup; /* I/F up (new IP address) callback */
+ dev->uip_dev.d_ifdown = e1000_ifdown; /* I/F down callback */
+ dev->uip_dev.d_txavail = e1000_txavail; /* New TX data callback */
+#ifdef CONFIG_NET_IGMP
+ dev->uip_dev.d_addmac = e1000_addmac; /* Add multicast MAC address */
+ dev->uip_dev.d_rmmac = e1000_rmmac; /* Remove multicast MAC address */
+#endif
+ dev->uip_dev.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->uip_dev.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->uip_dev);
+ 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:
+ rgmp_free_irq(irq, &dev->int_desc);
+ err0:
+ rgmp_memunmap(mmio_base, mmio_size);
+ error:
+ kfree(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);
+ return 0;
+}
+
+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->uip_dev);
+ 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);
+ rgmp_free_irq(dev->irq, &dev->int_desc);
+ rgmp_memunmap((uintptr_t)dev->io_mem_base, dev->mem_size);
+ kfree(dev);
+ }
+
+ e1000_list.next = NULL;
+}
diff --git a/nuttx/drivers/net/e1000.h b/nuttx/drivers/net/e1000.h
new file mode 100644
index 000000000..04f986fef
--- /dev/null
+++ b/nuttx/drivers/net/e1000.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+ * 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 <rgmp/types.h>
+#include <rgmp/trap.h>
+#include <rgmp/x86.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
diff --git a/nuttx/drivers/net/vnet.c b/nuttx/drivers/net/vnet.c
index 6475334b5..c12976a0f 100644
--- a/nuttx/drivers/net/vnet.c
+++ b/nuttx/drivers/net/vnet.c
@@ -123,7 +123,6 @@ static int vnet_uiptxpoll(struct uip_driver_s *dev);
/* Interrupt handling */
-static void vnet_receive(FAR struct vnet_driver_s *vnet);
static void vnet_txdone(FAR struct vnet_driver_s *vnet);
/* Watchdog timer expirations */
@@ -250,7 +249,7 @@ static int vnet_uiptxpoll(struct uip_driver_s *dev)
}
/****************************************************************************
- * Function: vnet_receive
+ * Function: rtos_vnet_recv
*
* Description:
* An interrupt was received indicating the availability of a new RX packet
diff --git a/nuttx/lib/net/Make.defs b/nuttx/lib/net/Make.defs
index 5cacb1079..ca7ab9587 100644
--- a/nuttx/lib/net/Make.defs
+++ b/nuttx/lib/net/Make.defs
@@ -33,4 +33,4 @@
#
############################################################################
-NET_SRCS = lib_htons.c lib_htonl.c lib_inetntoa.c lib_etherntoa.c
+NET_SRCS = lib_htons.c lib_htonl.c lib_inetntoa.c lib_etherntoa.c lib_inetaddr.c
diff --git a/nuttx/lib/net/lib_inetaddr.c b/nuttx/lib/net/lib_inetaddr.c
new file mode 100644
index 000000000..48b01d682
--- /dev/null
+++ b/nuttx/lib/net/lib_inetaddr.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * lib/net/lib_inetaddr.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 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 <stdio.h>
+#include <arpa/inet.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * name inet_addr
+ *
+ * Description:
+ * The inet_addr() function converts the string pointed to by cp, in the
+ * standard IPv4 dotted decimal notation, to an integer value suitable for
+ * use as an Internet address.
+
+ ****************************************************************************/
+
+in_addr_t inet_addr(FAR const char *cp)
+{
+ unsigned int a, b, c, d;
+ uint32_t result;
+
+ sscanf(cp, "%u.%u.%u.%u", &a, &b, &c, &d);
+ result = a << 8;
+ result |= b;
+ result <<= 8;
+ result |= c;
+ result <<= 8;
+ result |= d;
+ return HTONL(result);
+}