1 /*
2 * Copyright (C) 2021-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <errno.h>
9 #include <stddef.h>
10 #include <sys/queue.h>
11 #include <stdlib.h>
12
13 #include "pcireg.h"
14 #include "pciaccess.h"
15 #include "pci_core.h"
16 #include "pci_util.h"
17 #include "log.h"
18
19
20 /* find position of specified pci capability register*/
pci_find_cap(struct pci_device * pdev,const int cap_id)21 int pci_find_cap(struct pci_device *pdev, const int cap_id)
22 {
23 uint8_t cap_pos, cap_data;
24 uint16_t status = 0;
25
26 pci_device_cfg_read_u16(pdev, &status, PCIR_STATUS);
27 if (status & PCIM_STATUS_CAPPRESENT) {
28 pci_device_cfg_read_u8(pdev, &cap_pos, PCIR_CAP_PTR);
29
30 while (cap_pos != 0 && cap_pos != 0xff) {
31 pci_device_cfg_read_u8(pdev, &cap_data,
32 cap_pos + PCICAP_ID);
33
34 if (cap_data == cap_id)
35 return cap_pos;
36
37 pci_device_cfg_read_u8(pdev, &cap_pos,
38 cap_pos + PCICAP_NEXTPTR);
39 }
40 }
41
42 return 0;
43 }
44
45 /* find extend capability register position from cap_id */
pci_find_ext_cap(struct pci_device * pdev,int cap_id)46 int pci_find_ext_cap(struct pci_device *pdev, int cap_id)
47 {
48 int offset = 0;
49 uint32_t data = 0;
50
51 offset = PCIR_EXTCAP;
52
53 do {
54 /* PCI Express Extended Capability must have 4 bytes header */
55 pci_device_cfg_read_u32(pdev, &data, offset);
56
57 if (PCI_EXTCAP_ID(data) == cap_id)
58 break;
59
60 offset = PCI_EXTCAP_NEXTPTR(data);
61 } while (offset != 0);
62
63 return offset;
64 }
65
66 /* find pci-e device type */
pci_get_pcie_type(struct pci_device * dev)67 int pci_get_pcie_type(struct pci_device *dev)
68 {
69 uint8_t data = 0;
70 int pcie_type;
71 int pos = 0;
72
73 if (dev == NULL)
74 return -EINVAL;
75
76 pos = pci_find_cap(dev, PCIY_EXPRESS);
77 if (!pos)
78 return -EINVAL;
79
80 pci_device_cfg_read_u8(dev, &data, pos + PCIER_FLAGS);
81 pcie_type = data & PCIEM_FLAGS_TYPE;
82
83 return pcie_type;
84 }
85
86 /* check whether pdev is a pci root port */
is_root_port(struct pci_device * pdev)87 bool is_root_port(struct pci_device *pdev)
88 {
89 int pcie_type;
90
91 pcie_type = pci_get_pcie_type(pdev);
92
93 return (pcie_type == PCIEM_TYPE_ROOT_PORT);
94 }
95
96 /* check whether pdev is multi-function device */
is_mfdev(struct pci_device * pdev)97 bool is_mfdev(struct pci_device *pdev)
98 {
99 uint8_t hdr_type;
100
101 pci_device_cfg_read_u8(pdev, &hdr_type, PCIR_HDRTYPE);
102
103 return ((hdr_type & PCIM_MFDEV) == PCIM_MFDEV);
104 }
105