pci: add API to add capability at a known offset
Unlike virtio, device emulations need to add pci capabilities at known offsets to match real hardware. Make this possible by adding an appropriate API. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
f62719ca6f
commit
1db5a3aad3
17
hw/pci.c
17
hw/pci.c
|
@ -1789,12 +1789,10 @@ static int pci_add_option_rom(PCIDevice *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve space and add capability to the linked list in pci config space */
|
/* Reserve space and add capability to the linked list in pci config space */
|
||||||
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
|
int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id,
|
||||||
|
uint8_t offset, uint8_t size)
|
||||||
{
|
{
|
||||||
uint8_t offset = pci_find_space(pdev, size);
|
|
||||||
uint8_t *config = pdev->config + offset;
|
uint8_t *config = pdev->config + offset;
|
||||||
if (!offset)
|
|
||||||
return -ENOSPC;
|
|
||||||
config[PCI_CAP_LIST_ID] = cap_id;
|
config[PCI_CAP_LIST_ID] = cap_id;
|
||||||
config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
|
config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
|
||||||
pdev->config[PCI_CAPABILITY_LIST] = offset;
|
pdev->config[PCI_CAPABILITY_LIST] = offset;
|
||||||
|
@ -1807,6 +1805,17 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find and reserve space and add capability to the linked list
|
||||||
|
* in pci config space */
|
||||||
|
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
|
||||||
|
{
|
||||||
|
uint8_t offset = pci_find_space(pdev, size);
|
||||||
|
if (!offset) {
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
return pci_add_capability_at_offset(pdev, cap_id, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unlink capability from the pci config space. */
|
/* Unlink capability from the pci config space. */
|
||||||
void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
|
void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
|
||||||
{
|
{
|
||||||
|
|
2
hw/pci.h
2
hw/pci.h
|
@ -190,6 +190,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
|
||||||
PCIMapIORegionFunc *map_func);
|
PCIMapIORegionFunc *map_func);
|
||||||
|
|
||||||
int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
|
int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
|
||||||
|
int pci_add_capability_at_offset(PCIDevice *pci_dev, uint8_t cap_id,
|
||||||
|
uint8_t cap_offset, uint8_t cap_size);
|
||||||
|
|
||||||
void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
|
void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue