Signed-off-by: Knut Omang <knut.om...@oracle.com> --- hw/net/e1000.c | 126 +++++++-------------------------------------------- hw/net/e1000.h | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 110 deletions(-) create mode 100644 hw/net/e1000.h
diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 272df00..7afdcad 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -35,6 +35,7 @@ #include "qemu/iov.h" #include "e1000_regs.h" +#include "e1000.h" #define E1000_DEBUG @@ -75,101 +76,6 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); * Others never tested */ -typedef struct E1000State_st { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - NICState *nic; - NICConf conf; - MemoryRegion mmio; - MemoryRegion io; - - uint32_t mac_reg[0x8000]; - uint16_t phy_reg[0x20]; - uint16_t eeprom_data[64]; - - uint32_t rxbuf_size; - uint32_t rxbuf_min_shift; - 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; - unsigned char sum_needed; - unsigned char vlan_needed; - uint8_t ipcss; - uint8_t ipcso; - uint16_t ipcse; - uint8_t tucss; - uint8_t tucso; - uint16_t tucse; - uint8_t hdr_len; - uint16_t mss; - uint32_t paylen; - uint16_t tso_frames; - char tse; - int8_t ip; - int8_t tcp; - char cptse; // current packet tse bit - } tx; - - struct { - uint32_t val_in; // shifted in from guest driver - uint16_t bitnum_in; - uint16_t bitnum_out; - uint16_t reading; - uint32_t old_eecd; - } eecd_state; - - QEMUTimer *autoneg_timer; - - QEMUTimer *mit_timer; /* Mitigation timer. */ - bool mit_timer_on; /* Mitigation timer is running. */ - bool mit_irq_level; /* Tracks interrupt pin level. */ - uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */ - -/* Compatibility flags for migration to/from qemu 1.3.0 and older */ -#define E1000_FLAG_AUTONEG_BIT 0 -#define E1000_FLAG_MIT_BIT 1 -#define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) -#define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT) - uint32_t compat_flags; -} E1000State; - -typedef struct E1000BaseClass { - PCIDeviceClass parent_class; - uint16_t phy_id2; -} E1000BaseClass; - -#define TYPE_E1000_BASE "e1000-base" - -#define E1000(obj) \ - OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE) - -#define E1000_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE) -#define E1000_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE) - -#define defreg(x) x = (E1000_##x>>2) -enum { - defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), - defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), - defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), - defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH), - defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT), - defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), - defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), - defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL), - defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC), - defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA), - defreg(VET), defreg(RDTR), defreg(RADV), defreg(TADV), - defreg(ITR), -}; - static void e1000_link_down(E1000State *s) { @@ -398,7 +304,7 @@ rxbufsize(uint32_t v) return 2048; } -static void e1000_reset(void *opaque) +void e1000_reset(void *opaque) { E1000State *d = opaque; E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d); @@ -1507,8 +1413,7 @@ e1000_cleanup(NetClientState *nc) s->nic = NULL; } -static void -pci_e1000_uninit(PCIDevice *dev) +void pci_e1000_uninit(PCIDevice *dev) { E1000State *d = E1000(dev); @@ -1529,10 +1434,11 @@ static NetClientInfo net_e1000_info = { .link_status_changed = e1000_set_link_status, }; -static int pci_e1000_init(PCIDevice *pci_dev) +int pci_e1000_init(PCIDevice *pci_dev) { DeviceState *dev = DEVICE(pci_dev); E1000State *d = E1000(pci_dev); + E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d); PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(pci_dev); uint8_t *pci_conf; uint16_t checksum = 0; @@ -1548,9 +1454,12 @@ static int pci_e1000_init(PCIDevice *pci_dev) e1000_mmio_setup(d); - pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); - - pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io); + if (pci_dev->exp.is_vf) { + pcie_register_vf_bar(pci_dev, 0, &d->mmio); + } else { + pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); + pci_register_bar(pci_dev, edc->io_bar, PCI_BASE_ADDRESS_SPACE_IO, &d->io); + } memmove(d->eeprom_data, e1000_eeprom_template, sizeof e1000_eeprom_template); @@ -1592,14 +1501,7 @@ static Property e1000_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -typedef struct E1000Info { - const char *name; - uint16_t device_id; - uint8_t revision; - uint16_t phy_id2; -} E1000Info; - -static void e1000_class_init(ObjectClass *klass, void *data) +void e1000_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); @@ -1613,6 +1515,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) k->device_id = info->device_id; k->revision = info->revision; e->phy_id2 = info->phy_id2; + e->io_bar = info->io_bar; k->class_id = PCI_CLASS_NETWORK_ETHERNET; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); dc->desc = "Intel Gigabit Ethernet"; @@ -1634,18 +1537,21 @@ static const E1000Info e1000_devices[] = { .name = "e1000-82540em", .device_id = E1000_DEV_ID_82540EM, .revision = 0x03, + .io_bar = 1, .phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT, }, { .name = "e1000-82544gc", .device_id = E1000_DEV_ID_82544GC_COPPER, .revision = 0x03, + .io_bar = 1, .phy_id2 = E1000_PHY_ID2_82544x, }, { .name = "e1000-82545em", .device_id = E1000_DEV_ID_82545EM_COPPER, .revision = 0x03, + .io_bar = 1, .phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT, }, }; diff --git a/hw/net/e1000.h b/hw/net/e1000.h new file mode 100644 index 0000000..f215122 --- /dev/null +++ b/hw/net/e1000.h @@ -0,0 +1,139 @@ +/* + * 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: + * Copyright (c) 2007 Dan Aloni + * Copyright (c) 2004 Antony T Curtis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "e1000_regs.h" + +typedef struct E1000State_st { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + + NICState *nic; + NICConf conf; + MemoryRegion mmio; + MemoryRegion io; + + uint32_t mac_reg[0x8000]; + uint16_t phy_reg[0x20]; + uint16_t eeprom_data[64]; + + uint32_t rxbuf_size; + uint32_t rxbuf_min_shift; + 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; + unsigned char sum_needed; + unsigned char vlan_needed; + uint8_t ipcss; + uint8_t ipcso; + uint16_t ipcse; + uint8_t tucss; + uint8_t tucso; + uint16_t tucse; + uint8_t hdr_len; + uint16_t mss; + uint32_t paylen; + uint16_t tso_frames; + char tse; + int8_t ip; + int8_t tcp; + char cptse; // current packet tse bit + } tx; + + struct { + uint32_t val_in; // shifted in from guest driver + uint16_t bitnum_in; + uint16_t bitnum_out; + uint16_t reading; + uint32_t old_eecd; + } eecd_state; + + QEMUTimer *autoneg_timer; + + QEMUTimer *mit_timer; /* Mitigation timer. */ + bool mit_timer_on; /* Mitigation timer is running. */ + bool mit_irq_level; /* Tracks interrupt pin level. */ + uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */ + +/* Compatibility flags for migration to/from qemu 1.3.0 and older */ +#define E1000_FLAG_AUTONEG_BIT 0 +#define E1000_FLAG_MIT_BIT 1 +#define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT) +#define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT) + uint32_t compat_flags; +} E1000State; + +typedef struct E1000BaseClass { + PCIDeviceClass parent_class; + uint16_t phy_id2; + uint16_t io_bar; /* Which BAR register to use for the IO bar */ +} E1000BaseClass; + +#define TYPE_E1000_BASE "e1000-base" + +#define E1000(obj) \ + OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE) + +#define E1000_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE) +#define E1000_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE) + +#define defreg(x) x = (E1000_##x>>2) +enum { + defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), + defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), + defreg(IMS), defreg(LEDCTL), defreg(MANC), defreg(MDIC), + defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH), + defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT), + defreg(STATUS), defreg(SWSM), defreg(TCTL), defreg(TDBAH), + defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), + defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL), + defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC), + defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA), + defreg(VET), defreg(RDTR), defreg(RADV), defreg(TADV), + defreg(ITR), +}; + + +typedef struct E1000Info { + const char *name; + uint16_t device_id; + uint8_t revision; + uint8_t io_bar; + uint16_t phy_id2; +} E1000Info; + + +void e1000_class_init(ObjectClass *klass, void *data); + +int pci_e1000_init(PCIDevice *pci_dev); +void pci_e1000_uninit(PCIDevice *dev); +void e1000_reset(void *opaque); -- 1.9.0