void pcie_cap_deverr_reset(PCIDevice *dev) { uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL; pci_long_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); }
void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector) { uint8_t *aer_cap = dev->config + dev->exp.aer_cap; assert(vector < PCI_ERR_ROOT_IRQ_MAX); pci_long_test_and_clear_mask(aer_cap + PCI_ERR_ROOT_STATUS, PCI_ERR_ROOT_IRQ); pci_long_test_and_set_mask(aer_cap + PCI_ERR_ROOT_STATUS, vector << PCI_ERR_ROOT_IRQ_SHIFT); }
/* pci express slot for pci express root/downstream port PCI express capability slot registers */ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) { uint32_t pos = dev->exp.exp_cap; pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_FLAGS, PCI_EXP_FLAGS_SLOT); pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP, ~PCI_EXP_SLTCAP_PSN); pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, (slot << PCI_EXP_SLTCAP_PSN_SHIFT) | PCI_EXP_SLTCAP_EIP | PCI_EXP_SLTCAP_HPS | PCI_EXP_SLTCAP_HPC | PCI_EXP_SLTCAP_PIP | PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_ABP); if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) { pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP, PCI_EXP_SLTCAP_PCP); pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PCC); pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PCC); } pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PIC | PCI_EXP_SLTCTL_AIC); pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PIC_OFF | PCI_EXP_SLTCTL_AIC_OFF); pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_PIC | PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE); /* Although reading PCI_EXP_SLTCTL_EIC returns always 0, * make the bit writable here in order to detect 1b is written. * pcie_cap_slot_write_config() test-and-clear the bit, so * this bit always returns 0 to the guest. */ pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL, PCI_EXP_SLTCTL_EIC); pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA, PCI_EXP_HP_EV_SUPPORTED); dev->exp.hpev_notified = false; qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), DEVICE(dev), NULL); }
static void pcie_aer_clear_log(PCIDevice *dev) { uint8_t *aer_cap = dev->config + dev->exp.aer_cap; pci_long_test_and_clear_mask(aer_cap + PCI_ERR_CAP, PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP); memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE); memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0, PCI_ERR_TLP_PREFIX_LOG_SIZE); }
void pcie_cap_arifwd_reset(PCIDevice *dev) { uint8_t *devctl2 = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2; pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI); }
static void pcie_cap_fill_slot_lnk(PCIDevice *dev) { PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT); uint8_t *exp_cap = dev->config + dev->exp.exp_cap; /* Skip anything that isn't a PCIESlot */ if (!s) { return; } /* Clear and fill LNKCAP from what was configured above */ pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS); pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP, QEMU_PCI_EXP_LNKCAP_MLW(s->width) | QEMU_PCI_EXP_LNKCAP_MLS(s->speed)); /* * Link bandwidth notification is required for all root ports and * downstream ports supporting links wider than x1 or multiple link * speeds. */ if (s->width > QEMU_PCI_EXP_LNK_X1 || s->speed > QEMU_PCI_EXP_LNK_2_5GT) { pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_LBNC); } if (s->speed > QEMU_PCI_EXP_LNK_2_5GT) { /* * Hot-plug capable downstream ports and downstream ports supporting * link speeds greater than 5GT/s must hardwire PCI_EXP_LNKCAP_DLLLARC * to 1b. PCI_EXP_LNKCAP_DLLLARC implies PCI_EXP_LNKSTA_DLLLA, which * we also hardwire to 1b here. 2.5GT/s hot-plug slots should also * technically implement this, but it's not done here for compatibility. */ pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_DLLLARC); pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_DLLLA); /* * Target Link Speed defaults to the highest link speed supported by * the component. 2.5GT/s devices are permitted to hardwire to zero. */ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKCTL2, PCI_EXP_LNKCTL2_TLS); pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKCTL2, QEMU_PCI_EXP_LNKCAP_MLS(s->speed) & PCI_EXP_LNKCTL2_TLS); } /* * 2.5 & 5.0GT/s can be fully described by LNKCAP, but 8.0GT/s is * actually a reference to the highest bit supported in this register. * We assume the device supports all link speeds. */ if (s->speed > QEMU_PCI_EXP_LNK_5GT) { pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP2, ~0U); pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2, PCI_EXP_LNKCAP2_SLS_2_5GB | PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_8_0GB); if (s->speed > QEMU_PCI_EXP_LNK_8GT) { pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2, PCI_EXP_LNKCAP2_SLS_16_0GB); } } }
void pcie_cap_lnkctl_reset(PCIDevice *dev) { uint8_t *lnkctl = dev->config + dev->exp.exp_cap + PCI_EXP_LNKCTL; pci_long_test_and_clear_mask(lnkctl, PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES); }