qemu/tests/qtest/libqos/igb.c
<<
>>
Prefs
   1/*
   2 * libqos driver framework
   3 *
   4 * Copyright (c) 2022-2023 Red Hat, Inc.
   5 * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License version 2.1 as published by the Free Software Foundation.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "hw/net/igb_regs.h"
  22#include "hw/net/mii.h"
  23#include "hw/pci/pci_ids.h"
  24#include "../libqtest.h"
  25#include "pci-pc.h"
  26#include "qemu/sockets.h"
  27#include "qemu/iov.h"
  28#include "qemu/module.h"
  29#include "qemu/bitops.h"
  30#include "libqos-malloc.h"
  31#include "qgraph.h"
  32#include "e1000e.h"
  33
  34#define IGB_IVAR_TEST_CFG \
  35    ((E1000E_RX0_MSG_ID | E1000_IVAR_VALID) << (igb_ivar_entry_rx(0) * 8)   | \
  36     ((E1000E_TX0_MSG_ID | E1000_IVAR_VALID) << (igb_ivar_entry_tx(0) * 8)))
  37
  38#define E1000E_RING_LEN (0x1000)
  39
  40static void e1000e_foreach_callback(QPCIDevice *dev, int devfn, void *data)
  41{
  42    QPCIDevice *res = data;
  43    memcpy(res, dev, sizeof(QPCIDevice));
  44    g_free(dev);
  45}
  46
  47static void e1000e_pci_destructor(QOSGraphObject *obj)
  48{
  49    QE1000E_PCI *epci = (QE1000E_PCI *) obj;
  50    qpci_iounmap(&epci->pci_dev, epci->mac_regs);
  51    qpci_msix_disable(&epci->pci_dev);
  52}
  53
  54static void igb_pci_start_hw(QOSGraphObject *obj)
  55{
  56    static const uint8_t address[] = E1000E_ADDRESS;
  57    QE1000E_PCI *d = (QE1000E_PCI *) obj;
  58    uint32_t val;
  59
  60    /* Enable the device */
  61    qpci_device_enable(&d->pci_dev);
  62
  63    /* Reset the device */
  64    val = e1000e_macreg_read(&d->e1000e, E1000_CTRL);
  65    e1000e_macreg_write(&d->e1000e, E1000_CTRL, val | E1000_CTRL_RST | E1000_CTRL_SLU);
  66
  67    /* Setup link */
  68    e1000e_macreg_write(&d->e1000e, E1000_MDIC,
  69                        MII_BMCR_AUTOEN | MII_BMCR_ANRESTART |
  70                        (MII_BMCR << E1000_MDIC_REG_SHIFT) |
  71                        (1 << E1000_MDIC_PHY_SHIFT) |
  72                        E1000_MDIC_OP_WRITE);
  73
  74    qtest_clock_step(d->pci_dev.bus->qts, 900000000);
  75
  76    /* Enable and configure MSI-X */
  77    qpci_msix_enable(&d->pci_dev);
  78    e1000e_macreg_write(&d->e1000e, E1000_IVAR0, IGB_IVAR_TEST_CFG);
  79
  80    /* Check the device link status */
  81    val = e1000e_macreg_read(&d->e1000e, E1000_STATUS);
  82    g_assert_cmphex(val & E1000_STATUS_LU, ==, E1000_STATUS_LU);
  83
  84    /* Initialize TX/RX logic */
  85    e1000e_macreg_write(&d->e1000e, E1000_RCTL, 0);
  86    e1000e_macreg_write(&d->e1000e, E1000_TCTL, 0);
  87
  88    e1000e_macreg_write(&d->e1000e, E1000_TDBAL(0),
  89                           (uint32_t) d->e1000e.tx_ring);
  90    e1000e_macreg_write(&d->e1000e, E1000_TDBAH(0),
  91                           (uint32_t) (d->e1000e.tx_ring >> 32));
  92    e1000e_macreg_write(&d->e1000e, E1000_TDLEN(0), E1000E_RING_LEN);
  93    e1000e_macreg_write(&d->e1000e, E1000_TDT(0), 0);
  94    e1000e_macreg_write(&d->e1000e, E1000_TDH(0), 0);
  95
  96    /* Enable transmit */
  97    e1000e_macreg_write(&d->e1000e, E1000_TCTL, E1000_TCTL_EN);
  98
  99    e1000e_macreg_write(&d->e1000e, E1000_RDBAL(0),
 100                           (uint32_t)d->e1000e.rx_ring);
 101    e1000e_macreg_write(&d->e1000e, E1000_RDBAH(0),
 102                           (uint32_t)(d->e1000e.rx_ring >> 32));
 103    e1000e_macreg_write(&d->e1000e, E1000_RDLEN(0), E1000E_RING_LEN);
 104    e1000e_macreg_write(&d->e1000e, E1000_RDT(0), 0);
 105    e1000e_macreg_write(&d->e1000e, E1000_RDH(0), 0);
 106    e1000e_macreg_write(&d->e1000e, E1000_RA,
 107                        le32_to_cpu(*(uint32_t *)address));
 108    e1000e_macreg_write(&d->e1000e, E1000_RA + 4,
 109                        E1000_RAH_AV | E1000_RAH_POOL_1 |
 110                        le16_to_cpu(*(uint16_t *)(address + 4)));
 111
 112    /* Enable receive */
 113    e1000e_macreg_write(&d->e1000e, E1000_RFCTL, E1000_RFCTL_EXTEN);
 114    e1000e_macreg_write(&d->e1000e, E1000_RCTL, E1000_RCTL_EN);
 115
 116    /* Enable all interrupts */
 117    e1000e_macreg_write(&d->e1000e, E1000_IMS,  0xFFFFFFFF);
 118    e1000e_macreg_write(&d->e1000e, E1000_EIMS, 0xFFFFFFFF);
 119
 120}
 121
 122static void *igb_pci_get_driver(void *obj, const char *interface)
 123{
 124    QE1000E_PCI *epci = obj;
 125    if (!g_strcmp0(interface, "igb-if")) {
 126        return &epci->e1000e;
 127    }
 128
 129    /* implicit contains */
 130    if (!g_strcmp0(interface, "pci-device")) {
 131        return &epci->pci_dev;
 132    }
 133
 134    fprintf(stderr, "%s not present in igb\n", interface);
 135    g_assert_not_reached();
 136}
 137
 138static void *igb_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
 139{
 140    QE1000E_PCI *d = g_new0(QE1000E_PCI, 1);
 141    QPCIBus *bus = pci_bus;
 142    QPCIAddress *address = addr;
 143
 144    qpci_device_foreach(bus, address->vendor_id, address->device_id,
 145                        e1000e_foreach_callback, &d->pci_dev);
 146
 147    /* Map BAR0 (mac registers) */
 148    d->mac_regs = qpci_iomap(&d->pci_dev, 0, NULL);
 149
 150    /* Allocate and setup TX ring */
 151    d->e1000e.tx_ring = guest_alloc(alloc, E1000E_RING_LEN);
 152    g_assert(d->e1000e.tx_ring != 0);
 153
 154    /* Allocate and setup RX ring */
 155    d->e1000e.rx_ring = guest_alloc(alloc, E1000E_RING_LEN);
 156    g_assert(d->e1000e.rx_ring != 0);
 157
 158    d->obj.get_driver = igb_pci_get_driver;
 159    d->obj.start_hw = igb_pci_start_hw;
 160    d->obj.destructor = e1000e_pci_destructor;
 161
 162    return &d->obj;
 163}
 164
 165static void igb_register_nodes(void)
 166{
 167    QPCIAddress addr = {
 168        .vendor_id = PCI_VENDOR_ID_INTEL,
 169        .device_id = E1000_DEV_ID_82576,
 170    };
 171
 172    /*
 173     * FIXME: every test using this node needs to setup a -netdev socket,id=hs0
 174     * otherwise QEMU is not going to start
 175     */
 176    QOSGraphEdgeOptions opts = {
 177        .extra_device_opts = "netdev=hs0",
 178    };
 179    add_qpci_address(&opts, &addr);
 180
 181    qos_node_create_driver("igb", igb_pci_create);
 182    qos_node_consumes("igb", "pci-bus", &opts);
 183}
 184
 185libqos_init(igb_register_nodes);
 186