예제 #1
0
파일: pci_bridge.c 프로젝트: 3a9LL/panda
int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
                          uint16_t svid, uint16_t ssid)
{
    int pos;
    pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset, PCI_SSVID_SIZEOF);
    if (pos < 0) {
        return pos;
    }

    pci_set_word(dev->config + pos + PCI_SSVID_SVID, svid);
    pci_set_word(dev->config + pos + PCI_SSVID_SSID, ssid);
    return pos;
}
예제 #2
0
파일: msix.c 프로젝트: AsherBond/qemu-kvm
/* Given a bar and its size, add MSI-X table on top of it
 * and fill MSI-X capability in the config space.
 * Original bar size must be a power of 2 or 0.
 * New bar size is returned. */
static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
                           unsigned bar_nr, unsigned bar_size)
{
    int config_offset;
    uint8_t *config;

    pdev->msix_bar_size = bar_size;

    config_offset = pci_find_capability(pdev, PCI_CAP_ID_MSIX);

    if (!config_offset) {
        uint32_t new_size;

        if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1)
            return -EINVAL;
        if (bar_size > 0x80000000)
            return -ENOSPC;

        /* Add space for MSI-X structures */
        if (!bar_size) {
            new_size = MSIX_PAGE_SIZE;
        } else if (bar_size < MSIX_PAGE_SIZE) {
            bar_size = MSIX_PAGE_SIZE;
            new_size = MSIX_PAGE_SIZE * 2;
        } else {
            new_size = bar_size * 2;
        }

        pdev->msix_bar_size = new_size;
        config_offset = pci_add_capability(pdev, PCI_CAP_ID_MSIX,
                                           0, MSIX_CAP_LENGTH);
        if (config_offset < 0)
            return config_offset;
        config = pdev->config + config_offset;

        pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
        /* Table on top of BAR */
        pci_set_long(config + PCI_MSIX_TABLE, bar_size | bar_nr);
        /* Pending bits on top of that */
        pci_set_long(config + PCI_MSIX_PBA, (bar_size + MSIX_PAGE_PENDING) |
                     bar_nr);
    }
    pdev->msix_cap = config_offset;
    /* Make flags bit writable. */
    pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
	    MSIX_MASKALL_MASK;
    return 0;
}
예제 #3
0
파일: pcie.c 프로젝트: THanwa/qemu
/***************************************************************************
 * pci express capability helper functions
 */
int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
{
    int pos;
    uint8_t *exp_cap;

    assert(pci_is_express(dev));

    pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                                 PCI_EXP_VER2_SIZEOF);
    if (pos < 0) {
        return pos;
    }
    dev->exp.exp_cap = pos;
    exp_cap = dev->config + pos;

    /* capability register
       interrupt message number defaults to 0 */
    pci_set_word(exp_cap + PCI_EXP_FLAGS,
                 ((type << PCI_EXP_FLAGS_TYPE_SHIFT) & PCI_EXP_FLAGS_TYPE) |
                 PCI_EXP_FLAGS_VER2);

    /* device capability register
     * table 7-12:
     * roll based error reporting bit must be set by all
     * Functions conforming to the ECN, PCI Express Base
     * Specification, Revision 1.1., or subsequent PCI Express Base
     * Specification revisions.
     */
    pci_set_long(exp_cap + PCI_EXP_DEVCAP, PCI_EXP_DEVCAP_RBER);

    pci_set_long(exp_cap + PCI_EXP_LNKCAP,
                 (port << PCI_EXP_LNKCAP_PN_SHIFT) |
                 PCI_EXP_LNKCAP_ASPMS_0S |
                 PCI_EXP_LNK_MLW_1 |
                 PCI_EXP_LNK_LS_25);

    pci_set_word(exp_cap + PCI_EXP_LNKSTA,
                 PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25);

    pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
                 PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);

    pci_set_word(dev->wmask + pos, PCI_EXP_DEVCTL2_EETLPPB);
    return pos;
}
예제 #4
0
파일: ich.c 프로젝트: ft-/ox820-qemu
static int pci_ich9_ahci_init(PCIDevice *dev)
{
    struct AHCIPCIState *d;
    int sata_cap_offset;
    uint8_t *sata_cap;
    d = DO_UPCAST(struct AHCIPCIState, card, dev);

    ahci_init(&d->ahci, &dev->qdev, 6);

    pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);

    d->card.config[PCI_CACHE_LINE_SIZE] = 0x08;  /* Cache line size */
    d->card.config[PCI_LATENCY_TIMER]   = 0x00;  /* Latency timer */
    pci_config_set_interrupt_pin(d->card.config, 1);

    /* XXX Software should program this register */
    d->card.config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */

    qemu_register_reset(ahci_reset, d);

    msi_init(dev, 0x50, 1, true, false);
    d->ahci.irq = d->card.irq[0];

    pci_register_bar(&d->card, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
                     &d->ahci.idp);
    pci_register_bar(&d->card, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
                     &d->ahci.mem);

    sata_cap_offset = pci_add_capability(&d->card, PCI_CAP_ID_SATA,
                                         ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE);
    if (sata_cap_offset < 0) {
        return sata_cap_offset;
    }

    sata_cap = d->card.config + sata_cap_offset;
    pci_set_word(sata_cap + SATA_CAP_REV, 0x10);
    pci_set_long(sata_cap + SATA_CAP_BAR,
                 (ICH9_IDP_BAR + 0x4) | (ICH9_IDP_INDEX_LOG2 << 4));
    d->ahci.idp_offset = ICH9_IDP_INDEX;

    return 0;
}
예제 #5
0
파일: e1000e.c 프로젝트: evandowning/panda
static int
e1000e_add_pm_capability(PCIDevice *pdev, uint8_t offset, uint16_t pmc)
{
    int ret = pci_add_capability(pdev, PCI_CAP_ID_PM, offset, PCI_PM_SIZEOF);

    if (ret >= 0) {
        pci_set_word(pdev->config + offset + PCI_PM_PMC,
                     PCI_PM_CAP_VER_1_1 |
                     pmc);

        pci_set_word(pdev->wmask + offset + PCI_PM_CTRL,
                     PCI_PM_CTRL_STATE_MASK |
                     PCI_PM_CTRL_PME_ENABLE |
                     PCI_PM_CTRL_DATA_SEL_MASK);

        pci_set_word(pdev->w1cmask + offset + PCI_PM_CTRL,
                     PCI_PM_CTRL_PME_STATUS);
    }

    return ret;
}
예제 #6
0
파일: pcie.c 프로젝트: juanquintela/qemu
int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset, uint8_t type,
                     uint8_t port)
{
    /* PCIe cap v1 init */
    int pos;
    Error *local_err = NULL;

    assert(pci_is_express(dev));

    pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                             PCI_EXP_VER1_SIZEOF, &local_err);
    if (pos < 0) {
        error_report_err(local_err);
        return pos;
    }
    dev->exp.exp_cap = pos;

    pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER1);

    return pos;
}
예제 #7
0
파일: shpc.c 프로젝트: CTU-IIG/qemu
/* Add SHPC capability to the config space for the device. */
static int shpc_cap_add_config(PCIDevice *d, Error **errp)
{
    uint8_t *config;
    int config_offset;
    config_offset = pci_add_capability(d, PCI_CAP_ID_SHPC,
                                       0, SHPC_CAP_LENGTH,
                                       errp);
    if (config_offset < 0) {
        return config_offset;
    }
    config = d->config + config_offset;

    pci_set_byte(config + SHPC_CAP_DWORD_SELECT, 0);
    pci_set_byte(config + SHPC_CAP_CxP, 0);
    pci_set_long(config + SHPC_CAP_DWORD_DATA, 0);
    d->shpc->cap = config_offset;
    /* Make dword select and data writeable. */
    pci_set_byte(d->wmask + config_offset + SHPC_CAP_DWORD_SELECT, 0xff);
    pci_set_long(d->wmask + config_offset + SHPC_CAP_DWORD_DATA, 0xffffffff);
    return 0;
}
예제 #8
0
파일: pcie.c 프로젝트: juanquintela/qemu
int pcie_cap_init(PCIDevice *dev, uint8_t offset,
                  uint8_t type, uint8_t port,
                  Error **errp)
{
    /* PCIe cap v2 init */
    int pos;
    uint8_t *exp_cap;

    assert(pci_is_express(dev));

    pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                             PCI_EXP_VER2_SIZEOF, errp);
    if (pos < 0) {
        return pos;
    }
    dev->exp.exp_cap = pos;
    exp_cap = dev->config + pos;

    /* Filling values common with v1 */
    pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER2);

    /* Fill link speed and width options */
    pcie_cap_fill_slot_lnk(dev);

    /* Filling v2 specific values */
    pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
                 PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);

    pci_set_word(dev->wmask + pos + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_EETLPPB);

    if (dev->cap_present & QEMU_PCIE_EXTCAP_INIT) {
        /* read-only to behave like a 'NULL' Extended Capability Header */
        pci_set_long(dev->wmask + PCI_CONFIG_SPACE_SIZE, 0);
    }

    return pos;
}
예제 #9
0
/* Initialize the MSI-X structures */
int msix_init(struct PCIDevice *dev, unsigned short nentries,
              MemoryRegion *table_bar, uint8_t table_bar_nr,
              unsigned table_offset, MemoryRegion *pba_bar,
              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos)
{
    int cap;
    unsigned table_size, pba_size;
    uint8_t *config;

    /* Nothing to do if MSI is not supported by interrupt controller */
    if (!msi_supported) {
        return -ENOTSUP;
    }

    if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1) {
        return -EINVAL;
    }

    table_size = nentries * PCI_MSIX_ENTRY_SIZE;
    pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;

    /* Sanity test: table & pba don't overlap, fit within BARs, min aligned */
    if ((table_bar_nr == pba_bar_nr &&
         ranges_overlap(table_offset, table_size, pba_offset, pba_size)) ||
        table_offset + table_size > memory_region_size(table_bar) ||
        pba_offset + pba_size > memory_region_size(pba_bar) ||
        (table_offset | pba_offset) & PCI_MSIX_FLAGS_BIRMASK) {
        return -EINVAL;
    }

    cap = pci_add_capability(dev, PCI_CAP_ID_MSIX, cap_pos, MSIX_CAP_LENGTH);
    if (cap < 0) {
        return cap;
    }

    dev->msix_cap = cap;
    dev->cap_present |= QEMU_PCI_CAP_MSIX;
    config = dev->config + cap;

    pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
    dev->msix_entries_nr = nentries;
    dev->msix_function_masked = true;

    pci_set_long(config + PCI_MSIX_TABLE, table_offset | table_bar_nr);
    pci_set_long(config + PCI_MSIX_PBA, pba_offset | pba_bar_nr);

    /* Make flags bit writable. */
    dev->wmask[cap + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
                                             MSIX_MASKALL_MASK;

    dev->msix_table = g_malloc0(table_size);
    dev->msix_pba = g_malloc0(pba_size);
    dev->msix_entry_used = g_malloc0(nentries * sizeof *dev->msix_entry_used);

    msix_mask_all(dev, nentries);

    memory_region_init_io(&dev->msix_table_mmio, OBJECT(dev), &msix_table_mmio_ops, dev,
                          "msix-table", table_size);
    memory_region_add_subregion(table_bar, table_offset, &dev->msix_table_mmio);
    memory_region_init_io(&dev->msix_pba_mmio, OBJECT(dev), &msix_pba_mmio_ops, dev,
                          "msix-pba", pba_size);
    memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio);

    return 0;
}