From 3e3be6ba506dcee77efe6e60c96058ec5e91506d Mon Sep 17 00:00:00 2001 From: dongshen Date: Mon, 10 Jun 2019 13:31:40 -0700 Subject: [PATCH] HV: for PCI cardbus device, its capability offset is at offset 0x14 Add get_offset_of_caplist() function to return capability offset based on header type: For normal pci device and bridge, its capability offset is at offset 0x34 For cardbus, its capability offset is at offset 0x14 Tracked-On: #3241 Signed-off-by: dongshen Reviewed-by: Eddie Dong --- hypervisor/hw/pci.c | 39 +++++++++++++++++++++++++++++++++---- hypervisor/include/hw/pci.h | 1 + 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index b861500524..8dcfb47601 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -301,7 +301,6 @@ static uint8_t pci_pdev_read_bar(union pci_bdf bdf, uint8_t idx, struct pci_bar return (type == PCIBAR_MEM64)?2U:1U; } - /* * @pre nr_bars <= PCI_BAR_COUNT */ @@ -314,14 +313,46 @@ static void pci_pdev_read_bars(union pci_bdf bdf, uint8_t nr_bars, struct pci_ba } } -static void pci_read_cap(struct pci_pdev *pdev) +/* + * @pre ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL) || ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) || ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_CARDBUS) + */ +static uint32_t get_offset_of_caplist(uint8_t hdr_type) +{ + uint32_t cap_offset = 0U; + + switch (hdr_type & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_NORMAL: + case PCIM_HDRTYPE_BRIDGE: + cap_offset = PCIR_CAP_PTR; + break; + + case PCIM_HDRTYPE_CARDBUS: + cap_offset = PCIR_CAP_PTR_CARDBUS; + break; + + default: + /* do nothing */ + break; + } + + return cap_offset; +} + +/* + * @pre pdev != NULL + * @pre ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL) || ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) || ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_CARDBUS) + */ +static void pci_read_cap(struct pci_pdev *pdev, uint8_t hdr_type) { uint8_t ptr, cap; uint32_t msgctrl; uint32_t len, offset, idx; uint32_t table_info; + uint32_t cap_offset; + + cap_offset = get_offset_of_caplist(hdr_type); - ptr = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_CAP_PTR, 1U); + ptr = (uint8_t)pci_pdev_read_cfg(pdev->bdf, cap_offset, 1U); while ((ptr != 0U) && (ptr != 0xFFU)) { cap = (uint8_t)pci_pdev_read_cfg(pdev->bdf, ptr + PCICAP_ID, 1U); @@ -381,7 +412,7 @@ static void fill_pdev(uint16_t pbdf, struct pci_pdev *pdev) pci_pdev_read_bars(pdev->bdf, nr_bars, &pdev->bar[0]); if ((pci_pdev_read_cfg(pdev->bdf, PCIR_STATUS, 2U) & PCIM_STATUS_CAPPRESENT) != 0U) { - pci_read_cap(pdev); + pci_read_cap(pdev, hdr_type); } } diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 6b6cd6073b..5fb48e6005 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -84,6 +84,7 @@ #define PCIM_BAR_MEM_64 0x04U #define PCIM_BAR_MEM_BASE 0xFFFFFFF0U #define PCIR_CAP_PTR 0x34U +#define PCIR_CAP_PTR_CARDBUS 0x14U /* config registers for header type 1 (PCI-to-PCI bridge) devices */ #define PCIR_PRIBUS_1 0x18U