dm: PTM: Add a few pci utility functions

Add a few pci utility functions to help easy access of pci
    functionalities.
    1. pci_find_capability(): find position of specified pci capability register
    2. pci_find_ext_cap(): find extend capability register position from cap_id
    3. pci_pcie_type(): find pci-e device type
    4. is_root_port(): check whether pdev is a pci root port
    5. is_bridge(): check whether pdev is a bridge

Tracked-On: #5915
Signed-off-by: Rong Liu <rong.l.liu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Rong Liu 2021-04-28 21:08:59 +00:00 committed by wenlingz
parent 1e033f9d89
commit d3185f8a0c
3 changed files with 124 additions and 0 deletions

View File

@ -130,6 +130,7 @@ SRCS += hw/pci/hostbridge.c
SRCS += hw/pci/platform_gsi_info.c
SRCS += hw/pci/gsi_sharing.c
SRCS += hw/pci/passthrough.c
SRCS += hw/pci/pci_util.c
SRCS += hw/pci/virtio/virtio_audio.c
SRCS += hw/pci/virtio/virtio_net.c
SRCS += hw/pci/virtio/virtio_rnd.c

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <errno.h>
#include <stddef.h>
#include <sys/queue.h>
#include <stdlib.h>
#include "pcireg.h"
#include "pciaccess.h"
#include "pci_core.h"
#include "pci_util.h"
#include "log.h"
/* find position of specified pci capability register*/
int pci_find_cap(struct pci_device *pdev, const int cap_id)
{
uint8_t cap_pos, cap_data;
uint16_t status = 0;
pci_device_cfg_read_u16(pdev, &status, PCIR_STATUS);
if (status & PCIM_STATUS_CAPPRESENT) {
pci_device_cfg_read_u8(pdev, &cap_pos, PCIR_CAP_PTR);
while (cap_pos != 0 && cap_pos != 0xff) {
pci_device_cfg_read_u8(pdev, &cap_data,
cap_pos + PCICAP_ID);
if (cap_data == cap_id)
return cap_pos;
pci_device_cfg_read_u8(pdev, &cap_pos,
cap_pos + PCICAP_NEXTPTR);
}
}
return 0;
}
/* find extend capability register position from cap_id */
int pci_find_ext_cap(struct pci_device *pdev, int cap_id)
{
int offset = 0;
uint32_t data = 0;
offset = PCIR_EXTCAP;
do {
/* PCI Express Extended Capability must have 4 bytes header */
pci_device_cfg_read_u32(pdev, &data, offset);
if (PCI_EXTCAP_ID(data) == cap_id)
break;
offset = PCI_EXTCAP_NEXTPTR(data);
} while (offset != 0);
return offset;
}
/* find pci-e device type */
int pci_get_pcie_type(struct pci_device *dev)
{
uint8_t data = 0;
int pcie_type;
int pos = 0;
if (dev == NULL)
return -EINVAL;
pos = pci_find_cap(dev, PCIY_EXPRESS);
if (!pos)
return -EINVAL;
pci_device_cfg_read_u8(dev, &data, pos + PCIER_FLAGS);
pcie_type = data & PCIEM_FLAGS_TYPE;
return pcie_type;
}
/* check whether pdev is a pci root port */
bool is_root_port(struct pci_device *pdev)
{
int pcie_type;
pcie_type = pci_get_pcie_type(pdev);
return (pcie_type == PCIEM_TYPE_ROOT_PORT);
}
/* check whether pdev is a bridge */
bool is_bridge(struct pci_device *pdev)
{
uint8_t hdr_type;
pci_device_cfg_read_u8(pdev, &hdr_type, PCIR_HDRTYPE);
return ((hdr_type & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE);
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __PCI_UTIL_H
#define __PCI_UTIL_H
#include <stdbool.h>
#include "pciaccess.h"
int pci_find_cap(struct pci_device *pdev, const int cap_id);
int pci_find_ext_cap(struct pci_device *pdev, int cap_id);
int pci_get_pcie_type(struct pci_device *dev);
bool is_root_port(struct pci_device *pdev);
bool is_bridge(struct pci_device *pdev);
#endif