T308: Improve support for Intel 82574 gbe network cards
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 14 Oct 2016 15:59:42 +0000 (17:59 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 14 Oct 2016 16:11:52 +0000 (18:11 +0200)
It turns out the card is too similiar to give it an extra driver, remove
the e1000e binary and improve e1000n instead. e1000n needs refactoring.
The driver does not hang on hw reset (on the 82574) and the interrupt
handling is correct enough to let irqtest pass (with legacy interrupts).

Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

devices/e1000.dev
devices/e1000e.dev [deleted file]
usr/drivers/e1000/e1000n.c
usr/drivers/e1000/e1000n.h
usr/drivers/e1000/e1000n_helpers.c
usr/drivers/e1000/e1000n_hwinit.c
usr/drivers/e1000e/Hakefile [deleted file]
usr/drivers/e1000e/e1000e.c [deleted file]
usr/drivers/e1000e/e1000e_debug.h [deleted file]
usr/skb/programs/device_db.pl
usr/skb/programs/device_db_irqtest.pl

index b9b6fc1..026359d 100644 (file)
@@ -195,6 +195,27 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
     _            12 mbz;
   };  
 
+  register eec_82574 rw also addr(base, 0x0010) "EEPROM/Flash control for 82574" {
+    ee_sk         1 "Clock input to EEPROM";
+    ee_cs         1 "Chip select to EEPROM";
+    ee_di         1 "Data input to EEPROM";
+    ee_do         1 "Data output bit from EEPROM";
+    fwe           2 type(flashenable) "Flash write enable control";
+    ee_req        1 "Request EEPROM access";
+    ee_gnt        1 "Grant EEPROM access";
+    ee_pres       1 "EEPROM present";
+    auto_rd       1 "EEPROM Auto Read Done";
+    _             1 mbz;
+    nv_size       4 "NVM Size";
+    nv_adds       2 "NVM Address size";
+    _             3 mbz;
+    audpen        1 "Autonomous flash update";
+    _             1 mbz;
+    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" {
@@ -332,7 +353,7 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   };
 
   // 13.3.17
-  register ufuse3 ro addr(base, 0x00f0) "ULT Fuse register 3" {
+  register ufuse3 ro also addr(base, 0x00f0) "ULT Fuse register 3" {
     drred      15 "Data RAM redundancy fuses";
     crred      13 "Code RAM redundancy fuses";
     enad       1  "Enable Data RAM redundancy fuses";
@@ -532,6 +553,12 @@ device e1000 lsbfirst ( addr base ) "Intel e1000 Gigabit Ethernet" {
   // 13.3.32
   register iam rw addr(base, 0x00e0) "Interrupt ack auto mask" type(intreg);
 
+  // 82574: 10.2.4.3
+  regarray eitr_82574 addr(base, 0x00e8)[4;0x4] "Extended Interrupt Throttle" {
+    interval   16 "Minimum inter-interrupt interval (x256ns)";
+    _              16 mbz;
+  };
+
   regarray eitr addr(base, 0x1680)[9;0x4] "Extended Interrupt Throttle" {
     _         2 mbz;
     interval 13 "Interval";
diff --git a/devices/e1000e.dev b/devices/e1000e.dev
deleted file mode 100644 (file)
index e90729d..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- */
-
-/*
- * e1000e.dev
- *
- * DESCRIPTION: Intel e1000e family Gigabit Ethernet NICs
- * 
- * Source of this interface is the
- * Intel 82574 GbE Controller Family Datasheet
- * The card is similar but not compatible to the e1000.
- */
-
-device e1000e lsbfirst ( addr base ) "Intel e1000e Gigabit Ethernet" {
-
-  /************************************
-   * General registers
-   ***********************************/
-
-  // 13.3.1
-  constants linkspeed "Link speed" {
-    mb10       = 0b00 "10Mb/s";
-    mb100      = 0b01 "100Mb/s";
-    mb1000     = 0b10 "1Gb/s";
-    mb_notused = 0b11 "1Gb/s";
-  };
-
-
-  // 10.2.2.1
-  register ctrl rw addr(base, 0x0000) "Device control" {
-    fd         1 "full-duplex";
-    _          1 mbz;
-    gio_md     1 "GIO master disable";
-    _       1 mb1; 
-    _          1 mbz;
-    asde       1 "Auto-Speed Detection Enable";
-    slu                1 "Set link up";
-    _          1 mbz;
-    speed      2 type(linkspeed) "Speed selection";
-    _          1 mbz;
-    frcspd     1 "Force speed";
-    frcdplx    1 "Force duplex";
-    _          7 mbz;
-    advd3wuc   1 "D3cold wakeup capability";
-    _       5 mbz;
-    rst                1 "Device reset";
-    rfce       1 "Receive flow control enable";
-    tfce       1 "Transmit flow control enable";
-    _          1 mbz;
-    vme                1 "VLAN mode enable";
-    phy_rst    1 "PHY reset";
-  };
-
-  register ctrldup rw addr(base, 0x0004) "Device Control Duplicate (Shadow)" {
-    fd         1 "full-duplex";
-    _          1 mbz;
-    gio_md     1 "GIO master disable";
-    _       1 mb1; // must be one
-    _          1 mbz;
-    asde       1 "Auto-Speed Detection Enable";
-    slu                1 "Set link up";
-    _          1 mbz;
-    speed      2 type(linkspeed) "Speed selection";
-    _          1 mbz;
-    frcspd     1 "Force speed";
-    frcdplx    1 "Force duplex";
-    _          7 mbz;
-    advd3wuc   1 "D3cold wakeup capability";
-    _       5 mbz;
-    rst                1 "Device reset";
-    rfce       1 "Receive flow control enable";
-    tfce       1 "Transmit flow control enable";
-    _          1 mbz;
-    vme                1 "VLAN mode enable";
-    phy_rst    1 "PHY reset";
-  };
-
-  constants lanid "LAN ID" {
-    lan_a       = 0b00 "LAN A";
-    lan_b       = 0b01 "LAN B";
-    lan_not_u1  = 0b10 "LAN ID not used";
-    lan_not_u2  = 0b11 "LAN ID not used";
-  };
-  constants mac_mask "LAN MAC MASK" {
-    lan_b_mask  = 0x0100 "LAN B mask";
-  };
-
-  // 10.2.2.2
-  register status ro addr(base, 0x0008) "Device status" {
-    fd         1 "Link full duplex configuration";
-    lu         1 "Link up";
-    func_id    2 "Function ID";
-    txoff      1 "Transmission paused";
-    tbimode    1 "TBI mode";
-    speed      2 type(linkspeed) "Link speed setting";
-    asdv       2 type(linkspeed) "Auto speed detection value";
-    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;   
-    gio_mes     1 "GIO master enable status";
-    dev_rst_set 1 "Device reset set";
-    pf_rst_done 1 "Software Rest or device reset completed";
-    _          10 mbz;
-  };
-  
-
-  // 13.3.3
-  constants flashenable "Flash write enable control" {
-    flash_erase                = 0b00 "Flash erase";
-    flash_wr_disable   = 0b01 "Flash writes discarded";
-    flash_wr_enable    = 0b10 "Flash writed enabled";
-  };
-
-  constants eeaddrsize "EEPROM address size" {
-    bits8or9   = 0 "8- and 9-bit";
-    bits16     = 1 "16-bit";
-  };
-
-  constants nvmtype "Non-volatile memory type" {
-    eeprom     = 0b00 "EEPROM";
-    saflash    = 0b01 "Stand-alone Flash";
-    spiflash   = 0b10 "Shared SPI Flash";
-    sio                = 0b11 "SIO";
-  };
-
-  register eecd rw addr(base, 0x0010) "EEPROM/Flash control" {
-    ee_sk      1 "Clock input to EEPROM";
-    ee_cs      1 "Chip select to EEPROM";
-    ee_di      1 "Data input to EEPROM";
-    ee_do      1 "Data output bit from EEPROM";
-    fwe                2 type(flashenable) "Flash write enable control";
-    ee_req     1 "Request EEPROM access";
-    ee_gnt     1 "Grant EEPROM access";
-    ee_pres    1 "EEPROM present";
-
-    auto_rd 1 "NVM Auto Read Done";
-    _       1 mbz;
-    nv_size 4 "NVM Size";
-    nvadds  2 "NVM Address Size";
-    _       3 mbz;
-    audpen  1 "Enable autonomous flash update";
-    _       1 mbz;
-    sec1val 1 "Sector 1 valid";
-    nvmtype 1 "NVM Type";
-    _       8 mbz;
-  };
-  
-  // 10.2.2.4
-  register eerd rw addr(base, 0x0014) "EEPROM read" {
-    start       1 "Start read";
-    done        1 ro "Read done";
-    addr        14 "Read address";
-    data        16 "Read data";   
-  };
-
-
-  // 10.2.2.5
-  register ctrlext rw addr(base, 0x0018) "Extended device control" {
-    _          12 mbz;
-    asdchk     1 "Auto-speed-detection check";
-    ee_rst     1 "EEPROM reset";
-    _          1 mbz;
-    spd_byps   1 "Speed select bypass";
-    _          1;
-    rodis      1 "Relaxed ordering disabled";
-    _      1 mbz;  
-    dmadge     1 "DMA dynamic gating enable";
-    phypde     1 "PHY power down enable";
-    _          1;
-    txlsflow 1 "Tx LS Flow";
-    txls    1 "TxLS";
-    eiame      1 "Extended interrupt acknowledge auto-mask enable";
-    _       2 mbz;
-    iame       1 "Interrupt acknowledge auto-mask enable";
-    drv_load   1 "Driver loaded";
-    int_tca    1 "Timers clear enable";
-    _       1 mbz;
-    pbasupport 1 "PBA support";
-  };
-
-  // 10.2.2.6
-  register fla rw addr(base, 0x001c) "Flash access" {
-    fl_nvm_sk   1 "Clock input to the Flash";
-    fl_ce       1 "Chip select input to the Flash";
-    fl_si       1 "Data input to the Flash";
-    fl_so       1 "X Data output bit from the Flash";
-    fl_req      1 "Request Flash Access";
-    fl_gnt      1 "Grant Flash Access";
-    fl_dev_er_ind 1 "Device erase initiated";
-    fl_sec_er_ind 1 "Sector erase initiated";
-    fl_wr_ind   1 "Write initiated";
-    sw_wr_done  1 "Last write done";
-    _           20 mbz;
-    fl_busy     1 "Flash Busy";
-    fl_er       1 "Flash Erase Command";
-  };
-
-  // 10.2.2..7
-  constants phyop "PHY register opcode" {
-    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;
-  };
-  
-  // There are a lot of PHY registers, all accessed through the MDIC.
-  // We don't yet list them here. 
-
-  // 10.2.2.8-9
-  constants fca "Flow control address" {
-    fca_lo     = 0x0c28001;
-    fca_hi     = 0x0000100;
-  };
-  register fcal rw addr(base, 0x0028) "Flow control address low" type(uint32);
-  register fcah rw addr(base, 0x002C) "Flow control address low" type(uint32);
-  
-  // 10.2.2.10
-  constants fctval "Flow control type" {
-    fct_val = 0x0008808;
-  };
-  register fct rw addr(base, 0x0030) "Flow control type" type(uint32);
-  
-  // 10.2.2.11
-  constants vet_val "VLAN ether type value" {
-    vlan_type  = 0x0008100;
-  };
-  register vet rw addr(base, 0x0038) "VLAN Ether type" type(uint32);
-  
-  // 10.2.2.12
-  register fcttv rw addr(base, 0x0170) "Flow control transmit timer value" {
-    ttv                16 "Transmit timer value";
-    _          16 mbz;
-  };
-  
-  // 10.2.2.14
-  constants ledmode "LED output mode" {
-    link_10_100                = 0b0000 "Either 10 or 100 Mbs link established";
-    link_100_1000      = 0b0001 "Either 100 or 1000 Mbs link established";
-    link_up            = 0b0010 "Any speed link established";
-    filter_activity    = 0b0011 "Packets passing MAC filtering";
-    link_activity      = 0b0100 "No transmit or receive activity";
-    link_10            = 0b0101 "10 Mbs link established";
-    link_100           = 0b0110 "100 Mbs link established";
-    link_1000          = 0b0111 "1000 Mbs link established";
-    full_duplex                = 0b1001 "Link configured for full-duplex";
-    collision          = 0b1010 "Collision is observed";
-    activity           = 0b1011 "Link established and packets sent or revd";
-    bus_size           = 0b1100 "Controller detects 1 PCIe lane conn.";
-    paused             = 0b1101 "Transmitter is flow controlled";
-    led_on             = 0b1110 "Always on";
-    led_off            = 0b1111 "Always off";
-  };
-  constants blmode "LED blink mode" {
-    ms200              = 0 "200ms on, 200ms off";
-    ms83               = 1 "83ms on, 83 ms off";
-  };
-  register ledctl rw addr(base, 0x0e00) "LED control" {
-    led0_mode  4 type(ledmode) "LED0/LINK# mode";
-    _          1 mbz;
-    global_blink_mode 1 type(blmode) "Global blink mode";
-    led0_ivrt  1 "LED0 invert";
-    led0_blink 1 "LED0 blink";
-
-    led1_mode  4 type(ledmode) "LED1/LINK# mode";
-    _          1 mbz;
-    led1_blink_mode 1 type(blmode) "Global blink mode";
-    led1_ivrt  1 "LED1 invert";
-    led1_blink 1 "LED1 blink";
-
-    led2_mode  4 type(ledmode) "LED2/LINK# mode";
-    _          1 mbz;
-    led2_blink_mode 1 type(blmode) "Global blink mode";
-    led2_ivrt  1 "LED2 invert";
-    led2_blink 1 "LED2 blink";
-    _       8 mbz;
-  };    
-
-  // 10.2.2.15
-  register extcnf_ctrl rw addr(base, 0x0f00) "Extended config control" {
-    _          3 mbz;
-    _      1 mb1;
-    _       1 mbz;
-    mdio_swown 1 "MDIO software ownership (ro)";
-    mdio_hwown 1 "MDIO hoftware ownership (ro)";
-    mdio_mngown        1 "MDIO MNG ownership";
-    _          24 mbz;
-  };
-
-  // 10.2.2.16
-  register extcnf_size rw addr(base, 0x0f08) "Extended config size" {
-    phy_len    8 "Extended PHY configuration area length";
-    dock_len   8 "Extended dock configuration area length";
-    _          8 mbz;
-    _          8;
-  };
-  
-  // 10.2.2.17
-  register pba rw addr(base, 0x1000) "Packet buffer allocation" {
-    rxa                16 "Rx packet buffer allocation in KB";
-    txa                16 "Tx packet buffer allocation in KB";
-  };
-  
-  // 10.2.2.18
-  register eemngctl ro addr(base, 0x1010) "MNG EEPROM control" {
-    addr    15 "Address";
-    start   1 "Start";
-    write   1 "Write";
-    eebusy  1 "EPROM Busy";
-    _       1 mbz;
-    ee_trans_e  1 "Transaction";
-    _       11 mbz;
-    done    1 "Transaction Done";
-  };
-
-
-  /************************************
-   * Interrupt registers
-   ***********************************/
-
-  // 10.2.3.13
-  register pbaclr rw addr(base, 0x5B68) "MSI-x PBA Clear" {
-    penbit 5 "MSI-x Pending bit clear";
-    _      27 mbz;
-  };
-
-  // 10.2.4.1
-  regtype intreg "Interrupt register format" {
-    txdw       1 "Transmit descriptor written back";
-    txqe       1 "Transmit queue empty";
-    lsc                1 "Link status change";
-    _      1 mbz;
-    rxdmt0     1 "Receive descriptor minimum threshold reached";
-    _          1;
-    rxo                1 "Receiver overrun";
-    rxt0       1 "Receiver timer interrupt";
-    _          1;
-    mdac       1 "MDI/O access complete";
-    _          5 mbz;
-    txd_low 1 "TX desc low threshold hit";
-    srpd       1 "Small receive packet detected";
-    ack                1 "Receive ack frame detected";
-    mng                1 "Manageability event";
-    _       1 mbz;
-    rx_q0   1 "Rx Queue 0 Interrupt"; 
-    rx_q1   1 "Rx Queue 1 Interrupt"; 
-    tx_q0   1 "Rx Queue 0 Interrupt"; 
-    tx_q1   1 "Rx Queue 1 Interrupt"; 
-    other   1 "Other interrupt";
-    _       6 mbz;
-    int_asserted 1 "Interrupt asserted";
-  };
-
-  // 10.2.4.1
-  register icr ro addr(base, 0x00c0) "Interrupt cause read" type(intreg);
-
-  // 10.2.4.2
-  register itr rw addr(base, 0x00c4) "Interrupt throttling rate" {
-    interval   16 "Minimum inter-interrupt interval (x256ns)";
-    _              16 mbz;
-  };
-
-  // 10.2.4.3
-  regarray eitr addr(base, 0x00e8)[4;0x4] "Extended Interrupt Throttle" {
-    interval   16 "Minimum inter-interrupt interval (x256ns)";
-    _              16 mbz;
-  };
-  
-  // 10.2.4.4
-  register ics wo addr(base, 0x00c8) "Interrupt cause write" type(intreg);
-  
-  // 10.2.4.5
-  register ims rw addr(base, 0x00d0) "Interrupt mask set/read" type(intreg);
-  
-  // 10.2.4.6
-  register imc wo addr(base, 0x00d8) "Interrupt mask clear" type(intreg);
-
-  // 10.2.4.7
-  register eiac rw addr(base, 0x00dc) "Ext Interrupt auto clear" {
-    _   20 mbz;
-    value 5 "Auto clear bits for the corresponding bits of ICR";
-    _   7 mbz;
-  };
-
-  // 10.2.4.8
-  register iam rw addr(base, 0x00e0) "Interrupt ack auto mask" type(intreg);
-
-  // 10.2.4.9
-  // This maps internal int causes to an entry in the MSIx-vec table
-  register ivar rw addr(base, 0x00e4) "Interrupt vector allocation register" {
-    int_alloc0      3 "RxQ0 interrupt";
-    int_alloc0_en   1 "RxQ0 int enable";
-    int_alloc1      3 "RxQ1 interrupt";
-    int_alloc1_en   1 "RxQ1 int enable";
-    int_alloc2      3 "TxQ0 interrupt";
-    int_alloc2_en   1 "TxQ0 int enable";
-    int_alloc3      3 "TxQ1 interrupt";
-    int_alloc3_en   1 "TxQ1 int enable";
-    int_alloc4      3 "Other cause interrupt";
-    int_alloc4_en   1 "Other cause int enabled";
-    _               11 mbz;
-    int_on_all_wb   1 "Interrupt on every write back";
-  };
-
-
-  // TODO: All receive and send registers
-
-
-};
index 11aeaa9..8990f19 100644 (file)
@@ -972,6 +972,8 @@ int e1000n_driver_init(int argc, char **argv)
         mac_type = e1000_get_mac_type(vendor, deviceid);
     }
 
+    E1000_DEBUG("mac_type is: %s\n", e1000_mac_type_to_str(mac_type));
+
     /* Setup known device info */
     e1000_device.device = &e1000;
     e1000_device.mac_type = mac_type;
index f54b258..9cccb2e 100644 (file)
 #define E1000_DEVICE_I350_DUMMY          0x10A6
 #define E1000_DEVICE_82546GB_QUAD_COPPER_KSP3 0x10B5
 
+/**
+ * Initial default values
+ */
+
+#define E1000_DEFAULT_INT_THROTTLE_RATE 5580
+#define E1000_INT_THROTTLE_RATE_DISABLED 0
+
 
 /**
  * Group definitions for cards that share specification and quirks.
@@ -172,11 +179,13 @@ typedef struct {
 
 
 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);
 bool e1000_supported_device(uint32_t vendor, uint32_t device_id);
 bool e1000_link_up_led_status(e1000_device_t *dev);
 bool e1000_check_link_up(e1000_device_t *dev);
 bool e1000_auto_negotiate_link(e1000_device_t *dev);
 void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap);
+void e1000_set_interrupt_throttle(e1000_device_t *dev, uint16_t rate);
 void e1000_hwinit(e1000_device_t *device, struct device_mem *bar_info,
                   int nr_allocated_bars,
                   volatile struct tx_desc **transmit_ring,
index dd20544..c78c9d4 100644 (file)
@@ -114,6 +114,35 @@ e1000_mac_type_t e1000_get_mac_type(uint32_t vendor, uint32_t device_id)
     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];
+};
+
 
 /*****************************************************************
  * allocate a single frame, mapping it into our vspace with given
index e6b5db9..dcf5c5d 100644 (file)
@@ -66,10 +66,12 @@ static errval_t e1000_read_eeprom(e1000_device_t *dev, uint64_t offset,
 {
     int timeout = 1000;
 
-    /* Make shore there are no direct access requests on
+    /* Make sure there are no direct access requests on
      * devices that support this.
      */
-    if (dev->mac_type != e1000_82544) {
+    if (dev->mac_type == e1000_82574){
+        e1000_eec_ee_req_wrf(dev->device, 1);
+    } else if (dev->mac_type != e1000_82544) {
         e1000_eecd_ee_req_wrf(dev->device, 1);
     }
 
@@ -80,7 +82,7 @@ static errval_t e1000_read_eeprom(e1000_device_t *dev, uint64_t offset,
     }
 
     /* EEPROM present */
-    // TODO(gz): Why does e1000 82574 have ee_pres == 0?
+    // TODO(gz): Why does e1000 82574 have ee_pres == 0? LH: QEMUs 82574 has ee_pres=1?
     if (e1000_eecd_ee_pres_rdf(dev->device) ||
             dev->mac_type == e1000_82574) {
         e1000_eerd_ms_t eerd_ms = 0;
@@ -143,8 +145,22 @@ static errval_t e1000_get_auto_rd_done(e1000_device_t *dev)
 {
     uint16_t data;
     errval_t err;
-
-    err = e1000_read_eeprom(dev, 0, &data);
+    
+    if(dev->mac_type == e1000_82574){
+        // For the 82574  we just check the auto rd flag without issuing
+        // an eeprom read. (FreeBSD does it like this)
+        int timeout = 1000;
+        while(timeout-- > 0){
+            if(e1000_eec_82574_auto_rd_rdf(dev->device)){
+                return SYS_ERR_OK;
+            }
+            usec_delay(10);
+        }
+        E1000_DEBUG("Timeout reached while waiting for auto_rd_done");
+        return 1;
+    } else {
+        err = e1000_read_eeprom(dev, 0, &data);
+    }
 
     /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
      * Need to wait for PHY configuration completion before accessing NVM
@@ -235,6 +251,22 @@ static int e1000_reset(e1000_device_t *dev)
         }
     }
 
+    if(dev->mac_type == e1000_82574){
+        // 82574: Must poll on GIO Master Enable Status in status register
+        E1000_DEBUG("Disabling GIO management.\n");
+        e1000_ctrl_gio_md_wrf(dev->device, 1);
+
+        timeout = 1000;
+        do {
+            usec_delay(10);
+        } while (e1000_status_gio_mes_rdf(dev->device) && 0 < timeout--);
+
+        if (timeout <= 0) {
+            E1000_DEBUG("Error: Failed to disable GIO management.\n");
+            // return -1;
+        }
+    }
+
     if (dev->mac_type == e1000_I350) {
         E1000_DEBUG("Disabling GIO management.\n");
         e1000_ctrl_gio_md_wrf(dev->device, 1);
@@ -255,13 +287,19 @@ static int e1000_reset(e1000_device_t *dev)
 
     /* Must acquire MDIO ownership before MAC reset
      * Ownership defaults to firmware after a reset */
-    if (dev->mac_type == e1000_82573) {
+    int mdio_acquired = false;
+    if (dev->mac_type == e1000_82573 || dev->mac_type == e1000_82574) {
         timeout = 1000;
         do {
             e1000_extcnf_ctrl_mdio_swown_wrf(dev->device, 1);
             usec_delay(200);
         } while (e1000_extcnf_ctrl_mdio_swown_rdf(dev->device) == 0
                  && 0 < timeout--);
+        if(timeout > 0){
+            mdio_acquired = true;
+        } else {
+            E1000_DEBUG("Could not acquire MDIO software ownership.\n");
+        }
     }
 
     E1000_DEBUG("Resetting device.\n");
@@ -296,6 +334,12 @@ static int e1000_reset(e1000_device_t *dev)
             E1000_DEBUG("Error: Failed to reset device.\n");
         }
         break;
+
+    case e1000_82574:
+        e1000_ctrl_rst_wrf(dev->device, 1);
+        usec_delay(10);
+        break;
+
     default:
         e1000_ctrl_rst_wrf(dev->device, 1);
 
@@ -311,6 +355,23 @@ static int e1000_reset(e1000_device_t *dev)
         break;
     }
 
+    /*
+     * If acquired, release mdio ownership
+     */ 
+    if (mdio_acquired) {
+        timeout = 1000;
+        do {
+            e1000_extcnf_ctrl_mdio_swown_wrf(dev->device, 0);
+            usec_delay(200);
+        } while (e1000_extcnf_ctrl_mdio_swown_rdf(dev->device) == 1
+                 && 0 < timeout--);
+        if(timeout > 0){
+            mdio_acquired = 0;
+        } else {
+            E1000_DEBUG("Could not release MDIO software ownership.\n");
+        }
+    }
+
 
     /* After MAC reset, force reload of EEPROM to restore power-on settings to
      * device.  Later controllers reload the EEPROM automatically, so just wait
@@ -332,6 +393,7 @@ static int e1000_reset(e1000_device_t *dev)
         usec_delay(20000);
         break;
     case e1000_82573:
+    case e1000_82574:
         if (e1000_is_onboard_nvm_eeprom(dev) == false) {
             usec_delay(100);
             e1000_ctrlext_ee_rst_wrf(dev->device, 1);
@@ -653,6 +715,38 @@ static void e1000_configure_rx(e1000_device_t *dev)
     e1000_set_rxbsize(dev, dev->rx_bsize);
 }
 
+/*
+ * Set interrupt throttle for all interrupts
+ */
+void e1000_set_interrupt_throttle(e1000_device_t *dev, uint16_t rate){
+        /* 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
+         */
+        if (dev->mac_type == e1000_82575
+            || dev->mac_type == e1000_82576
+            || dev->mac_type == e1000_I210
+            || dev->mac_type == e1000_I350) {
+            // TODO(lh): Check if these cards really dont need the itr set as well.
+            e1000_eitr_interval_wrf(dev->device, 0, rate);
+            e1000_eitr_interval_wrf(dev->device, 1, rate);
+            e1000_eitr_interval_wrf(dev->device, 2, rate);
+            e1000_eitr_interval_wrf(dev->device, 3, rate);
+        }
+        else if(dev->mac_type == e1000_82574){
+            e1000_itr_interval_wrf(dev->device, rate);
+            e1000_eitr_82574_interval_wrf(dev->device, 0, rate);
+            e1000_eitr_82574_interval_wrf(dev->device, 1, rate);
+            e1000_eitr_82574_interval_wrf(dev->device, 2, rate);
+            e1000_eitr_82574_interval_wrf(dev->device, 3, rate);
+        }
+        else {
+            e1000_itr_interval_wrf(dev->device, 5580);
+        }
+}
+
 /*****************************************************************
  * Initialize the hardware
  *
@@ -974,30 +1068,20 @@ void e1000_hwinit(e1000_device_t *dev, struct device_mem *bar_info,
 
     /* Enable interrupts */
     if (use_interrupt) {
-
-        /* 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
-         */
-        if (dev->mac_type == e1000_82575
-            || dev->mac_type == e1000_82576
-            || dev->mac_type == e1000_I210
-            || dev->mac_type == e1000_I350) {
-            e1000_eitr_interval_wrf(dev->device, 0, 5580);
-            //e1000_eitr_interval_wrf(dev->device, 0, 10);
-        }
-        else {
-            e1000_itr_interval_wrf(dev->device, 5580);
-            //e1000_itr_interval_wrf(dev->device, 10);
-        }
+        e1000_set_interrupt_throttle(dev, E1000_DEFAULT_INT_THROTTLE_RATE);
 
         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);
         e1000_ims_wr(dev->device, intreg);
+
+        /* In case of the 82574, we explicitly activate int cause auto clear to
+         * get the same behaviour as the other cards */
+        if(dev->mac_type == e1000_82574){
+            e1000_ctrlext_iame_wrf(dev->device, 1);
+        }
     }
 }
 
diff --git a/usr/drivers/e1000e/Hakefile b/usr/drivers/e1000e/Hakefile
deleted file mode 100644 (file)
index e49d967..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
---------------------------------------------------------------------------
--- Copyright (c) 2007-2009, 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.
---
--- Hakefile for /usr/drivers/e1000e
---
---------------------------------------------------------------------------
-
-[ build application { target = "e1000e_irqtest",
-                      cFiles = [ "e1000e.c"],
-                      flounderBindings = [ "net_queue_manager",
-                                            "net_soft_filters", "octopus" ],
-                      mackerelDevices = [ "e1000e" ],
-                      addLibraries = libDeps [ "pci", "netQmng", "trace", "octopus" ],
-                      architectures = [ "x86_64" ],
-                      addCFlags = [ "-DIRQTEST" ]
-                    }
-]
diff --git a/usr/drivers/e1000e/e1000e.c b/usr/drivers/e1000e/e1000e.c
deleted file mode 100644 (file)
index 50e3984..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- */
-/*
- * e1000e.c
- *
- *  Created on: Oct 10, 2016
- *      Author: lh
- *
- * NOTES:
- *      General:
- *          The driver must be started by Kaluga. It supports
- *          the Intel 82574 GbE Controller Family.
- *
- *      PCI Ids:
- *          Vendor: 0x8086, Device: 0x10d3 
- *
- *
- * Inspired by the Barrelfish e1000 driver.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <barrelfish/barrelfish.h>
-#include <barrelfish/nameservice_client.h>
-#include <octopus/octopus.h>
-#include <net_queue_manager/net_queue_manager.h>
-#include <if/net_queue_manager_defs.h>
-#include <pci/devids.h>
-#include <pci/pci.h>
-
-#include "e1000e_debug.h"
-
-#include <dev/e1000e_dev.h>
-
-static void e1000e_hwinit(e1000e_t *dev, struct device_mem *bar_info,
-                  int nr_allocated_bars)
-{
-    errval_t err;
-    if (nr_allocated_bars < 1) {
-        USER_PANIC("Error: Not enough PCI bars allocated. Can not initialize network device.\n");
-    }
-
-    err = map_device(&bar_info[0]);
-    if (err_is_fail(err)) {
-        USER_PANIC("Error: map_device failed. Can not initialize network device.\n");
-    }
-
-    e1000e_initialize(dev, (void *) bar_info[0].vaddr);
-}
-
-// Interrupt handler
-static void e1000e_interrupt_handler_fn(void *arg)
-{
-    E1000E_DEBUG("e1000e_interrupt_handler called");
-}
-
-// Callback from pci lib
-static void e1000e_init_fn(struct device_mem *bar_info, int nr_allocated_bars) {
-    E1000E_DEBUG("e1000e_init_fn interrupt handler called");
-    e1000e_t dev;
-    e1000e_hwinit(&dev, bar_info, nr_allocated_bars);
-}
-
-// On core move
-static void e1000e_reregister_handler(void *arg) {
-    printf("%s:%s:%d:\n", __FILE__, __FUNCTION__, __LINE__);
-}
-
-// Local state
-static uint32_t class = PCI_CLASS_ETHERNET;
-static uint32_t subclass = PCI_DONT_CARE;
-static uint32_t bus = PCI_DONT_CARE;
-static uint32_t device = PCI_DONT_CARE;
-static uint32_t function = PCI_DONT_CARE;
-static uint32_t deviceid = PCI_DONT_CARE;
-static uint32_t vendor = PCI_VENDOR_INTEL;
-static uint32_t program_interface = PCI_DONT_CARE;
-
-int main(int argc, char **argv)
-{
-    errval_t err;
-    // Parse command line arguments.
-    E1000E_DEBUG("e1000e standalone driver started.\n");
-    E1000E_DEBUG("argc = %d\n", argc);
-
-    // try parse Kaluga information which is located at the last argument
-    if (argc > 1) {
-        uint32_t parsed = sscanf(argv[argc - 1], "%x:%x:%x:%x:%x", &vendor,
-                                 &deviceid, &bus, &device, &function);
-        if (parsed != 5) {
-            E1000E_DEBUG("Driver seems not to be started by Kaluga.\n");
-            vendor = PCI_DONT_CARE;
-            deviceid = PCI_DONT_CARE;
-            bus = PCI_DONT_CARE;
-            device = PCI_DONT_CARE;
-            function = PCI_DONT_CARE;
-        } else {
-            E1000E_DEBUG("PCI Device (%u, %u, %u) Vendor: 0x%04x, Device 0x%04x\n",
-                        bus, device, function, vendor, deviceid);
-            // remove the last argument
-            argc--;
-        }
-    }
-
-    printf("########### Driver with interrupts ###########\n");
-    err = pci_register_driver_movable_irq(e1000e_init_fn, class, subclass, program_interface,
-                                          vendor, deviceid, bus, device, function,
-                                          e1000e_interrupt_handler_fn, NULL,
-                                          e1000e_reregister_handler,
-                                          NULL);
-    assert(err_is_ok(err));
-
-    E1000E_DEBUG("#### starting polling.\n");
-    while (true) {
-        event_dispatch(get_default_waitset());
-    }
-    return 1;
-}
-
diff --git a/usr/drivers/e1000e/e1000e_debug.h b/usr/drivers/e1000e/e1000e_debug.h
deleted file mode 100644 (file)
index 21dee7b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2016, 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 __E1000E_DEBUG_H__
-#define __E1000E_DEBUG_H__
-
-
-/*****************************************************************
- * Debug printer:
- *****************************************************************/
-#define E1000E_SERVICE_DEBUG 1
-
-
-#if defined(E1000E_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
-#define E1000E_DEBUG(fmt, ...) printf("e1000e: " fmt, ##__VA_ARGS__)
-#else
-#define E1000E_DEBUG(fmt, ...) ((void)0)
-#endif
-
-#endif // __E1000E_DEBUG_H__
index 0747c13..c514dd4 100644 (file)
@@ -48,6 +48,7 @@ pci_driver{
       pci_card{ vendor: 16'8086, device: 16'100e, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'10c9, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'10a7, function: _, subvendor: _, subdevice: _ },
+      pci_card{ vendor: 16'8086, device: 16'10d3, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'1533, function: _, subvendor: _, subdevice: _ } ],
     core_hint: 0,
     core_offset: 0,
index 0829109..9d15ac6 100644 (file)
@@ -1,7 +1,6 @@
 % Load the irqtest program with a higher priority than the e1000 driver
 pci_driver{
     binary: "e1000n_irqtest",
-    binary: "irqtest",
     supported_cards:
     [ pci_card{ vendor: 16'8086, device: 16'1521, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'107d, function: _, subvendor: _, subdevice: _ },
@@ -14,7 +13,8 @@ pci_driver{
       pci_card{ vendor: 16'8086, device: 16'100e, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'10c9, function: _, subvendor: _, subdevice: _ },
       pci_card{ vendor: 16'8086, device: 16'10a7, function: _, subvendor: _, subdevice: _ },
-      pci_card{ vendor: 16'8086, device: 16'1533, function: _, subvendor: _, subdevice: _ } ],
+      pci_card{ vendor: 16'8086, device: 16'1533, function: _, subvendor: _, subdevice: _ },
+      pci_card{ vendor: 16'8086, device: 16'10d3, function: _, subvendor: _, subdevice: _ } ],
     core_hint: 0,
     core_offset: 0,
     multi_instance: 0,
@@ -24,14 +24,3 @@ pci_driver{
     priority: 1000
 }.
 
-% Load the irqtest_e1000e program 
-pci_driver{
-    binary: "e1000e_irqtest",
-    supported_cards:
-    [ pci_card{ vendor: 16'8086, device: 16'10d3, function: _, subvendor: _, subdevice: _ } ],
-    core_hint: 0,
-    core_offset: 0,
-    multi_instance: 0,
-    interrupt_load: 0.75,
-    platforms: ['x86_64']
-}.