xref: /kvm-unit-tests/lib/pci.h (revision 80e8b3d82fc53befe77728786530d286a78d0d78)
1*80e8b3d8SCornelia Huck #ifndef _PCI_H_
2*80e8b3d8SCornelia Huck #define _PCI_H_
3456c55bcSAndrew Jones /*
4456c55bcSAndrew Jones  * API for scanning a PCI bus for a given device, as well to access
5456c55bcSAndrew Jones  * BAR registers.
6456c55bcSAndrew Jones  *
7456c55bcSAndrew Jones  * Copyright (C) 2013, Red Hat Inc, Michael S. Tsirkin <mst@redhat.com>
8456c55bcSAndrew Jones  *
9456c55bcSAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
10456c55bcSAndrew Jones  */
114932b58aSMichael S. Tsirkin #include "libcflat.h"
124932b58aSMichael S. Tsirkin 
134932b58aSMichael S. Tsirkin typedef uint16_t pcidevaddr_t;
144932b58aSMichael S. Tsirkin enum {
15d3a8ad49SAndrew Jones 	PCIDEVADDR_INVALID = 0xffff,
164932b58aSMichael S. Tsirkin };
17ebb58e7eSAlexander Gordeev 
18e954ce23SPeter Xu #define PCI_BAR_NUM                     6
194d6cefa9SPeter Xu #define PCI_DEVFN_MAX                   256
204d6cefa9SPeter Xu 
2168cf12d2SAlexander Gordeev #define ASSERT_BAR_NUM(bar_num)	\
2268cf12d2SAlexander Gordeev 	do { assert(bar_num >= 0 && bar_num < PCI_BAR_NUM); } while (0)
2368cf12d2SAlexander Gordeev 
2492d2c192SPeter Xu #define PCI_BDF_GET_DEVFN(x)            ((x) & 0xff)
2592d2c192SPeter Xu #define PCI_BDF_GET_BUS(x)              (((x) >> 8) & 0xff)
2692d2c192SPeter Xu 
274d6cefa9SPeter Xu struct pci_dev {
284d6cefa9SPeter Xu 	uint16_t bdf;
29903b0516SPeter Xu 	uint16_t msi_offset;
30e954ce23SPeter Xu 	phys_addr_t resource[PCI_BAR_NUM];
314d6cefa9SPeter Xu };
324d6cefa9SPeter Xu 
334d6cefa9SPeter Xu extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf);
3466082ed6SPeter Xu extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr);
35cdccea7cSAndrew Jones typedef void (*pci_cap_handler_t)(struct pci_dev *dev, int cap_offset, int cap_id);
36cdccea7cSAndrew Jones extern void pci_cap_walk(struct pci_dev *dev, pci_cap_handler_t handler);
3766082ed6SPeter Xu extern void pci_enable_defaults(struct pci_dev *dev);
38903b0516SPeter Xu extern bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr,
39903b0516SPeter Xu 			  uint32_t msi_data);
404d6cefa9SPeter Xu 
4192d2c192SPeter Xu typedef phys_addr_t iova_t;
4292d2c192SPeter Xu 
4333d78b07SAlexander Gordeev extern bool pci_probe(void);
44e4611520SAlexander Gordeev extern void pci_print(void);
45e1cad5c8SAlexander Gordeev extern bool pci_dev_exists(pcidevaddr_t dev);
46fa80a74dSAlexander Gordeev extern pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id);
472455ef20SAlexander Gordeev 
482455ef20SAlexander Gordeev /*
492455ef20SAlexander Gordeev  * @bar_num in all BAR access functions below is the index of the 32-bit
502455ef20SAlexander Gordeev  * register starting from the PCI_BASE_ADDRESS_0 offset.
512455ef20SAlexander Gordeev  *
522455ef20SAlexander Gordeev  * In cases where the BAR size is 64-bit, a caller should still provide
532455ef20SAlexander Gordeev  * @bar_num in terms of 32-bit words. For example, if a device has a 64-bit
542455ef20SAlexander Gordeev  * BAR#0 and a 32-bit BAR#1, then caller should provide 2 to address BAR#1,
552455ef20SAlexander Gordeev  * not 1.
562455ef20SAlexander Gordeev  *
572455ef20SAlexander Gordeev  * It is expected the caller is aware of the device BAR layout and never
582455ef20SAlexander Gordeev  * tries to address the middle of a 64-bit register.
592455ef20SAlexander Gordeev  */
604d6cefa9SPeter Xu extern phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num);
614d6cefa9SPeter Xu extern void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr);
624d6cefa9SPeter Xu extern phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num);
634d6cefa9SPeter Xu extern uint32_t pci_bar_get(struct pci_dev *dev, int bar_num);
6433d78b07SAlexander Gordeev extern uint32_t pci_bar_mask(uint32_t bar);
654d6cefa9SPeter Xu extern bool pci_bar_is64(struct pci_dev *dev, int bar_num);
664d6cefa9SPeter Xu extern bool pci_bar_is_memory(struct pci_dev *dev, int bar_num);
674d6cefa9SPeter Xu extern bool pci_bar_is_valid(struct pci_dev *dev, int bar_num);
684d6cefa9SPeter Xu extern void pci_bar_print(struct pci_dev *dev, int bar_num);
69cb026028SAlexander Gordeev extern void pci_dev_print_id(struct pci_dev *dev);
70cb026028SAlexander Gordeev extern void pci_dev_print(struct pci_dev *dev);
71352096c7SPeter Xu extern uint8_t pci_intx_line(struct pci_dev *dev);
7219daf1c5SPeter Xu void pci_msi_set_enable(struct pci_dev *dev, bool enabled);
734932b58aSMichael S. Tsirkin 
747d4c532dSPeter Xu extern int pci_testdev(void);
75e4125c0cSAlexander Gordeev 
76289ebf8fSAndrew Jones /*
77289ebf8fSAndrew Jones  * pci-testdev is a driver for the pci-testdev qemu pci device. The
78289ebf8fSAndrew Jones  * device enables testing mmio and portio exits, and measuring their
79289ebf8fSAndrew Jones  * speed.
80289ebf8fSAndrew Jones  */
81289ebf8fSAndrew Jones #define PCI_VENDOR_ID_REDHAT		0x1b36
82289ebf8fSAndrew Jones #define PCI_DEVICE_ID_REDHAT_TEST	0x0005
83289ebf8fSAndrew Jones 
84e4125c0cSAlexander Gordeev /*
85e4125c0cSAlexander Gordeev  * pci-testdev supports at least three types of tests (via mmio and
86e4125c0cSAlexander Gordeev  * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd
87e4125c0cSAlexander Gordeev  */
88e954ce23SPeter Xu #define PCI_TESTDEV_BAR_MEM		0
89e954ce23SPeter Xu #define PCI_TESTDEV_BAR_IO		1
90289ebf8fSAndrew Jones #define PCI_TESTDEV_NUM_BARS		2
91e4125c0cSAlexander Gordeev #define PCI_TESTDEV_NUM_TESTS		3
92289ebf8fSAndrew Jones 
93289ebf8fSAndrew Jones struct pci_test_dev_hdr {
94289ebf8fSAndrew Jones 	uint8_t  test;
95289ebf8fSAndrew Jones 	uint8_t  width;
96289ebf8fSAndrew Jones 	uint8_t  pad0[2];
97289ebf8fSAndrew Jones 	uint32_t offset;
98289ebf8fSAndrew Jones 	uint32_t data;
99289ebf8fSAndrew Jones 	uint32_t count;
100289ebf8fSAndrew Jones 	uint8_t  name[];
101289ebf8fSAndrew Jones };
102289ebf8fSAndrew Jones 
103e4611520SAlexander Gordeev #define  PCI_HEADER_TYPE_MASK		0x7f
104e4611520SAlexander Gordeev 
105*80e8b3d8SCornelia Huck #endif /* _PCI_H_ */
106