]> Git Repo - qemu.git/blobdiff - hw/e1000.c
Merge remote branch 'spice/bugfix.2' into staging
[qemu.git] / hw / e1000.c
index 028afd1504f95b8825c993bed6411d2436d8c12b..677165f830963b4a84fa601ab1aef5d7dcff0865 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * QEMU e1000 emulation
  *
+ * Software developer's manual:
+ * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
+ *
  * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
  * Copyright (c) 2008 Qumranet
  * Based on work done by:
@@ -30,9 +33,9 @@
 
 #include "e1000_hw.h"
 
-#define DEBUG
+#define E1000_DEBUG
 
-#ifdef DEBUG
+#ifdef E1000_DEBUG
 enum {
     DEBUG_GENERAL,     DEBUG_IO,       DEBUG_MMIO,     DEBUG_INTERRUPT,
     DEBUG_RX,          DEBUG_TX,       DEBUG_MDIC,     DEBUG_EEPROM,
@@ -52,6 +55,7 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
 #define IOPORT_SIZE       0x40
 #define PNPMMIO_SIZE      0x20000
+#define MIN_BUF_SIZE      60 /* Min. octets in an ethernet frame sans FCS */
 
 /*
  * HW models:
@@ -75,7 +79,7 @@ enum {
 
 typedef struct E1000State_st {
     PCIDevice dev;
-    VLANClientState *vc;
+    NICState *nic;
     NICConf conf;
     int mmio_index;
 
@@ -89,6 +93,7 @@ typedef struct E1000State_st {
     struct e1000_tx {
         unsigned char header[256];
         unsigned char vlan_header[4];
+        /* Fields vlan and data must not be reordered or separated. */
         unsigned char vlan[4];
         unsigned char data[0x10000];
         uint16_t size;
@@ -145,10 +150,11 @@ static const char phy_regcap[0x20] = {
 };
 
 static void
-ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
-           uint32_t size, int type)
+ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
+           pcibus_t size, int type)
 {
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
+    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS
+           " size=0x%08"FMT_PCIBUS"\n", addr, size);
 }
 
 static void
@@ -257,21 +263,20 @@ set_eecd(E1000State *s, int index, uint32_t val)
 
     s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS |
             E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ);
+    if (!(E1000_EECD_CS & val))                        // CS inactive; nothing to do
+       return;
+    if (E1000_EECD_CS & (val ^ oldval)) {      // CS rise edge; reset state
+       s->eecd_state.val_in = 0;
+       s->eecd_state.bitnum_in = 0;
+       s->eecd_state.bitnum_out = 0;
+       s->eecd_state.reading = 0;
+    }
     if (!(E1000_EECD_SK & (val ^ oldval)))     // no clock edge
         return;
     if (!(E1000_EECD_SK & val)) {              // falling edge
         s->eecd_state.bitnum_out++;
         return;
     }
-    if (!(val & E1000_EECD_CS)) {              // rising, no CS (EEPROM reset)
-        memset(&s->eecd_state, 0, sizeof s->eecd_state);
-        /*
-         * restore old_eecd's E1000_EECD_SK (known to be on)
-         * to avoid false detection of a clock edge
-         */
-        s->eecd_state.old_eecd = E1000_EECD_SK;
-        return;
-    }
     s->eecd_state.val_in <<= 1;
     if (val & E1000_EECD_DI)
         s->eecd_state.val_in |= 1;
@@ -339,6 +344,15 @@ is_vlan_txd(uint32_t txd_lower)
     return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
 }
 
+/* FCS aka Ethernet CRC-32. We don't get it from backends and can't
+ * fill it in, just pad descriptor length by 4 bytes unless guest
+ * told us to strip it off the packet. */
+static inline int
+fcs_len(E1000State *s)
+{
+    return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
+}
+
 static void
 xmit_seg(E1000State *s)
 {
@@ -370,9 +384,12 @@ xmit_seg(E1000State *s)
         } else // UDP
             cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
         if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
+            unsigned int phsum;
             // add pseudo-header length before checksum calculation
             sp = (uint16_t *)(tp->data + tp->tucso);
-            cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
+            phsum = be16_to_cpup(sp) + len;
+            phsum = (phsum >> 16) + (phsum & 0xffff);
+            cpu_to_be16wu(sp, phsum);
         }
         tp->tso_frames++;
     }
@@ -382,11 +399,12 @@ xmit_seg(E1000State *s)
     if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
         putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
     if (tp->vlan_needed) {
-        memmove(tp->vlan, tp->data, 12);
+        memmove(tp->vlan, tp->data, 4);
+        memmove(tp->data, tp->data + 4, 8);
         memcpy(tp->data + 8, tp->vlan_header, 4);
-        qemu_send_packet(s->vc, tp->vlan, tp->size + 4);
+        qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4);
     } else
-        qemu_send_packet(s->vc, tp->data, tp->size);
+        qemu_send_packet(&s->nic->nc, tp->data, tp->size);
     s->mac_reg[TPT]++;
     s->mac_reg[GPTC]++;
     n = s->mac_reg[TOTL];
@@ -538,8 +556,8 @@ start_xmit(E1000State *s)
 static int
 receive_filter(E1000State *s, const uint8_t *buf, int size)
 {
-    static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-    static int mta_shift[] = {4, 3, 2, 0};
+    static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    static const int mta_shift[] = {4, 3, 2, 0};
     uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
 
     if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
@@ -589,12 +607,12 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
 }
 
 static void
-e1000_set_link_status(VLANClientState *vc)
+e1000_set_link_status(VLANClientState *nc)
 {
-    E1000State *s = vc->opaque;
+    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
     uint32_t old_status = s->mac_reg[STATUS];
 
-    if (vc->link_down)
+    if (nc->link_down)
         s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
     else
         s->mac_reg[STATUS] |= E1000_STATUS_LU;
@@ -604,27 +622,36 @@ e1000_set_link_status(VLANClientState *vc)
 }
 
 static int
-e1000_can_receive(VLANClientState *vc)
+e1000_can_receive(VLANClientState *nc)
 {
-    E1000State *s = vc->opaque;
+    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
     return (s->mac_reg[RCTL] & E1000_RCTL_EN);
 }
 
 static ssize_t
-e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
+e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
 {
-    E1000State *s = vc->opaque;
+    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
     struct e1000_rx_desc desc;
     target_phys_addr_t base;
     unsigned int n, rdt;
     uint32_t rdh_start;
     uint16_t vlan_special = 0;
     uint8_t vlan_status = 0, vlan_offset = 0;
+    uint8_t min_buf[MIN_BUF_SIZE];
 
     if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
         return -1;
 
+    /* Pad to minimum Ethernet frame length */
+    if (size < sizeof(min_buf)) {
+        memcpy(min_buf, buf, size);
+        memset(&min_buf[size], 0, sizeof(min_buf) - size);
+        buf = min_buf;
+        size = sizeof(min_buf);
+    }
+
     if (size > s->rxbuf_size) {
         DBGOUT(RX, "packet too large for buffers (%lu > %d)\n",
                (unsigned long)size, s->rxbuf_size);
@@ -636,14 +663,13 @@ e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
 
     if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
         vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
-        memmove((void *)(buf + 4), buf, 12);
+        memmove((uint8_t *)buf + 4, buf, 12);
         vlan_status = E1000_RXD_STAT_VP;
         vlan_offset = 4;
         size -= 4;
     }
 
     rdh_start = s->mac_reg[RDH];
-    size += 4; // for the header
     do {
         if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
             set_ics(s, 0, E1000_ICS_RXO);
@@ -657,7 +683,7 @@ e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
         if (desc.buffer_addr) {
             cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
                                       (void *)(buf + vlan_offset), size);
-            desc.length = cpu_to_le16(size);
+            desc.length = cpu_to_le16(size + fcs_len(s));
             desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
         } else // as per intel docs; skip descriptors with null buf addr
             DBGOUT(RX, "Null RX descriptor!!\n");
@@ -677,9 +703,14 @@ e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
 
     s->mac_reg[GPRC]++;
     s->mac_reg[TPR]++;
-    n = s->mac_reg[TORL];
-    if ((s->mac_reg[TORL] += size) < n)
+    /* TOR - Total Octets Received:
+     * This register includes bytes received in a packet from the <Destination
+     * Address> field through the <CRC> field, inclusively.
+     */
+    n = s->mac_reg[TORL] + size + /* Always include FCS length. */ 4;
+    if (n < s->mac_reg[TORL])
         s->mac_reg[TORH]++;
+    s->mac_reg[TORL] = n;
 
     n = E1000_ICS_RXT0;
     if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
@@ -789,6 +820,8 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
     getreg(MANC),      getreg(MDIC),   getreg(SWSM),   getreg(STATUS),
     getreg(TORL),      getreg(TOTL),   getreg(IMS),    getreg(TCTL),
     getreg(RDH),       getreg(RDT),    getreg(VET),    getreg(ICS),
+    getreg(TDBAL),     getreg(TDBAH),  getreg(RDBAH),  getreg(RDBAL),
+    getreg(TDLEN),     getreg(RDLEN),
 
     [TOTH] = mac_read_clr8,    [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
     [GPTC] = mac_read_clr4,    [TPR] = mac_read_clr4,  [TPT] = mac_read_clr4,
@@ -1011,7 +1044,7 @@ static CPUReadMemoryFunc * const e1000_mmio_read[] = {
 
 static void
 e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
@@ -1021,7 +1054,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
     };
 
 
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
+           addr, size);
 
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
     qemu_register_coalesced_mmio(addr, excluded_regs[0]);
@@ -1033,11 +1067,11 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
 }
 
 static void
-e1000_cleanup(VLANClientState *vc)
+e1000_cleanup(VLANClientState *nc)
 {
-    E1000State *d = vc->opaque;
+    E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
-    d->vc = NULL;
+    s->nic = NULL;
 }
 
 static int
@@ -1046,8 +1080,7 @@ pci_e1000_uninit(PCIDevice *dev)
     E1000State *d = DO_UPCAST(E1000State, dev, dev);
 
     cpu_unregister_io_memory(d->mmio_index);
-    qemu_del_vlan_client(d->vc);
-    vmstate_unregister(&vmstate_e1000, d);
+    qemu_del_vlan_client(&d->nic->nc);
     return 0;
 }
 
@@ -1063,6 +1096,15 @@ static void e1000_reset(void *opaque)
     memset(&d->tx, 0, sizeof d->tx);
 }
 
+static NetClientInfo net_e1000_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = e1000_can_receive,
+    .receive = e1000_receive,
+    .cleanup = e1000_cleanup,
+    .link_status_changed = e1000_set_link_status,
+};
+
 static int pci_e1000_init(PCIDevice *pci_dev)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
@@ -1075,22 +1117,24 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, E1000_DEVID);
-    *(uint16_t *)(pci_conf+0x04) = cpu_to_le16(0x0407);
-    *(uint16_t *)(pci_conf+0x06) = cpu_to_le16(0x0010);
-    pci_conf[0x08] = 0x03;
+    /* TODO: we have no capabilities, so why is this bit set? */
+    pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST);
+    pci_conf[PCI_REVISION_ID] = 0x03;
     pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
-    pci_conf[0x0c] = 0x10;
+    /* TODO: RST# value should be 0, PCI spec 6.2.4 */
+    pci_conf[PCI_CACHE_LINE_SIZE] = 0x10;
 
-    pci_conf[0x3d] = 1; // interrupt pin 0
+    /* TODO: RST# value should be 0 if programmable, PCI spec 6.2.4 */
+    pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
 
     d->mmio_index = cpu_register_io_memory(e1000_mmio_read,
             e1000_mmio_write, d);
 
     pci_register_bar((PCIDevice *)d, 0, PNPMMIO_SIZE,
-                           PCI_ADDRESS_SPACE_MEM, e1000_mmio_map);
+                           PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
 
     pci_register_bar((PCIDevice *)d, 1, IOPORT_SIZE,
-                           PCI_ADDRESS_SPACE_IO, ioport_map);
+                           PCI_BASE_ADDRESS_SPACE_IO, ioport_map);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
@@ -1103,25 +1147,10 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     checksum = (uint16_t) EEPROM_SUM - checksum;
     d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
 
-    d->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC,
-                                 d->conf.vlan, d->conf.peer,
-                                 d->dev.qdev.info->name, d->dev.qdev.id,
-                                 e1000_can_receive, e1000_receive, NULL,
-                                 NULL, e1000_cleanup, d);
-    d->vc->link_status_changed = e1000_set_link_status;
-
-    qemu_format_nic_info_str(d->vc, macaddr);
+    d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
+                          d->dev.qdev.info->name, d->dev.qdev.id, d);
 
-    vmstate_register(-1, &vmstate_e1000, d);
-    e1000_reset(d);
-
-    if (!pci_dev->qdev.hotplugged) {
-        static int loaded = 0;
-        if (!loaded) {
-            rom_add_option("pxe-e1000.bin");
-            loaded = 1;
-        }
-    }
+    qemu_format_nic_info_str(&d->nic->nc, macaddr);
     return 0;
 }
 
@@ -1136,8 +1165,10 @@ static PCIDeviceInfo e1000_info = {
     .qdev.desc  = "Intel Gigabit Ethernet",
     .qdev.size  = sizeof(E1000State),
     .qdev.reset = qdev_e1000_reset,
+    .qdev.vmsd  = &vmstate_e1000,
     .init       = pci_e1000_init,
     .exit       = pci_e1000_uninit,
+    .romfile    = "pxe-e1000.bin",
     .qdev.props = (Property[]) {
         DEFINE_NIC_PROPERTIES(E1000State, conf),
         DEFINE_PROP_END_OF_LIST(),
This page took 0.037293 seconds and 4 git commands to generate.