devif: e1000 backend initial version
authorAdam Turowski <adam.turowski@inf.ethz.ch>
Tue, 6 Jun 2017 14:12:11 +0000 (16:12 +0200)
committerAdam Turowski <adam.turowski@inf.ethz.ch>
Wed, 7 Jun 2017 08:39:16 +0000 (10:39 +0200)
Signed-off-by: Adam Turowski <adam.turowski@inf.ethz.ch>

15 files changed:
devices/e1000.dev
include/devif/backends/net/e1000_devif.h [new file with mode: 0644]
lib/devif/backends/net/e1000/Hakefile [new file with mode: 0644]
lib/devif/backends/net/e1000/e1000.c [new file with mode: 0644]
lib/devif/backends/net/e1000/e1000.h [new file with mode: 0644]
lib/devif/queue_interface_internal.h
lib/lwip-2.0.2/src/core/inet_chksum.c
lib/lwip-2.0.2/src/core/udp.c
lib/net/Hakefile
lib/net/net.c
lib/net/net_filter.c
lib/net/netif.c
lib/net/networking_internal.h
lib/net/pbuf.c
usr/skb/programs/device_db.pl

index 026359d..4a1fa21 100644 (file)
  * e1000.dev
  *
  * DESCRIPTION: Intel e1000 family Gigabit Ethernet NICs
- * 
+ *
  * Numbers in comments refer to the Intel PCIe GbE Controllers Open
  * Source Software Development Manual, 631xESB / 632xESB, 82563EB /
- * 82564EB, 82571EB / 82572EI & 82573E / 82573V / 82573L. 
+ * 82564EB, 82571EB / 82572EI & 82573E / 82573V / 82573L.
  * 316080-003, Revison 1.2, September 2007
  */
 
@@ -100,7 +100,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     lan_b_mask  = 0x0100 "LAN B mask";
   };
 
-  // 13.3.2 
+  // 13.3.2
   register status ro addr(base, 0x0008) "Device status" {
     fd         1 "Link full duplex configuration";
     lu         1 "Link up";
@@ -109,12 +109,12 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     tbimode    1 "TBI mode";
     speed      2 type(linkspeed) "Link speed setting";
     asdv       2 type(linkspeed) "Auto speed detection value";
-    phyra      1 "PHY reset asserted"; 
+    phyra      1 "PHY reset asserted";
     pci66      1 "PCI Bus speed indication";
     bus64      1 "PCI Bus Width indication";
     pcix_mode   1 "PCI-X Mode indication";
     pcixspd     2 "PCI-X Bus Speed Indication";
-    _          3 mbz;   
+    _          3 mbz;
     gio_mes     1 "GIO master enable status";
     dev_rst_set 1 "Device reset set";
     pf_rst_done 1 "Software Rest or device reset completed";
@@ -129,7 +129,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     _           1 mbz;
     speed       2 type(linkspeed) "Link speed setting";
     asdv        2 type(linkspeed) "Auto speed detection value";
-    phyra       1 "PHY reset asserted"; 
+    phyra       1 "PHY reset asserted";
     _           3  mbz;
     nvf         4 "Num VFs in the IOV capability s";
     vfe         1 "VF enable (VFE) bit in the IOV capability";
@@ -193,7 +193,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     ee_clr_err    1 "Clear EEPROM Access Error";
     ee_det        1 "EEPROM Detected";
     _            12 mbz;
-  };  
+  };
 
   register eec_82574 rw also addr(base, 0x0010) "EEPROM/Flash control for 82574" {
     ee_sk         1 "Clock input to EEPROM";
@@ -214,12 +214,12 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     sec1val       1 "Sec 1 valid";
     nvmtype       1 "NVM Type";
     _             8 mbz;
-  };  
+  };
 
   // 13.3.4
   // NM93C46 compatible EEPROMs
   register eerd_nm rw addr(base, 0x0014) "EEPROM read" {
-    start       1 "Start read";  
+    start       1 "Start read";
     _           3 mbz;
     done        1 ro "Read done";
     _           3 mbz;
@@ -231,7 +231,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     start       1 "Start read";
     done        1 ro "Read done";
     addr        14 "Read address";
-    data        16 "Read data";   
+    data        16 "Read data";
   };
 
 
@@ -292,23 +292,23 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
 
   // 13.3.7
   constants phyop "PHY register opcode" {
-    mdi_write  = 0b01 "MDI Write";
-    mdi_read   = 0b10 "MDI Read";
+    mdi_write_ = 0b01 "MDI Write";
+    mdi_read_  = 0b10 "MDI Read";
   };
   register mdic rw addr(base, 0x0020) "MDI control" {
-    data       16 "Data";
-    regadd     5  "PHY register address";
-    phyadd     5  "PHY address";
-    op         2 type(phyop) "Opcode";
-    r          1 "Ready bit";
-    i          1 "Interript enable";
-    e          1 "Error";
-    _          1 mbz;
+    data        16  "Data";
+    regadd      5   "PHY register address";
+    phyadd      5   "PHY address";
+    op          2   type(phyop) "Opcode";
+    r           1   "Ready bit";
+    i           1   "Interrupt enable";
+    e           1   "Error";
+    _           1   mbz;
   };
   
   // 13.3.8
   // There are a lot of PHY registers, all accessed through the MDIC.
-  // We don't yet list them here. 
+  // We don't yet list them here.
 
   // 13.3.10
   register serdesctl rw addr(base, 0x0024) "SERDES ANA" {
@@ -358,7 +358,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     crred      13 "Code RAM redundancy fuses";
     enad       1  "Enable Data RAM redundancy fuses";
     enac       1  "Enable Code RAM redundancy fuses";
-    _          2; 
+    _          2;
   };
   
   // 13.3.18
@@ -447,9 +447,9 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     led3_blink_mode 1 type(blmode) "Global blink mode";
     led3_ivrt  1 "LED3 invert";
     led3_blink 1 "LED3 blink";
-  };    
+  };
 
-  // 13.3.22 
+  // 13.3.22
   register extcnf_ctrl rw addr(base, 0x0f00) "Extended config control" {
     _          1 mbz;
     phy_we     1 "PHY write enable";
@@ -522,16 +522,35 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     srpd       1 "Small receive packet detected";
     ack                1 "Receive ack frame detected";
     _          2;
-    rx_desc_fifo_par0 1 "Rx descriptor FIFO parity error 0"; 
-    tx_desc_fifo_par0 1 "Tx descriptor FIFO parity error 0"; 
+    rx_desc_fifo_par0 1 "Rx descriptor FIFO parity error 0";
+    tx_desc_fifo_par0 1 "Tx descriptor FIFO parity error 0";
     pcie_master_par 1 "PCIe master data FIFO parity error";
     pbpar      1 "Packet buffer parity error";
-    rx_desc_fifo_par1 1 "Rx descriptor FIFO parity error 1"; 
-    tx_desc_fifo_par1 1 "Tx descriptor FIFO parity error 1"; 
+    rx_desc_fifo_par1 1 "Rx descriptor FIFO parity error 1";
+    tx_desc_fifo_par1 1 "Tx descriptor FIFO parity error 1";
     _          5;
     int_asserted 1 "Interrupt asserted";
   };
 
+  regtype eintreg "Extended Interrupt register format" {
+    rxtxq0      1 "Receive/Transmit Queue 0 Interrupt";
+    rxtxq1      1 "Receive/Transmit Queue 1 Interrupt";
+    rxtxq2      1 "Receive/Transmit Queue 2 Interrupt";
+    rxtxq3      1 "Receive/Transmit Queue 3 Interrupt";
+    rxtxq4      1 "Receive/Transmit Queue 4 Interrupt";
+    rxtxq5      1 "Receive/Transmit Queue 5 Interrupt";
+    rxtxq6      1 "Receive/Transmit Queue 6 Interrupt";
+    rxtxq7      1 "Receive/Transmit Queue 7 Interrupt";
+    _           22 mbz;
+    tcp_timer   1 "TCP Timer expired";
+    other_cause 1 "Other cause";
+  };
+
+  regtype msixintreg "MSI-X Interrupt register format "{
+    msix        25 "MSI-X vectors";
+    _           7 mbz;
+  };
+
   // 13.3.27
   register icr ro addr(base, 0x00c0) "Interrupt cause read" type(intreg);
 
@@ -544,7 +563,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   // 13.3.29
   register ics wo addr(base, 0x00c8) "Interrupt cause write" type(intreg);
   
-  // 13.3.30 
+  // 13.3.30
   register ims rw addr(base, 0x00d0) "Interrupt mask set/read" type(intreg);
   
   // 13.3.31
@@ -566,17 +585,25 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     counter  16 "Down counter";
   };
   
-  register eimc wo addr(base, 0x1528) "Extended Interrupt Mask Clear" {
-    RxTxQ 8 "Clear Mask bit for the corresponding EICR RxTXQ interrupt.";
-    _     22 mbz;
-    tcp_timer   1 "EICR TCP timer interrupt.";
-    other_cause 1 "EICR other cause interrupt.";
+  register gpie rw addr(base, 0x1514) "General Purpose Interrupt Enable" {
+    nsicr           1 "Non Selective Interrupt clear on read";
+    _               3 mbz;
+    multiple_msix   1 "Multiple MSIX";
+    _               2 mbz;
+    ll_interval     5 "Low Latency Credits Increment Rate";
+    _               18 mbz;
+    EIAME           1 "EIAME";
+    pba_support     1 "PBA support";
   };
   
-  register eimc_msix wo also addr(base, 0x1528) "Extended Interrupt Mask Clear" {
-    msix 25 "Clear Mask bit for the corresponding EICR RxTXQ interrupt.";
-    _ 7 mbz;
-  };
+  register eics wo addr(base, 0x1520) "Extended Interrupt Cause Set" type(eintreg);
+  register eims rw addr(base, 0x1524) "Extended Interrupt Mask Set/Read" type(eintreg);
+  register eimc wo addr(base, 0x1528) "Extended Interrupt Mask Clear" type(eintreg);
+  register eiac rw addr(base, 0x152c) "Extended Interrupt Auto Clear" type(eintreg);
+  register eiam rw addr(base, 0x1530) "Extended Interrupt Auto Mask Enable" type(eintreg);
+  register eicr rw addr(base, 0x1580) "Extended Interrupt Cause" type(eintreg);
+
+  register eimc_msix wo also addr(base, 0x1528) "Extended Interrupt Mask Clear" type(msixintreg);
   
   regarray eitr_I350 also addr(base, 0x1680)[24;0x4] "Extended Interrupt Throttle" {
     _         2 mbz;
@@ -587,6 +614,32 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     cnt_ingr  1 "When set the hardware does not override the counters fields";
   };
 
+  regarray ivar rw addr(base, 0x1700)[4;0x4] "Interrupt Vector Allocation" {
+    int_alloc0      5   "MSI-X vector";
+    _               2   mbz;
+    int_alloc_val0  1   "Valid bit";
+    int_alloc1      5   "MSI-X vector";
+    _               2   mbz;
+    int_alloc_val1  1   "Valid bit";
+    int_alloc2      5   "MSI-X vector";
+    _               2   mbz;
+    int_alloc_val2  1   "Valid bit";
+    int_alloc3      5   "MSI-X vector";
+    _               2   mbz;
+    int_alloc_val3  1   "Valid bit";
+  };
+
+  register ivar_misc rw addr(base, 0x1740) "Interrupt Vector Allocation - MISC" {
+    int_alloc16     5   "TCP Timer";
+    _               2   mbz;
+    int_alloc_val16 1   "Valid bit";
+    int_alloc17     5   "Other cause";
+    _               2   mbz;
+    int_alloc_val17 1   "Valid bit";
+    _               16  mbz;
+  };
+
+
   /************************************
    * Receive registers
    ***********************************/
@@ -636,7 +689,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     secrc      1 "Strip Ethernet CRC from packet";
     flxbuf     4 "Flexible buffer size (in KB)";
     _          1 mbz;
-  };    
+  };
   
   // 13.3.34
   register ert rw addr(base, 0x2008) "Early receive threshold" {
@@ -674,15 +727,15 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   };
   
   // 13.3.38/46/39/47
-  regarray rdbal rw addr(base, 0x2800)[2;0x100] 
+  regarray rdbal rw addr(base, 0x2800)[2;0x100]
     "Rx descr. base addr low" type(uint32);
-  regarray rdbah rw addr(base, 0x2804)[2;0x100] 
+  regarray rdbah rw addr(base, 0x2804)[2;0x100]
     "Rx descr. base addr high" type(uint32);
     
-  regarray rdbal_I350 rw addr(base, 0xC000)[8;0x40] 
+  regarray rdbal_I350 rw addr(base, 0xC000)[8;0x40]
     "Rx descr. base addr low" type(uint32);
-  regarray rdbah_I350 rw addr(base, 0xC004)[8;0x40] 
-    "Rx descr. base addr high" type(uint32);    
+  regarray rdbah_I350 rw addr(base, 0xC004)[8;0x40]
+    "Rx descr. base addr high" type(uint32);
 
   // 13.3.40/48 and 13.3.62/71
   // Note that the description of the transmit length (13.3.62/71) refers to
@@ -693,10 +746,10 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     len                13 "Num. descriptors (x8)";
     _          12 mbz;
   };
-  regarray rdlen rw addr(base, 0x2808)[2;0x100] 
+  regarray rdlen rw addr(base, 0x2808)[2;0x100]
     "Rx descriptor length" type(dqlen);
 
-  regarray rdlen_I350 rw addr(base, 0xC008)[8;0x40] 
+  regarray rdlen_I350 rw addr(base, 0xC008)[8;0x40]
     "Rx descriptor length" type(dqlen);
 
   // 13.3.41/49/42/50
@@ -770,7 +823,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     _          20 mbz;
   };
   
-  // 13.3.53 
+  // 13.3.53
   register raid rw addr(base, 0x2c08) "Rx ACK interrupt delay" {
     idv                16 "Interrupt delay value (x 1.024us)";
     _          16 mbz;
@@ -863,15 +916,15 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   //
 
   // 13.3.60/61/69/70
-  regarray tdbal rw addr(base, 0x3800)[2;0x100] "Tx descr. base addr. low" 
+  regarray tdbal rw addr(base, 0x3800)[2;0x100] "Tx descr. base addr. low"
     type(uint32);
-  regarray tdbah rw addr(base, 0x3804)[2;0x100] "Tx descr. base addr. hi" 
+  regarray tdbah rw addr(base, 0x3804)[2;0x100] "Tx descr. base addr. hi"
     type(uint32);
     
-  regarray tdbal_I350 rw addr(base, 0xE000)[8;0x40] "Tx descr. base addr. low" 
+  regarray tdbal_I350 rw addr(base, 0xE000)[8;0x40] "Tx descr. base addr. low"
+    type(uint32);
+  regarray tdbah_I350 rw addr(base, 0xE004)[8;0x40] "Tx descr. base addr. hi"
     type(uint32);
-  regarray tdbah_I350 rw addr(base, 0xE004)[8;0x40] "Tx descr. base addr. hi" 
-    type(uint32);    
   
   // 13.3.62/71
   regarray tdlen rw addr(base, 0x3808)[2;0x100] "Tx descr. length" type(dqlen);
@@ -895,7 +948,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     HeadWB_Low 30 "Bits 31:2 of the head write-back memory location";
   };
   
-  regarray tdwbah rw addr(base, 0xE03C)[8; 0x40] "Tx Descriptor Completion Write" 
+  regarray tdwbah rw addr(base, 0xE03C)[8; 0x40] "Tx Descriptor Completion Write"
     type(uint32);
 
   // 13.3.66/74
@@ -979,7 +1032,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   };
 
   // 13.4.4
-  regarray vfta rw addr(base, 0x5600)[128] 
+  regarray vfta rw addr(base, 0x5600)[128]
     "VLAN filter table array" type(uint32);
 
   // 13.4.5
@@ -1002,7 +1055,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   // 13.4.6
   register rssim rw addr(base, 0x5864) "RSS interrupt mask" type(uint32);
   
-  // 13.4.7 
+  // 13.4.7
   register rssir rw addr(base, 0x5868) "RSS interrupt request" type(uint32);
   
   // 13.4.8
@@ -1024,7 +1077,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     _          28;
   };
 
-  // 13.5.2 
+  // 13.5.2
   regtype wakeup "Wakeup register" {
     lnkc       1 "Link status change";
     mag                1 "Magic packet";
@@ -1059,7 +1112,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   };
 
   // 13.5.5
-  regarray ip4at rw addr(base, 0x5840)[4;8] 
+  regarray ip4at rw addr(base, 0x5840)[4;8]
     "IPv4 address table" type(uint32);
 
   // 13.5.6
@@ -1074,7 +1127,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   // 13.5.8
   regarray wupm rw addr(base, 0x5a00)[32] "Wakeup packet memory" type(uint32);
   
-  // 13.5.9 
+  // 13.5.9
   regarray fflt rw addr(base, 0x5f00)[4;8] "Flexible filter length table" {
     len                11 "Length";
     _          21 mbz;
@@ -1160,7 +1213,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     dis_tmout          1 "Disable PCIe timeout mechanism";
   };
 
-  // 13.7.2 
+  // 13.7.2
   register gscl1 rw addr(base, 0x5b10) "PCIe statistics control 1" {
     count_en0  1 "Enable PCIe stats counter 0";
     count_en1  1 "Enable PCIe stats counter 1";
@@ -1448,7 +1501,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   register icrxoc rc addr(base, 0x4124)
     "Interrupt cause receive overrun count" type(uint32);
 
-  regarray statsregs rc also addr(base, 0x4000)[74] 
+  regarray statsregs rc also addr(base, 0x4000)[74]
     "All stats registers" type(uint32);
 
 
@@ -1491,7 +1544,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
       _                63;
   };
   datatype rdesc_write lsbfirst(64) "Extended rx descriptor (write format)" {
-      // MRQ 
+      // MRQ
       rss      4 type(rsstype) "RSS type";
       _                4;
       queue    5 "Receive queue";
@@ -1515,7 +1568,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
       _                4;
       ack      1  "ACK packet identification";
       _                4;
-      // Extended errors 
+      // Extended errors
       _                4;
       ce       1  "CRC or alignment error";
       se       1  "Symbol error";
diff --git a/include/devif/backends/net/e1000_devif.h b/include/devif/backends/net/e1000_devif.h
new file mode 100644 (file)
index 0000000..099effe
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef E1000_DEVIF_H
+#define E1000_DEVIF_H
+
+struct e1000_queue;
+
+// interrupt_mode: 0 - none, 1 - normal, 2 - interrupt test
+errval_t e1000_queue_create(struct e1000_queue** q, uint32_t vendor, uint32_t deviceid,
+    uint32_t bus, uint32_t device, uint32_t function, unsigned interrupt_mode,
+    void (*isr)(void *));
+errval_t e1000_queue_destroy(struct e1000_queue* q);
+
+#endif
diff --git a/lib/devif/backends/net/e1000/Hakefile b/lib/devif/backends/net/e1000/Hakefile
new file mode 100644 (file)
index 0000000..e0147de
--- /dev/null
@@ -0,0 +1,21 @@
+--------------------------------------------------------------------------
+-- Copyright (c) 2017, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/backend/net/e1000/
+--
+-- Intel e1000 backend implementation
+--
+--------------------------------------------------------------------------
+
+[
+    build library { target = "devif_backend_e1000",
+                    cFiles = ["e1000.c"],
+                    mackerelDevices = ["e1000"],
+                    addLibraries = libDeps ["pci"]
+                }
+]
diff --git a/lib/devif/backends/net/e1000/e1000.c b/lib/devif/backends/net/e1000/e1000.c
new file mode 100644 (file)
index 0000000..5eb551c
--- /dev/null
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2017, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/deferred.h>
+#include <devif/backends/net/e1000_devif.h>
+#include "../../../queue_interface_internal.h"
+#include "e1000.h"
+#include <net_interfaces/flags.h>
+
+#define DRIVER_RECEIVE_BUFFERS      (16384)
+#define DRIVER_TRANSMIT_BUFFERS     (16384)
+
+static errval_t e1000_register(struct devq* q, struct capref cap,
+                                  regionid_t rid)
+{
+    e1000_queue_t *device = (e1000_queue_t *)q;
+    struct frame_identity id;
+    errval_t err;
+    
+    err = invoke_frame_identify(cap, &id);
+    assert(err_is_ok(err));
+    assert(!device->region_id);
+    device->region_id = rid;
+    device->region_base = id.base;
+    device->region_size = id.bytes;
+    debug_printf("%s:%s:  rid:%d:%lx:%lx\n", device->name, __func__, rid, device->region_base, device->region_size);
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_deregister(struct devq* q, regionid_t rid)
+{
+    e1000_queue_t *device = (e1000_queue_t *)q;
+    debug_printf("%s:%s:\n", device->name, __func__);
+    return SYS_ERR_OK;
+}
+
+
+static errval_t e1000_control(struct devq* q, uint64_t cmd, uint64_t value,
+                                 uint64_t *result)
+{
+    e1000_queue_t *device = (e1000_queue_t *)q;
+    debug_printf("%s:%s:\n", device->name, __func__);
+    *result = device->mac_address;
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_enqueue_rx(e1000_queue_t *device, regionid_t rid,
+                               genoffset_t offset, genoffset_t length,
+                               genoffset_t valid_data, genoffset_t valid_length,
+                               uint64_t flags)
+{
+    union rx_desc desc;
+
+    desc.raw[0] = desc.raw[1] = 0;
+    desc.rx_read_format.buffer_address = device->region_base + offset;
+
+    device->receive_ring[device->receive_tail] = desc;
+    device->receive_tail = (device->receive_tail + 1) % DRIVER_RECEIVE_BUFFERS;
+
+    e1000_dqval_t dqval = 0;
+    dqval = e1000_dqval_val_insert(dqval, device->receive_tail);
+    e1000_rdt_wr(&device->hw_device, 0, dqval);
+
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_dequeue_rx(e1000_queue_t *device, regionid_t* rid, genoffset_t* offset,
+                                 genoffset_t* length, genoffset_t* valid_data,
+                                 genoffset_t* valid_length, uint64_t* flags)
+{
+    if (device->receive_head == device->receive_tail) {
+        return DEVQ_ERR_QUEUE_EMPTY;
+    }
+
+    volatile union rx_desc *rxd;
+    rxd = &device->receive_ring[device->receive_head];
+    if (!rxd->rx_read_format.info.status.dd ||
+            !rxd->rx_read_format.info.status.eop) {
+        return DEVQ_ERR_QUEUE_EMPTY;
+    }
+    
+    device->receive_head = (device->receive_head + 1) % DRIVER_TRANSMIT_BUFFERS;
+    
+    *rid = device->region_id;
+    *offset = rxd->rx_read_format.buffer_address - device->region_base;
+    *length = 2048;
+    *valid_data = 0;
+    *valid_length = rxd->rx_read_format.info.length;
+    *flags = NETIF_RXFLAG;
+    
+    // debug_print_to_log("DEQRX %d", *valid_length);
+    // debug_printf("%s:%s: %lx:%ld:%ld:%ld:%lx\n", device->name, __func__, *offset, *length, *valid_data, *valid_length, *flags);
+
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_enqueue_tx(e1000_queue_t *device, regionid_t rid,
+                               genoffset_t offset, genoffset_t length,
+                               genoffset_t valid_data, genoffset_t valid_length,
+                               uint64_t flags)
+{
+    struct tx_desc tdesc;
+
+    // debug_printf("%s:%s: %lx:%ld:%ld:%ld:%lx\n", device->name, __func__, offset, length, valid_data, valid_length, flags);
+    // debug_print_to_log("ENQTX %d", valid_length);
+
+    if (device->advanced_descriptors == 3) {
+        tdesc.buffer_address = device->region_base + offset + valid_data;
+        tdesc.ctrl.raw = 0;
+        tdesc.ctrl.advanced_data.dtalen = valid_length;
+        tdesc.ctrl.advanced_data.dtyp.d.dtyp = 3; // advanced data descriptor
+        tdesc.ctrl.advanced_data.dcmd.d.eop = 1;
+        tdesc.ctrl.advanced_data.dcmd.d.ifcs = 1;
+        tdesc.ctrl.advanced_data.dcmd.d.rs = 1;
+        tdesc.ctrl.advanced_data.dcmd.d.dext = 1;
+        tdesc.ctrl.advanced_data.popts_paylen.d.paylen = valid_length;
+    } else if (device->advanced_descriptors == 1) {
+        tdesc.buffer_address = device->region_base + offset + valid_data;
+        tdesc.ctrl.raw = 0;
+        tdesc.ctrl.extended_data.data_len = valid_length;
+        tdesc.ctrl.extended_data.dtyp = 1; // extended data descriptor
+        tdesc.ctrl.extended_data.dcmd.d.rs = 1;
+        tdesc.ctrl.extended_data.dcmd.d.ifcs = 1;
+        tdesc.ctrl.extended_data.dcmd.d.eop = 1;
+        tdesc.ctrl.extended_data.dcmd.d.dext = 1;
+    } else {
+        tdesc.buffer_address = device->region_base + offset + valid_data;
+        tdesc.ctrl.raw = 0;
+        tdesc.ctrl.legacy.data_len = valid_length;
+        tdesc.ctrl.legacy.cmd.d.eop = 1;
+        tdesc.ctrl.legacy.cmd.d.ifcs = 1;
+        tdesc.ctrl.legacy.cmd.d.rs = 1;
+}
+
+    device->transmit_ring[device->transmit_tail] = tdesc;
+    device->transmit_tail = (device->transmit_tail + 1) % DRIVER_TRANSMIT_BUFFERS;
+
+    e1000_dqval_t dqval = 0;
+    dqval = e1000_dqval_val_insert(dqval, device->transmit_tail);
+    e1000_tdt_wr(&device->hw_device, 0, dqval);
+
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_dequeue_tx(e1000_queue_t *device, regionid_t* rid, genoffset_t* offset,
+                                 genoffset_t* length, genoffset_t* valid_data,
+                                 genoffset_t* valid_length, uint64_t* flags)
+{
+    if (device->transmit_head == device->transmit_tail) {
+        return DEVQ_ERR_QUEUE_EMPTY;
+    }
+
+    volatile struct tx_desc *txd;
+    txd = &device->transmit_ring[device->transmit_head];
+    if (txd->ctrl.legacy.stat_rsv.d.dd != 1) {
+        return DEVQ_ERR_QUEUE_EMPTY;
+    }
+    device->transmit_head = (device->transmit_head + 1) % DRIVER_TRANSMIT_BUFFERS;
+    
+    *rid = device->region_id;
+    *offset = txd->buffer_address - device->region_base;
+    *length = 2048;
+    *valid_data = *offset & 2047;
+    *offset &= ~2047;
+    *valid_length = txd->ctrl.legacy.data_len;
+    *flags = NETIF_TXFLAG | NETIF_TXFLAG_LAST;
+    
+    // debug_print_to_log("DEQTX %d", *valid_length);
+    // debug_printf("%s:%s: %lx:%ld:%ld:%ld:%lx\n", device->name, __func__, *offset, *length, *valid_data, *valid_length, *flags);
+
+    return SYS_ERR_OK;
+}
+
+
+static errval_t e1000_enqueue(struct devq* q, regionid_t rid,
+                                 genoffset_t offset, genoffset_t length,
+                                 genoffset_t valid_data, genoffset_t valid_length,
+                                 uint64_t flags)
+{
+    e1000_queue_t *device = (e1000_queue_t *)q;
+    errval_t err;
+
+    if (flags & NETIF_RXFLAG) {
+        /* can not enqueue receive buffer larger than 2048 bytes */
+        assert(length <= 2048);
+
+        err = e1000_enqueue_rx(device, rid, offset, length, valid_data, valid_length,
+                             flags);
+        if (err_is_fail(err)) {
+            return err;
+        }
+    } else if (flags & NETIF_TXFLAG) {
+        assert(length <= BASE_PAGE_SIZE);
+
+        err = e1000_enqueue_tx(device, rid, offset, length, valid_data, valid_length,
+                             flags);
+        if (err_is_fail(err)) {
+            return err;
+        }
+    } else {
+        printf("Unknown buffer flags \n");
+        return NIC_ERR_ENQUEUE;
+    }
+
+    return SYS_ERR_OK;
+}
+
+static errval_t e1000_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset,
+                                 genoffset_t* length, genoffset_t* valid_data,
+                                 genoffset_t* valid_length, uint64_t* flags)
+{
+    e1000_queue_t *device = (e1000_queue_t *)q;
+    
+    if (e1000_dequeue_tx(device, rid, offset, length, valid_data, valid_length, flags) == SYS_ERR_OK)
+        return SYS_ERR_OK;
+    if (e1000_dequeue_rx(device, rid, offset, length, valid_data, valid_length, flags) == SYS_ERR_OK)
+        return SYS_ERR_OK;
+    // debug_printf("%s:%s:\n", device->name, __func__);
+    return DEVQ_ERR_QUEUE_EMPTY;
+}
+
+static errval_t e1000_notify(struct devq* q)
+{
+    assert(0);
+    return SYS_ERR_OK;
+}
+
+/*****************************************************************
+ * Reset the device and disable interrupts.
+ *
+ ****************************************************************/
+static int e1000_reset(e1000_queue_t *device)
+{
+    // errval_t err = 0;
+    int timeout;
+    e1000_t *hw_device = &device->hw_device;
+
+    /* disable interrupts */
+    if (device->extended_interrupts) {
+        e1000_eimc_wr(hw_device, 0xffffffff);
+    }
+    e1000_imc_rawwr(hw_device, 0xffffffff);
+
+    /* disable receive and transmit */
+    e1000_rctl_rawwr(hw_device, 0);
+    e1000_tctl_rawwr(hw_device, 0);
+
+    /* Delay to allow outstanding PCI transactions to complete before
+     * reseting the device */
+    // usec_delay(1000);
+    e1000_ctrl_phy_rst_wrf(hw_device, 1);
+    e1000_ctrl_rst_wrf(hw_device, 1);
+    /* Wait for reset to clear */
+    timeout = 1000;
+    do {
+        // usec_delay(10);
+    } while (e1000_ctrl_rst_rdf(hw_device) != 0 && 0 < timeout--);
+    assert(timeout >= 0);
+    debug_printf("%s.%d: timeout=%d\n", __func__, __LINE__, timeout);
+
+    /* clear any pending interrupts */
+    e1000_icr_rd(hw_device);
+    if (device->extended_interrupts) {
+        e1000_eicr_rd(hw_device);
+    }
+    
+    e1000_ctrl_phy_rst_wrf(hw_device, 0);
+
+    debug_printf("Reset done..\n");
+
+    return 0;
+}
+
+/*
+ * setup MAC
+ */
+static void e1000_setup_mac(e1000_queue_t *device, uint64_t *mac_addr)
+{
+    e1000_t *hw_device = &device->hw_device;
+    
+    /* is a valid MAC already present? */
+    /* This will always return false due to hardware/software reset */
+    bool mac_present = e1000_rah_av_rdf(hw_device, 0);
+    
+    assert(mac_present);
+    /* cache MAC for stack to see */
+    uint64_t mac_hi = e1000_rah_rah_rdf(hw_device, 0);
+    uint64_t mac = e1000_ral_rd(hw_device, 0) + (mac_hi << 32);
+    *mac_addr = mac | (mac_hi << 32);
+
+    debug_printf("%s: MAC address: %lx\n", device->name, *mac_addr);
+    device->mac_address = *mac_addr;
+
+    /* clear all other filers (clear high-to-low (13.4.3)) */
+    for (int i = 1; i < e1000_ral_length; i++) {
+        e1000_rah_wr(hw_device, i, 0);
+        e1000_ral_wr(hw_device, i, 0);
+    }
+
+}
+
+static void e1000_setup_link(e1000_queue_t *device)
+{
+    e1000_t *hw_device = &device->hw_device;
+    e1000_ctrl_slu_wrf(hw_device, 1);
+    // e1000_ctrl_asde_wrf(hw_device, 1);
+}
+
+/*
+ * Set interrupt throttle for all interrupts
+ */
+static void e1000_set_interrupt_throttle(e1000_queue_t *device, uint16_t usec)
+{
+    e1000_t *hw_device = &device->hw_device;
+    /* Enable interrupt throttling rate.
+     *
+     * The optimal performance setting for this register is very system and
+     * configuration specific. A initial suggested range is 651-5580 (28Bh - 15CCh).
+     * The value 0 will disable interrupt throttling
+     */
+    int16_t rate = usec;
+    
+    if (device->mac_type == e1000_82575
+        || device->mac_type == e1000_82576
+        || device->mac_type == e1000_I210
+        || device->mac_type == e1000_I350) {
+        e1000_eitr_interval_wrf(hw_device, 0, rate);
+        e1000_eitr_interval_wrf(hw_device, 1, rate);
+        e1000_eitr_interval_wrf(hw_device, 2, rate);
+        e1000_eitr_interval_wrf(hw_device, 3, rate);
+    } else if (device->mac_type == e1000_82574) {
+        e1000_itr_interval_wrf(hw_device, rate * 4);
+        e1000_eitr_82574_interval_wrf(hw_device, 0, rate);
+        e1000_eitr_82574_interval_wrf(hw_device, 1, rate);
+        e1000_eitr_82574_interval_wrf(hw_device, 2, rate);
+        e1000_eitr_82574_interval_wrf(hw_device, 3, rate);
+    } else {
+        e1000_itr_interval_wrf(hw_device, rate * 4);
+    }
+}
+
+static void e1000_enable_interrupts(e1000_queue_t *device)
+{
+    e1000_t *hw_device = &device->hw_device;
+
+    e1000_set_interrupt_throttle(device, E1000_DEFAULT_INT_THROTTLE_RATE);
+
+    if (device->extended_interrupts) {
+        e1000_intreg_t intreg = 0;
+        /* Activate link change interrupt */
+        intreg = e1000_intreg_lsc_insert(intreg, 1);
+        e1000_ims_wr(hw_device, intreg);
+        
+        e1000_ivar_int_alloc0_wrf(hw_device, 0, 0);
+        e1000_ivar_int_alloc1_wrf(hw_device, 0, 1);
+        e1000_ivar_int_alloc_val0_wrf(hw_device, 0, 1);
+        e1000_ivar_int_alloc_val1_wrf(hw_device, 0, 1);
+
+        e1000_eintreg_t eintreg = 0;
+        eintreg = e1000_eintreg_rxtxq0_insert(eintreg, 1);
+        eintreg = e1000_eintreg_rxtxq1_insert(eintreg, 1);
+
+        e1000_iam_wr(hw_device, 0);
+        e1000_eims_wr(hw_device, eintreg);
+        e1000_eiac_wr(hw_device, 0);
+        e1000_eiam_wr(hw_device, eintreg);
+        e1000_gpie_nsicr_wrf(hw_device, 1);
+    } else {
+        e1000_intreg_t intreg = 0;
+        /* Activate link change interrupt */
+        intreg = e1000_intreg_lsc_insert(intreg, 1);
+        /* Activate rx0 interrupt */
+        intreg = e1000_intreg_rxt0_insert(intreg, 1);
+        intreg = e1000_intreg_txdw_insert(intreg, 1);
+        e1000_ims_wr(hw_device, intreg);
+
+    /* In case of the 82574, we explicitly activate int cause auto clear to
+     * get the same behaviour as the other cards */
+        if (device->mac_type == e1000_82574) {
+            e1000_ctrlext_iame_wrf(hw_device, 1);
+        }
+    }
+    debug_printf("%s: Interrupts enabled\n", __func__);
+}
+
+
+/*****************************************************************
+ * allocate a single frame, mapping it into our vspace with given
+ * attributes
+ ****************************************************************/
+static void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap)
+{
+    struct capref frame;
+    errval_t err;
+    void *va;
+
+    err = frame_alloc(&frame, size, NULL);
+    assert(err_is_ok(err));
+    err = vspace_map_one_frame_attr(&va, size, frame, attr, NULL, NULL);
+    assert(err_is_ok(err));
+
+    if (retcap != NULL) {
+        *retcap = frame;
+    }
+    return va;
+}
+
+/*****************************************************************
+ * Set RX buffer size and enable receive unit.
+ *
+ ****************************************************************/
+static void e1000_set_rxbsize(e1000_queue_t *device, e1000_rx_bsize_t rx_bsize)
+{
+    e1000_t *hw_device = &device->hw_device;
+    uint8_t bsize;
+    uint8_t bsex;
+    e1000_rctl_t rctl;
+
+    switch (rx_bsize) {
+    case bsize_16384:
+        bsize = 0x1;
+        bsex = 1;
+        break;
+    case bsize_8192:
+        bsize = 0x2;
+        bsex = 1;
+        break;
+    case bsize_4096:
+        bsize = 0x3;
+        bsex = 1;
+        break;
+    case bsize_2048:
+        bsize = 0x0;
+        bsex = 0;
+        break;
+    case bsize_1024:
+        bsize = 0x1;
+        bsex = 0;
+        break;
+    case bsize_512:
+        bsize = 0x2;
+        bsex = 0;
+        break;
+    case bsize_256:
+    default:
+        bsize = 0x3;
+        bsex = 0;
+        break;
+    }
+
+    rctl = e1000_rctl_rd(hw_device);
+    rctl = e1000_rctl_bsize_insert(rctl, bsize);
+    rctl = e1000_rctl_bsex_insert(rctl, bsex);
+    rctl = e1000_rctl_bam_insert(rctl, 1);
+    e1000_rctl_wr(hw_device, rctl);
+
+    e1000_rctl_en_wrf(hw_device, 1);
+}
+
+/*****************************************************************
+ * Configure device receive
+ *
+ ****************************************************************/
+static void e1000_setup_rx(e1000_queue_t *device)
+{
+    e1000_t *hw_device = &device->hw_device;
+    struct frame_identity frameid = { .base = 0, .bytes = 0 };
+    struct capref frame;
+    errval_t err;
+
+    /* Allocate and map frame for receive ring */
+    device->receive_ring = alloc_map_frame(VREGION_FLAGS_READ_WRITE_NOCACHE,
+                                sizeof(union rx_desc) * device->receive_buffers,
+                                &frame);
+    assert(device->receive_ring);
+    err = invoke_frame_identify(frame, &frameid);
+    assert(err_is_ok(err));
+
+    /* clear MTA table */
+    for (int i = 0; i < e1000_mta_length; i++) {
+        e1000_mta_wr(hw_device, i, 0);
+    }
+
+    switch (device->mac_type) {
+        case e1000_82576:
+        case e1000_I210:
+        case e1000_I350: {
+            /*  Software should program RDLEN[n] register only when queue is disabled */
+            e1000_rdbal_I350_wr(hw_device, 0, frameid.base & 0xffffffff);
+            e1000_rdbah_I350_wr(hw_device, 0, (frameid.base >> 32) & 0xffffffff);
+            e1000_rdlen_I350_len_wrf(hw_device, 0, (device->receive_buffers / 8));
+
+            /* Initialize receive head and tail pointers */
+            e1000_rdh_I350_wr(hw_device, 0, 0);
+            e1000_rdt_I350_wr(hw_device, 0, 0);
+        } break;
+        default: {
+            /* tell card where receive ring is */
+            e1000_rdbal_wr(hw_device, 0, frameid.base & 0xffffffff);
+            e1000_rdbah_wr(hw_device, 0, (frameid.base >> 32) & 0xffffffff);
+            e1000_rdlen_len_wrf(hw_device, 0, (device->receive_buffers / 8));
+
+            /* Initialize receive head and tail pointers */
+            e1000_rdh_wr(hw_device, 0, 0);
+            e1000_rdt_wr(hw_device, 0, 0);
+        } break;
+    }
+
+    /* set buffer size and enable receive unit */
+    e1000_set_rxbsize(device, bsize_2048);
+
+    /* receive descriptor control */
+    switch (device->mac_type) {
+        case e1000_82575:
+        {
+            e1000_rxdctl_82575_t rxdctl = 0;
+
+            rxdctl = e1000_rxdctl_82575_enable_insert(rxdctl, 1);
+            rxdctl = e1000_rxdctl_82575_wthresh_insert(rxdctl, 1);
+            e1000_rxdctl_82575_wr(hw_device, 0, rxdctl);
+            
+            debug_printf("%s: rxdctl %x\n", __func__, e1000_rxdctl_82575_rd(hw_device, 0));
+        } break;
+        case e1000_82576:
+        case e1000_I210:
+        case e1000_I350: {
+            /* If VLANs are not used, software should clear VFE. */
+            e1000_rctl_vfe_wrf(hw_device, 0);
+
+             /* Set up the MTA (Multicast Table Array) by software. This means
+              * zeroing all entries initially and adding in entries as requested. */
+            for (int i = 0; i < 128; ++i) {
+                e1000_mta_wr(hw_device, i, 0);
+            }
+
+            /* Program SRRCTL of the queue according to the size of the buffers,
+             * the required header handling and the drop policy. */
+            e1000_srrctl_t srrctl = 0;
+            srrctl = e1000_srrctl_bsizeheader_insert(srrctl, 0);
+            e1000_srrctl_wr(hw_device, 0, srrctl);
+
+            /* Enable the queue by setting RXDCTL.ENABLE. In the case of queue zero,
+             * the enable bit is set by default - so the ring parameters should be
+             * set before RCTL.RXEN is set. */
+            e1000_rxdctl_I350_t rxdctl = 0;
+            rxdctl = e1000_rxdctl_I350_enable_insert(rxdctl, 1);
+            rxdctl = e1000_rxdctl_I350_wthresh_insert(rxdctl, 1);
+            e1000_rxdctl_I350_wr(hw_device, 0, rxdctl);
+
+            /* Poll the RXDCTL register until the ENABLE bit is set. The tail should
+             * not be bumped before this bit was read as one. */
+            int timeout = 1000;
+            while (!e1000_rxdctl_I350_enable_rdf(hw_device, 0) && timeout--) {
+                // usec_delay(10);
+            }
+            debug_printf("%s.%d: timeout=%d\n", __func__, __LINE__, timeout);
+            // if (timeout <= 0) {
+            //     E1000_DEBUG("ERROR: failed to enable the RX queue\n");
+            // }
+        } break;
+        default: {
+            e1000_rxdctl_t rxdctl = 0;
+
+            rxdctl = e1000_rxdctl_gran_insert(rxdctl, 1);
+            rxdctl = e1000_rxdctl_wthresh_insert(rxdctl, 1);
+            e1000_rxdctl_wr(hw_device, 0, rxdctl);
+
+            e1000_rfctl_exsten_wrf(hw_device, 0);
+        } break;
+    }
+    
+    debug_printf("%s: rctl:%x  rxdctl:%x\n", __func__, e1000_rctl_rd(hw_device), e1000_rxdctl_rd(hw_device, 0));
+}
+
+/*****************************************************************
+ * Configure card transmit
+ *
+ ****************************************************************/
+static void e1000_setup_tx(e1000_queue_t *device)
+{
+    e1000_t *hw_device = &device->hw_device;
+    struct frame_identity frameid = { .base = 0, .bytes = 0 };
+    struct capref frame;
+    errval_t err;
+
+    /* allocate and map frame for transmit ring */
+    device->transmit_ring = alloc_map_frame(VREGION_FLAGS_READ_WRITE_NOCACHE,
+                              sizeof(struct tx_desc) * device->transmit_buffers,
+                              &frame);
+    assert(device->transmit_ring);
+    err = invoke_frame_identify(frame, &frameid);
+    assert(err_is_ok(err));
+
+    switch (device->mac_type) {
+        case e1000_82576:
+        case e1000_I210:
+        case e1000_I350: {
+            /* Software should program TDLEN[n] register only when queue is disabled */
+            e1000_tdbal_I350_wr(hw_device, 0, frameid.base & 0xffffffff);
+            e1000_tdbah_I350_wr(hw_device, 0, frameid.base >> 32);
+            e1000_tdlen_I350_len_wrf(hw_device, 0, (device->transmit_buffers / 8));
+            e1000_tdh_I350_wr(hw_device, 0, 0);
+            e1000_tdt_I350_wr(hw_device, 0, 0);
+        } break;
+        default: {
+            /* tell card about our transmit ring */
+            e1000_tdbal_wr(hw_device, 0, frameid.base & 0xffffffff);
+            e1000_tdbah_wr(hw_device, 0, frameid.base >> 32);
+            e1000_tdlen_len_wrf(hw_device, 0, (device->transmit_buffers / 8));
+            e1000_tdh_wr(hw_device, 0, 0);
+            e1000_tdt_wr(hw_device, 0, 0);
+        } break;
+    }
+    
+    /* --------------------- transmit setup --------------------- */
+    switch (device->mac_type) {
+        case e1000_82575:
+        {
+            e1000_txdctl_82575_t txdctl = 0;
+            txdctl = e1000_txdctl_82575_enable_insert(txdctl, 1);
+            txdctl = e1000_txdctl_82575_priority_insert(txdctl, 1);
+            e1000_txdctl_82575_wr(hw_device, 0, txdctl);
+        } break;
+        case e1000_82576:
+        case e1000_I210:
+        case e1000_I350: {
+            /* Program the TXDCTL register with the desired TX descriptor write
+             * back policy. Suggested values are:
+                    — WTHRESH = 1b
+                    — All other fields 0b.
+             */
+            e1000_txdctl_I350_t txdctl = 0;
+            // txdctl = e1000_txdctl_I350_priority_insert(txdctl, 1);
+            txdctl = e1000_txdctl_I350_wthresh_insert(txdctl, 1);
+            e1000_txdctl_I350_wr(hw_device, 0, txdctl);
+
+            /* If needed, set the TDWBAL/TWDBAH to enable head write back */
+            e1000_tdwbal_wr(hw_device, 0, 0);
+            e1000_tdwbah_wr(hw_device, 0, 0);
+
+            /* Enable the queue using TXDCTL.ENABLE (queue zero is enabled by default). */
+            e1000_txdctl_I350_enable_wrf(hw_device, 0, 1);
+        } break;
+        default: {
+            e1000_txdctl_t txdctl = 0;
+            txdctl = e1000_txdctl_gran_insert(txdctl, 1);
+            txdctl = e1000_txdctl_wthresh_insert(txdctl, 1);
+            e1000_txdctl_wr(hw_device, 0, txdctl);
+        } break;
+    }
+    /* enable transmit */
+
+    e1000_tctl_t tctl = 0;
+    tctl = e1000_tctl_ct_insert(tctl, 0xf);
+    tctl = e1000_tctl_en_insert(tctl, 1);
+    tctl = e1000_tctl_psp_insert(tctl, 1);
+    e1000_tctl_wr(hw_device, tctl);
+
+    if (device->mac_type == e1000_82576 || device->mac_type == e1000_I210 || device->mac_type == e1000_I350) {
+            /* Poll the TXDCTL register until the ENABLE bit is set. */
+            int timeout = 1000;
+            while(!e1000_txdctl_I350_enable_rdf(hw_device, 0) && timeout--) {
+                // usec_delay(10);
+            }
+            debug_printf("%s.%d: timeout=%d\n", __func__, __LINE__, timeout);
+            // if (timeout <= 0) {
+            //     E1000_DEBUG("ERROR: failed to enable the TX queue\n");
+            // }
+    }
+    debug_printf("%s: tctl:%x  txdctl:%x\n", __func__, e1000_tctl_rd(hw_device), e1000_txdctl_rd(hw_device, 0));
+}
+
+// static void e1000_timer(void *arg)
+// {
+//     e1000_queue_t *device = arg;
+//     e1000_t *hw_device = &device->hw_device;
+//
+//     debug_printf("%x %x  %x %x\n", e1000_ctrl_rd(hw_device), e1000_status_rd(hw_device), e1000_icr_rd(hw_device), e1000_ims_rd(hw_device));
+// }
+
+/*****************************************************************
+ * PCI init callback.
+ *
+ * Setup device, create receive ring and connect to Ethernet server.
+ *
+ ****************************************************************/
+static void e1000_init_fn(void *user_state, struct device_mem *bar_info,
+                          int nr_allocated_bars)
+{
+    e1000_queue_t *device = user_state;
+    uint64_t mac_addr;
+    errval_t err;
+
+    err = map_device(&bar_info[0]);
+    assert(err_is_ok(err));
+
+    e1000_initialize(&device->hw_device, (void *) bar_info[0].vaddr);
+
+    device->mac_type = e1000_get_mac_type(device->pci_vendor, device->pci_deviceid);
+    debug_printf("%s: mac_type is: %s\n", __func__, e1000_mac_type_to_str(device->mac_type));
+    
+    // set features
+    switch (device->mac_type) {
+        case e1000_82571:
+        case e1000_82572:
+        case e1000_82574: {
+            device->extended_interrupts = 0;
+            device->advanced_descriptors = 1;
+        } break;
+        case e1000_82576:
+        case e1000_I210:
+        case e1000_I350: {
+            device->extended_interrupts = 1;
+            device->advanced_descriptors = 3;
+        } break;
+    default:
+        device->extended_interrupts = 0;
+        device->advanced_descriptors = 0;
+    }
+
+    e1000_reset(device);
+    e1000_setup_mac(device, &mac_addr);
+    e1000_setup_link(device);
+    e1000_setup_rx(device);
+    e1000_setup_tx(device);
+
+    /* Enable interrupts */
+    if (device->interrupt_mode) {
+        e1000_enable_interrupts(device);
+    }
+
+    // periodic_event_create(&device->timer, get_default_waitset(),
+    //                            500000, MKCLOSURE(e1000_timer, device));
+}
+
+/*****************************************************************
+ * Check link connection status.
+ *
+ ****************************************************************/
+static bool e1000_check_link_up(e1000_queue_t *device)
+{
+    e1000_t *hw_device = &device->hw_device;
+    e1000_status_t status = e1000_status_rd(hw_device);
+
+    if (e1000_status_lu_extract(status)) {
+        return true;
+    }
+    return false;
+}
+
+static void e1000_interrupt_handler(void *arg)
+{
+    e1000_queue_t *device = arg;
+    e1000_t *hw_device = &device->hw_device;
+    /* Read interrupt cause, this also acknowledges the interrupt */
+    e1000_intreg_t icr;
+    e1000_eintreg_t eicr;
+    
+    icr = e1000_icr_rd(hw_device);
+    if (device->extended_interrupts) {
+        eicr = e1000_eicr_rd(hw_device);
+        // debug_print_to_log("IRQ %x:%x", icr, eicr);
+        // debug_printf("IRQ %x:%x\n", icr, eicr);
+    } else {
+        // debug_print_to_log("IRQ %x", icr);
+        // debug_printf("IRQ %x\n", icr);
+    }
+
+    if (e1000_intreg_lsc_extract(icr) != 0) {
+        if (e1000_check_link_up(device)) {
+            debug_printf("%s: link up\n", device->name);
+        } else {
+            debug_printf("%s: link down\n", device->name);
+        }
+    }
+    device->isr(device);
+    // debug_printf("%s: E1k RX:%d:%d(%d:%d)  TX:%d:%d(%d:%d)\n",
+    //     device->name,
+    //     device->receive_head, device->receive_tail,
+    //     e1000_rdh_rd(hw_device, 0), e1000_rdt_rd(hw_device, 0),
+    //     device->transmit_head, device->transmit_tail,
+    //     e1000_tdh_rd(hw_device, 0), e1000_tdt_rd(hw_device, 0));
+    if (device->extended_interrupts) { // unmask interrupts
+        e1000_eintreg_t eintreg = 0;
+        eintreg = e1000_eintreg_rxtxq0_insert(eintreg, 1);
+        eintreg = e1000_eintreg_rxtxq1_insert(eintreg, 1);
+
+        e1000_eims_wr(hw_device, eintreg);
+    }
+}
+
+static void e1000_reregister_handler(void *arg)
+{
+    e1000_queue_t *device = arg;
+    errval_t err;
+    uint32_t class = PCI_CLASS_ETHERNET;
+    uint32_t subclass = PCI_DONT_CARE;
+    uint32_t program_interface = PCI_DONT_CARE;
+    
+    printf("%s:%s:%d:\n", __FILE__, __FUNCTION__, __LINE__);
+    err = pci_reregister_irq_for_device(
+            class, subclass, program_interface,
+            device->pci_vendor, device->pci_deviceid, device->pci_bus,
+            device->pci_device, device->pci_function,
+            e1000_interrupt_handler, device,
+            e1000_reregister_handler, device);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "pci_reregister_irq_for_device");
+    }
+
+    return;
+}
+
+static void e1000_init(e1000_queue_t *device, unsigned interrupt_mode)
+{
+    errval_t err;
+    uint32_t class = PCI_CLASS_ETHERNET;
+    uint32_t subclass = PCI_DONT_CARE;
+    uint32_t program_interface = PCI_DONT_CARE;
+
+    err = pci_client_connect();
+    assert(err_is_ok(err));
+
+    if (interrupt_mode) { // 1 or 2
+        err = pci_register_driver_movable_irq(e1000_init_fn, device, class,
+                                              subclass, program_interface,
+                                              device->pci_vendor, device->pci_deviceid,
+                                              device->pci_bus, device->pci_device,
+                                              device->pci_function,
+                                              e1000_interrupt_handler, device,
+                                              e1000_reregister_handler, device);
+        printf("########### Driver with interrupts ###########\n");
+    } else {
+        err = pci_register_driver_noirq(e1000_init_fn, device, class, subclass,
+                                        program_interface, device->pci_vendor,
+                                        device->pci_deviceid, device->pci_bus,
+                                        device->pci_device, device->pci_function);
+        printf("########### Driver without interrupts ###########\n");
+    }
+}
+
+
+errval_t e1000_queue_create(e1000_queue_t ** q, uint32_t vendor, uint32_t deviceid,
+    uint32_t bus, uint32_t pci_device, uint32_t function, unsigned interrupt_mode,
+    void (*isr)(void *))
+{
+    errval_t err;
+    e1000_queue_t *device;
+    
+    debug_printf("%s: %x:%x:%x:%x:%x  %d\n", __func__, vendor, deviceid, bus,
+        pci_device, function, interrupt_mode);
+
+    device = malloc(sizeof(e1000_queue_t));
+    assert(device);
+
+    device->pci_vendor = vendor;
+    device->pci_deviceid = deviceid;
+    device->pci_bus = bus;
+    device->pci_device = pci_device;
+    device->pci_function = function;
+    device->interrupt_mode = interrupt_mode;
+    device->name = malloc(128);
+    snprintf(device->name, 128, "e1000:%x:%x:%x:%x:%x", vendor, deviceid, bus,
+        pci_device, function);
+
+    device->receive_head = 0;
+    device->receive_tail = 0;
+    device->transmit_head = 0;
+    device->transmit_tail = 0;
+    device->region_id = 0;
+    device->isr = isr;
+
+    device->receive_buffers = DRIVER_RECEIVE_BUFFERS;
+    device->transmit_buffers = DRIVER_TRANSMIT_BUFFERS;
+
+    e1000_init(device, interrupt_mode);
+
+    err = devq_init(&device->q, false);
+    assert(err_is_ok(err));
+    
+    device->q.f.enq = e1000_enqueue;
+    device->q.f.deq = e1000_dequeue;
+    device->q.f.reg = e1000_register;
+    device->q.f.dereg = e1000_deregister;
+    device->q.f.ctrl = e1000_control;
+    device->q.f.notify = e1000_notify;
+    
+    *q = device;
+
+    return SYS_ERR_OK;
+}
+
+errval_t e1000_queue_destroy(e1000_queue_t * q)
+{
+    return SYS_ERR_OK;
+}
+
+
+e1000_mac_type_t e1000_get_mac_type(uint32_t vendor, uint32_t device_id)
+{
+    if (vendor == PCI_VENDOR_INTEL) {
+
+        switch (device_id) {
+        case E1000_DEVICE_82542:
+            return e1000_82542;
+        case E1000_DEVICE_82543GC_FIBER:
+        case E1000_DEVICE_82543GC_COPPER:
+            return e1000_82543;
+        case E1000_DEVICE_82544EI_COPPER:
+        case E1000_DEVICE_82544EI_FIBER:
+        case E1000_DEVICE_82544GC_COPPER:
+        case E1000_DEVICE_82544GC_LOM:
+            return e1000_82544;
+        case E1000_DEVICE_82540EM:
+        case E1000_DEVICE_82540EM_LOM:
+        case E1000_DEVICE_82540EP:
+        case E1000_DEVICE_82540EP_LOM:
+        case E1000_DEVICE_82540EP_LP:
+            return e1000_82540;
+        case E1000_DEVICE_82545EM_COPPER:
+        case E1000_DEVICE_82545EM_FIBER:
+            return e1000_82545;
+        case E1000_DEVICE_82545GM_COPPER:
+        case E1000_DEVICE_82545GM_FIBER:
+        case E1000_DEVICE_82545GM_SERDES:
+            return e1000_82545_rev_3;
+        case E1000_DEVICE_82546EB_COPPER:
+        case E1000_DEVICE_82546EB_FIBER:
+        case E1000_DEVICE_82546EB_QUAD_COPPER:
+            return e1000_82546;
+        case E1000_DEVICE_82546GB_COPPER:
+        case E1000_DEVICE_82546GB_FIBER:
+        case E1000_DEVICE_82546GB_SERDES:
+        case E1000_DEVICE_82546GB_PCIE:
+        case E1000_DEVICE_82546GB_QUAD_COPPER:
+        case E1000_DEVICE_82546GB_QUAD_COPPER_KSP3:
+            return e1000_82546_rev_3;
+        case E1000_DEVICE_82541EI:
+        case E1000_DEVICE_82541EI_MOBILE:
+        case E1000_DEVICE_82541ER_LOM:
+            return e1000_82541;
+        case E1000_DEVICE_82541ER:
+        case E1000_DEVICE_82541GI:
+        case E1000_DEVICE_82541GI_LF:
+        case E1000_DEVICE_82541GI_MOBILE:
+            return e1000_82541_rev_2;
+        case E1000_DEVICE_82547EI:
+        case E1000_DEVICE_82547EI_MOBILE:
+            return e1000_82547;
+        case E1000_DEVICE_82547GI:
+            return e1000_82547_rev_2;
+        case E1000_DEVICE_82563EB:
+            return e1000_82563;
+        case E1000_DEVICE_82571EB_COPPER:
+        case E1000_DEVICE_82571EB_FIBER:
+        case E1000_DEVICE_82571EB_SERDES:
+        case E1000_DEVICE_82571EB_SERDES_DUAL:
+        case E1000_DEVICE_82571EB_SERDES_QUAD:
+        case E1000_DEVICE_82571EB_QUAD_COPPER:
+        case E1000_DEVICE_82571EB_QUAD_FIBER:
+        case E1000_DEVICE_82571EB_QUAD_COPPER_LOWPROFILE:
+            return e1000_82571;
+        case E1000_DEVICE_82572EI_COPPER:
+        case E1000_DEVICE_82572EI_FIBER:
+        case E1000_DEVICE_82572EI_SERDES:
+        case E1000_DEVICE_82572EI:
+            return e1000_82572;
+        case E1000_DEVICE_82573E:
+        case E1000_DEVICE_82573E_IAMT:
+        case E1000_DEVICE_82573L:
+            return e1000_82573;
+        case E1000_DEVICE_82574L:
+            return e1000_82574;
+        case E1000_DEVICE_82575EB:
+            return e1000_82575;
+        case E1000_DEVICE_82576EG:
+            return e1000_82576;
+        case E1000_DEVICE_I210:
+            return e1000_I210;
+        case E1000_DEVICE_I350_EEPROM_LESS:
+        case E1000_DEVICE_I350_COPPER:
+        case E1000_DEVICE_I350_FIBER:
+        case E1000_DEVICE_I350_BACKPANE:
+        case E1000_DEVICE_I350_SGMII:
+        case E1000_DEVICE_I350_DUMMY:
+            return e1000_I350;
+        default:
+            // E1000_DEBUG("Unsupported device: vendor: 0x%x,  device id: 0x%x\n", PCI_VENDOR_INTEL, device_id);
+            return e1000_undefined;
+        }
+    }
+
+    return e1000_undefined;
+}
+
+char * e1000_mac_type_to_str(e1000_mac_type_t mt){
+    char * names[] = {
+        "undefined",
+        "82542",
+        "82543",
+        "82544",
+        "82540",
+        "82545",
+        "82545_rev_3",
+        "82546",
+        "82546_rev_3",
+        "82541",
+        "82541_rev_2",
+        "82547",
+        "82547_rev_2",
+        "82563",
+        "82571",
+        "82572",
+        "82573",
+        "82574",
+        "82575",
+        "82576",
+        "I210",
+        "I350"
+    };
+    if(mt >= e1000_num_macs) return NULL;
+    return names[mt];
+};
diff --git a/lib/devif/backends/net/e1000/e1000.h b/lib/devif/backends/net/e1000/e1000.h
new file mode 100644 (file)
index 0000000..4c62d4f
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2017, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef E1000_H
+#define E1000_H
+
+#include <devif/queue_interface.h>
+
+#include <barrelfish/barrelfish.h>
+#include <pci/pci.h>
+
+#include <dev/e1000_dev.h>      /* auto generated by Mackerel */
+
+
+/*
+ * e1000 (e1000) device family id's.
+ */
+#define E1000_DEVICE_82542               0x1000
+#define E1000_DEVICE_82543GC_FIBER       0x1001
+#define E1000_DEVICE_82543GC_COPPER      0x1004
+#define E1000_DEVICE_82544EI_COPPER      0x1008
+#define E1000_DEVICE_82544EI_FIBER       0x1009
+#define E1000_DEVICE_82544GC_COPPER      0x100C
+#define E1000_DEVICE_82544GC_LOM         0x100D
+#define E1000_DEVICE_82540EM             0x100E
+#define E1000_DEVICE_82540EM_LOM         0x1015
+#define E1000_DEVICE_82540EP_LOM         0x1016
+#define E1000_DEVICE_82540EP             0x1017
+#define E1000_DEVICE_82540EP_LP          0x101E
+#define E1000_DEVICE_82545EM_COPPER      0x100F
+#define E1000_DEVICE_82545EM_FIBER       0x1011
+#define E1000_DEVICE_82545GM_COPPER      0x1026
+#define E1000_DEVICE_82545GM_FIBER       0x1027
+#define E1000_DEVICE_82545GM_SERDES      0x1028
+#define E1000_DEVICE_82546EB_COPPER      0x1010
+#define E1000_DEVICE_82546EB_FIBER       0x1012
+#define E1000_DEVICE_82546EB_QUAD_COPPER 0x101D
+#define E1000_DEVICE_82541EI             0x1013
+#define E1000_DEVICE_82541EI_MOBILE      0x1018
+#define E1000_DEVICE_82541ER_LOM         0x1014
+#define E1000_DEVICE_82541ER             0x1078
+#define E1000_DEVICE_82547GI             0x1075
+#define E1000_DEVICE_82541GI             0x1076
+#define E1000_DEVICE_82541GI_MOBILE      0x1077
+#define E1000_DEVICE_82541GI_LF          0x107C
+#define E1000_DEVICE_82546GB_COPPER      0x1079
+#define E1000_DEVICE_82546GB_FIBER       0x107A
+#define E1000_DEVICE_82546GB_SERDES      0x107B
+#define E1000_DEVICE_82546GB_PCIE        0x108A
+#define E1000_DEVICE_82546GB_QUAD_COPPER 0x1099
+#define E1000_DEVICE_82563EB             0x1096
+#define E1000_DEVICE_82547EI             0x1019
+#define E1000_DEVICE_82547EI_MOBILE      0x101A
+#define E1000_DEVICE_82571EB_COPPER      0x105E
+#define E1000_DEVICE_82571EB_FIBER       0x105F
+#define E1000_DEVICE_82571EB_SERDES      0x1060
+#define E1000_DEVICE_82571EB_QUAD_COPPER 0x10A4
+#define E1000_DEVICE_82571EB_QUAD_FIBER  0x10A5
+#define E1000_DEVICE_82571EB_QUAD_COPPER_LOWPROFILE  0x10BC
+#define E1000_DEVICE_82571EB_SERDES_DUAL 0x10D9
+#define E1000_DEVICE_82571EB_SERDES_QUAD 0x10DA
+#define E1000_DEVICE_82572EI_COPPER      0x107D
+#define E1000_DEVICE_82572EI_FIBER       0x107E
+#define E1000_DEVICE_82572EI_SERDES      0x107F
+#define E1000_DEVICE_82572EI             0x10B9
+#define E1000_DEVICE_82573E              0x108B
+#define E1000_DEVICE_82573E_IAMT         0x108C
+#define E1000_DEVICE_82573L              0x109A
+#define E1000_DEVICE_82574L              0x10D3
+#define E1000_DEVICE_82575EB             0x10A7 // TODO(gz): This cards needs more work
+#define E1000_DEVICE_82576EG             0x10C9 // TODO(gz): This cards needs more work
+#define E1000_DEVICE_I210                0x1533
+#define E1000_DEVICE_I350_EEPROM_LESS    0x151F
+#define E1000_DEVICE_I350_COPPER         0x1521
+#define E1000_DEVICE_I350_FIBER          0x1522
+#define E1000_DEVICE_I350_BACKPANE       0x1523
+#define E1000_DEVICE_I350_SGMII          0x1524
+#define E1000_DEVICE_I350_DUMMY          0x10A6
+#define E1000_DEVICE_82546GB_QUAD_COPPER_KSP3 0x10B5
+
+/**
+ * Initial default values
+ */
+
+#define E1000_DEFAULT_INT_THROTTLE_RATE 10
+#define E1000_INT_THROTTLE_RATE_DISABLED 0
+
+
+/**
+ * Group definitions for cards that share specification and quirks.
+ *
+ * e1000_82542 should be split into:
+ *   e1000_82542_rev_2_1 and e1000_82542_rev_2_2.
+ * This can be figured out reading the PCI bus.
+ */
+typedef enum {
+    e1000_undefined = 0,
+    e1000_82542,        /* revision 2.1 and 2.2 merged */
+    e1000_82543,
+    e1000_82544,
+    e1000_82540,
+    e1000_82545,
+    e1000_82545_rev_3,
+    e1000_82546,
+    e1000_82546_rev_3,
+    e1000_82541,
+    e1000_82541_rev_2,
+    e1000_82547,
+    e1000_82547_rev_2,
+    e1000_82563,
+    e1000_82571,
+    e1000_82572,
+    e1000_82573,
+    e1000_82574,
+    e1000_82575,
+    e1000_82576,
+    e1000_I210,
+    e1000_I350,
+    e1000_num_macs
+} e1000_mac_type_t;
+
+/**
+ * Hardware supported buffer sizes.
+ */
+typedef enum {
+    bsize_256 = 256,
+    bsize_512 = 512,
+    bsize_1024 = 1024,
+    bsize_2048 = 2048,
+    bsize_4096 = 4096,
+    bsize_8192 = 8192,
+    bsize_16384 = 16384
+} e1000_rx_bsize_t;
+
+
+typedef struct e1000_queue {
+    struct devq q;
+
+    e1000_mac_type_t mac_type;
+    e1000_t hw_device;
+    uint32_t pci_vendor, pci_deviceid, pci_bus, pci_device, pci_function;
+    char *name;
+    uint64_t mac_address;
+
+    volatile union rx_desc *receive_ring;
+    volatile struct tx_desc *transmit_ring;
+
+    int receive_buffers;
+    int transmit_buffers;
+
+    regionid_t region_id;
+    genpaddr_t region_base;
+    gensize_t  region_size;
+
+    unsigned receive_head, receive_tail;
+    unsigned transmit_head, transmit_tail;
+
+    unsigned interrupt_mode;
+    void (*isr)(void *);
+
+    bool extended_interrupts;
+    unsigned advanced_descriptors; // 0 - none, 1 - 82572/4, 3 - 82576/i210/i350
+} e1000_queue_t;
+
+typedef union {
+    uint16_t   vlan;
+    struct {
+        uint16_t vlan :12;
+        uint16_t cfi  :1;
+        uint16_t pri  :3;
+    } __attribute__((packed)) bits;
+} __attribute__((packed)) vlan_tag_t;
+
+
+union rx_desc {
+    uint64_t raw[2] __attribute__((packed));
+    struct {
+        uint64_t buffer_address;
+        struct {
+            uint16_t   length;
+            uint16_t   checksum;        /* reserved on: 82544GC/EI */
+            struct {
+                unsigned int   dd      :1;
+                unsigned int   eop     :1;
+                unsigned int   ixsm    :1;
+                unsigned int   vp      :1;
+                unsigned int   udpcs   :1;  /* reserved on: 8254x */
+                unsigned int   tcpcs   :1;
+                unsigned int   ipcs    :1;
+                unsigned int   pif     :1;
+            } __attribute__ ((packed)) status;
+
+            union {
+                uint8_t errors;
+                struct {
+                    uint8_t ce   :1;
+                    uint8_t seq  :1;        /* reserved on: 82541xx, 82547GI/EI, and 82540EP/EM only. */
+                    uint8_t res0 :1;        /* reserved on: 8254x */
+                    uint8_t cxe  :1;        /* 82544GC/EI only */
+                    uint8_t tcpe :1;
+                    uint8_t ipe  :1;
+                    uint8_t rxe  :1;
+                } __attribute__ ((packed)) bits;
+            } __attribute__ ((packed)) errors;
+            vlan_tag_t vlan;
+        } __attribute__ ((packed)) info;
+    } __attribute__ ((packed)) rx_read_format;
+} __attribute__ ((packed));
+
+
+struct tx_desc {
+    uint64_t buffer_address;
+    union {
+        uint64_t raw;
+        struct {
+            uint16_t data_len;
+            uint8_t cso;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t eop  :1;
+                    uint8_t ifcs :1;
+                    uint8_t ic   :1;
+                    uint8_t rs   :1;
+                    uint8_t rsv  :1;
+                    uint8_t dext :1;
+                    uint8_t vle  :1;
+                    uint8_t ide  :1;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) cmd;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t dd  :1;
+                    uint8_t ec  :1;
+                    uint8_t lc  :1;
+                    uint8_t res :5;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) stat_rsv;
+            uint8_t  css;
+            uint16_t special;
+        } __attribute__ ((packed)) legacy;
+
+        struct {
+            uint64_t data_len :20;
+            uint64_t dtyp     :4;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t eop  :1;
+                    uint8_t ifcs :1;
+                    uint8_t tse  :1;
+                    uint8_t rs   :1;
+                    uint8_t rsv  :1;
+                    uint8_t dext :1;
+                    uint8_t vle  :1;
+                    uint8_t ide  :1;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) dcmd;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t dd  :1;
+                    uint8_t res :7;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) stat_rsv;
+            union {
+                uint8_t  raw;
+                struct {
+                    uint8_t ixsm : 1;
+                    uint8_t txsm : 1;
+                    uint8_t  res : 6;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) popts;
+            vlan_tag_t vlan;
+        } __attribute__ ((packed)) extended_data;
+
+        struct {
+            uint16_t dtalen;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t rsv  :2;
+                    uint8_t mac  :2;
+                    uint8_t dtyp :4;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) dtyp;
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t eop  :1;
+                    uint8_t ifcs :1;
+                    uint8_t rsv1 :1;
+                    uint8_t rs   :1;
+                    uint8_t rsv2 :1;
+                    uint8_t dext :1;
+                    uint8_t vle  :1;
+                    uint8_t tse  :1;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) dcmd;
+            
+            union {
+                uint8_t raw;
+                struct {
+                    uint8_t dd   :1;
+                    uint8_t rsv1 :3;
+                    uint8_t idx  :3;
+                    uint8_t rsv2 :1;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) stat_idx;
+
+            union {
+                uint8_t raw[3];
+                struct {
+                    uint8_t ixsm : 1;
+                    uint8_t txsm : 1;
+                    uint8_t ipsec: 1;
+                    uint8_t rsv  : 3;
+                    uint32_t paylen:18;
+                } __attribute__ ((packed)) d;
+            } __attribute__ ((packed)) popts_paylen;
+        } __attribute__ ((packed)) advanced_data;
+    } __attribute__ ((packed)) ctrl;
+} __attribute__ ((packed));
+
+/*
+ * TCP/IP Context Descriptor Layout
+ *
+ * Provides access to enhanced checksum offload facility
+ * available in the Ethernet controllerfor TCP and UDP packets.
+ */
+union context_desc {
+    uint64_t raw;
+    struct {
+        uint8_t ipcss;
+        uint8_t ipcso;
+        uint16_t ipcse;
+        uint8_t tucss;
+        uint8_t tucso;
+        uint16_t tucse;
+        struct {
+            uint32_t paylen :20;
+            uint32_t dtype  :4;
+        } __attribute__ ((packed)) pd;
+
+        union {
+            uint8_t raw;
+            struct {
+                uint8_t tcp  :1;
+                uint8_t ip   :1;
+                uint8_t tse  :1;
+                uint8_t rs   :1;
+                uint8_t rsv  :1;
+                uint8_t dext :1;
+                uint8_t snap :1;
+                uint8_t ide  :1;
+            } __attribute__ ((packed)) d;
+        } __attribute__ ((packed)) tucmd;
+
+        union {
+            uint8_t raw;
+            struct {
+                uint8_t dd  :1;
+                uint8_t res :7;
+            } __attribute__ ((packed)) d;
+        } __attribute__ ((packed)) stat_rsv;
+
+        uint8_t hdrlen;
+        uint16_t mss;
+
+    } __attribute__ ((packed)) d;
+} __attribute__ ((packed));
+
+
+e1000_mac_type_t e1000_get_mac_type(uint32_t vendor, uint32_t device_id);
+char * e1000_mac_type_to_str(e1000_mac_type_t mt);
+
+#endif
index e23d801..83c70e2 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef QUEUE_INTERFACE_INTERNAL_H_
 #define QUEUE_INTERFACE_INTERNAL_H_ 1
 
-//#include <devif/queue_interface.h>
+#include <devif/queue_interface.h>
 struct region_pool;
 struct devq;
 
index 917f3e4..cc2db13 100644 (file)
@@ -8,7 +8,7 @@
  * your own version, link it in and in your cc.h put:
  *
  * \#define LWIP_CHKSUM your_checksum_routine
- * 
+ *
  * Or you can select from the implementations below by defining
  * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
  */
index ce2e3d2..0cbf25e 100644 (file)
@@ -3,7 +3,7 @@
  * User Datagram Protocol module\n
  * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n
  * See also @ref udp_raw
- * 
+ *
  * @defgroup udp_raw UDP
  * @ingroup callbackstyle_api
  * User Datagram Protocol module\n
index 8eb30a3..5ee101f 100644 (file)
@@ -10,7 +10,7 @@
 --
 --------------------------------------------------------------------------
 
-[ build library { 
+[ build library {
     target       = "net",
     cFiles       = [ "net.c", "netbufs.c",  "netif.c", "pbuf.c", "dhcp.c",
                      "net_filter.c", "arp.c" ],
     flounderExtraDefs = [ ("net_filter",["rpcclient"]) ],
     addLibraries = libDeps [ "lwip2", "devif", "devif_backend_idc",
                              "devif_backend_solarflare", "devif_backend_e10k",
-                             "devif_backend_loopback",
-                             "octopus", "octopus_parser" ] 
+                             "devif_backend_loopback",  "devif_backend_e1000",
+                             "octopus", "octopus_parser" ]
   },
-    
+
   build application {
     target       = "net_udp_echo",
     cFiles       = [ "test/udp_echo.c" ],
     addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
     addLibraries = libDeps [ "net" ]
   },
-    build application {
+  build application {
     target       = "net_arp",
     cFiles       = [ "test/arp.c" ],
     addIncludes  = [ "include", "/lib/lwip-2.0.2/src/include/" ],
     addLibraries = libDeps [ "net" ]
-  }  
+  }
 ]
index ce3729a..7abb448 100644 (file)
@@ -86,6 +86,23 @@ static errval_t create_driver_queue (struct net_state *st, uint64_t* queueid,
     return SYS_ERR_OK;
 }
 
+// cardname - "e1000:vendor:deviceid:bus:device:function"
+static errval_t create_e1000_queue(struct net_state *st, uint64_t *queueid,
+                                   struct devq **retqueue)
+{
+    if (st->cardname[5] != ':') {
+        return SYS_ERR_OK;
+    }
+    uint32_t vendor, deviceid, bus, device, function;
+    unsigned parsed = sscanf(st->cardname + 6, "%x:%x:%x:%x:%x", &vendor,
+                             &deviceid, &bus, &device, &function);
+    if (parsed != 5) {
+        return SYS_ERR_OK;
+    }
+
+    return e1000_queue_create((struct e1000_queue**)retqueue, vendor, deviceid,
+                              bus, device, function, 1, int_handler);
+}
 
 static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
                                    struct devq **retqueue)
@@ -99,7 +116,7 @@ static errval_t create_e10k_queue (struct net_state *st, uint64_t* queueid,
     return err;
 }
 
-static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid, 
+static errval_t create_sfn5122f_queue (struct net_state *st, uint64_t* queueid,
                                        struct devq **retqueue)
 {
     errval_t err;
@@ -119,7 +136,8 @@ struct networking_card
     queue_create_fn createfn;
 } networking_cards [] = {
     { "loopback", create_loopback_queue},
-    { "e1000", create_driver_queue},
+    { "driver", create_driver_queue},
+    { "e1000", create_e1000_queue},
     { "e10k", create_e10k_queue},
     { "sfn5122f", create_sfn5122f_queue},
     { NULL, NULL}
@@ -204,7 +222,7 @@ static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *
     NETDEBUG("initializing networking with devq=%p, flags=%" PRIx32 "...\n", q,
              flags);
 
-    if(st->initialized) {
+    if (st->initialized) {
         debug_printf("WARNING. initialize called twice. Ignoring\n");
         return SYS_ERR_OK;
     }
@@ -218,6 +236,13 @@ static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *
     /* associate the net state with the device queue */
     devq_set_state(st->queue, st);
 
+    /* create buffers and add them to the interface*/
+    err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
+                             NETWORKING_BUFFER_SIZE, &st->pool);
+    if (err_is_fail(err)) {
+        //net_if_destroy(&st->netif);
+        goto out_err1;
+    }
 
     /* initialize the device queue */
     NETDEBUG("initializing LWIP...\n");
@@ -246,14 +271,6 @@ static errval_t networking_init_with_queue_st(struct net_state *st,struct devq *
     NETDEBUG("setting default netif...\n");
    // netif_set_default(&st->netif);
 
-    /* create buffers and add them to the interface*/
-    err = net_buf_pool_alloc(st->queue, NETWORKING_BUFFER_COUNT,
-                             NETWORKING_BUFFER_SIZE, &st->pool);
-    if (err_is_fail(err)) {
-        //net_if_destroy(&st->netif);
-        goto out_err1;
-    }
-
     NETDEBUG("adding RX buffers\n");
     for (int i = 0; i < NETWORKING_BUFFER_RX_POPULATE; i++) {
         struct pbuf *p = net_buf_alloc(st->pool);
@@ -434,11 +451,11 @@ errval_t networking_poll(void)
  * @param tcp       should TCP packets be filtered or UPD
  * @param src_ip    source ip of the filter, 0 for wildcard
  * @param src_port  source port of the filter, 0 for wildcard
- * @param dst_port  destination port fo the filter       
+ * @param dst_port  destination port fo the filter
  *
  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
  */
-errval_t networking_install_ip_filter(bool tcp, ip_addr_t* src, 
+errval_t networking_install_ip_filter(bool tcp, ip_addr_t* src,
                                       uint16_t src_port, uint16_t dst_port)
 {
     errval_t err;
@@ -478,11 +495,11 @@ errval_t networking_install_ip_filter(bool tcp, ip_addr_t* src,
  * @param tcp       should TCP packets be filtered or UPD
  * @param src_ip    source ip of the filter, 0 for wildcard
  * @param src_port  source port of the filter, 0 for wildcard
- * @param dst_port  destination port fo the filter       
+ * @param dst_port  destination port fo the filter
  *
  * @return SYS_ERR_OK on success, NET_FILTER_ERR_* on failure
  */
-errval_t networking_remove_ip_filter(bool tcp, ip_addr_t* src, 
+errval_t networking_remove_ip_filter(bool tcp, ip_addr_t* src,
                                      uint16_t src_port, uint16_t dst_port)
 {
 
index ac35924..8d04e57 100644 (file)
@@ -45,7 +45,7 @@ static void bind_cb(void *st, errval_t err, struct net_filter_binding *b)
 
 
 /** Open connection to management interface */
-static errval_t connect_to_net_filter(struct net_filter_state* st, 
+static errval_t connect_to_net_filter(struct net_filter_state* st,
                                       const char *dev_name)
 {
     errval_t r;
@@ -135,9 +135,9 @@ static bool is_reachable(struct net_filter_ip* filt)
  *
  * @return SYS_ERR_OK on success, error on failure
  */
-errval_t net_filter_init(struct net_filter_state** st, 
+errval_t net_filter_init(struct net_filter_state** st,
                          const char* cardname)
-{   
+{
     errval_t err;
 
     struct net_filter_state* tmp = calloc(1, sizeof(struct net_filter_state));
@@ -155,7 +155,7 @@ errval_t net_filter_init(struct net_filter_state** st,
 
 
 /**
- * @brief Installs an L3/L4 filter in the hardware filter 
+ * @brief Installs an L3/L4 filter in the hardware filter
  *        tables
  *
  * @param st    net filter state
@@ -163,7 +163,7 @@ errval_t net_filter_init(struct net_filter_state** st,
  *
  * @return SYS_ERR_OK on success, error on failure
  */
-errval_t net_filter_ip_install(struct net_filter_state* st, 
+errval_t net_filter_ip_install(struct net_filter_state* st,
                                struct net_filter_ip* filt)
 {
 
@@ -174,7 +174,7 @@ errval_t net_filter_ip_install(struct net_filter_state* st,
     struct net_filter_ele* cur = st->filters_ip.start;
     struct net_filter_ele* prev = NULL;
 
-    /* go through linked list and find last element 
+    /* go through linked list and find last element
      (and check if filter is already installed) */
     if (cur == NULL) {
         st->filters_ip.start = malloc(sizeof(struct net_filter_ele));
@@ -203,7 +203,7 @@ errval_t net_filter_ip_install(struct net_filter_state* st,
     cur->filter.ip.qid = filt->qid;
     cur->filter.ip.type = filt->type;
     cur->next = NULL;
-    cur->prev = prev;    
+    cur->prev = prev;
 
     st->filters_ip.num_ele++;
 
@@ -226,7 +226,7 @@ errval_t net_filter_ip_install(struct net_filter_state* st,
 
 
 /**
- * @brief Removes an L3/L4 filter in the hardware filter 
+ * @brief Removes an L3/L4 filter in the hardware filter
  *        tables
  *
  * @param st    net filter state
@@ -234,7 +234,7 @@ errval_t net_filter_ip_install(struct net_filter_state* st,
  *
  * @return SYS_ERR_OK on success, error on failure
  */
-errval_t net_filter_ip_remove(struct net_filter_state* st, 
+errval_t net_filter_ip_remove(struct net_filter_state* st,
                               struct net_filter_ip* filt)
 {
 
@@ -279,7 +279,7 @@ errval_t net_filter_ip_remove(struct net_filter_state* st,
         prev->next = cur->next;
         if (cur->next != NULL) { // check if last
             cur->next->prev = prev;
-        } 
+        }
     } else {
         st->filters_ip.start = cur->next;
     }
@@ -304,4 +304,3 @@ errval_t net_filter_mac_remove(struct net_filter_state* st,
 {
    USER_PANIC("NYI \n");
 }
-
index f3cc86c..5fb4778 100644 (file)
@@ -541,5 +541,3 @@ errval_t net_if_poll_all(void)
     }
     return SYS_ERR_OK;
 }
-
-
index 2d91207..c8dfe4e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * @brief 
+ * @brief
  *  net.h
  */
 
@@ -24,6 +24,7 @@
 #include <devif/backends/loopback_devif.h>
 #include <devif/backends/net/sfn5122f_devif.h>
 #include <devif/backends/net/e10k_devif.h>
+#include <devif/backends/net/e1000_devif.h>
 
 #include <lwip/netif.h>
 
index c61f7bd..cffc65f 100644 (file)
@@ -522,8 +522,6 @@ pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_cust
 void
 pbuf_realloc(struct pbuf *p, u16_t new_len)
 {
-    return;
-#if 0
   struct pbuf *q;
   u16_t rem_len; /* remaining length */
   s32_t grow;
@@ -540,10 +538,6 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
     return;
   }
 
-  p->len = new_len;
-  p->tot_len = new_len;
-  return;
-
   /* the pbuf chain grows by (new_len - p->tot_len) bytes
    * (which may be negative in case of shrinking) */
   grow = new_len - p->tot_len;
@@ -588,7 +582,6 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
   }
   /* q is last packet in chain */
   q->next = NULL;
-#endif
 }
 
 
@@ -705,8 +698,3 @@ pbuf_free(struct pbuf *p)
   /* return number of de-allocated pbufs */
   return count;
 }
-
-
-
-
-
index 6cdec30..6414b8f 100644 (file)
@@ -5,7 +5,7 @@
     core_offset,        % Core offset where to start the drivers (multi instance)
     multi_instance,     % Allow multi instances of the driver
     interrupt_load,     % Expected Interrupt load
-    interrupt_model,    % List of supported int models. legacy,msi,msix 
+    interrupt_model,    % List of supported int models. legacy,msi,msix
     platforms,          % List of architectures the driver runs on
     priority            % When more than one driver matches, the higher prio gets started
 )).
@@ -158,7 +158,7 @@ int_model_enum(msix, 3).
 get_interrupt_model(IntModels, Model) :-
     ((var(IntModels) -> ModelAtom = none);
     IntModels = [ModelAtom | _]),
-    int_model_enum(ModelAtom, Model). 
+    int_model_enum(ModelAtom, Model).
 
 find_pci_driver(PciInfo, DriverInfo) :-
     PciInfo = pci_card{vendor:VId, device: DId, function: Fun, subvendor: SVId,
@@ -178,7 +178,7 @@ find_pci_driver(PciInfo, DriverInfo) :-
 
 find_cpu_driver(ApicId, DriverInfo) :-
     cpu_driver{binary: Binary, platforms: Platforms},
-    % TODO: In future use ApicId to select cpu driver that has listed the correct 
+    % TODO: In future use ApicId to select cpu driver that has listed the correct
     % platform
     DriverInfo = driver(Binary).
 
@@ -186,4 +186,3 @@ find_ioapic_driver(IOApicId, DriverInfo) :-
     bus_driver{binary: Binary, core_hint: Core, platforms: Platforms},
     % TODO: Select appropriate Core based on core_hint, platform, ioapic id
     DriverInfo = driver(Core, Binary).
-