T308: Added e1000e mackerel and device driver stub
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Tue, 11 Oct 2016 16:32:31 +0000 (18:32 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Fri, 14 Oct 2016 16:11:52 +0000 (18:11 +0200)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

devices/Hakefile
devices/e1000e.dev [new file with mode: 0644]
usr/drivers/e1000e/Hakefile
usr/drivers/e1000e/e1000e.c
usr/drivers/e1000e/e1000e_debug.h [moved from usr/drivers/e1000e/e1000n_debug.h with 100% similarity]

index 743ad4b..057c44a 100644 (file)
@@ -30,6 +30,7 @@
            "ata_identify",
            "audio_nbm",
            "e1000",
+           "e1000e",
            "e10k",
            "e10k_vf",
            "e10k_q",
diff --git a/devices/e1000e.dev b/devices/e1000e.dev
new file mode 100644 (file)
index 0000000..e90729d
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * 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 e61937c..e49d967 100644 (file)
@@ -14,7 +14,7 @@
                       cFiles = [ "e1000e.c"],
                       flounderBindings = [ "net_queue_manager",
                                             "net_soft_filters", "octopus" ],
-                      -- mackerelDevices = [ "e1000e" ],
+                      mackerelDevices = [ "e1000e" ],
                       addLibraries = libDeps [ "pci", "netQmng", "trace", "octopus" ],
                       architectures = [ "x86_64" ],
                       addCFlags = [ "-DIRQTEST" ]
index 6b7c57a..50e3984 100644 (file)
 #include <octopus/octopus.h>
 #include <net_queue_manager/net_queue_manager.h>
 #include <if/net_queue_manager_defs.h>
-
-#include "e1000n_debug.h"
 #include <pci/devids.h>
-/*****************************************************************
- * Local states:
- *****************************************************************/
+#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)
 {
-    /** Parse command line arguments. */
+    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 */
+    // 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);
@@ -69,7 +108,18 @@ int main(int argc, char **argv)
         }
     }
 
+    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;
 }