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