Cornelia Huck | 80e8b3d | 2021-06-10 15:59:36 +0200 | [diff] [blame] | 1 | #ifndef _PCI_H_ |
| 2 | #define _PCI_H_ |
Andrew Jones | 456c55b | 2016-01-18 19:01:02 +0100 | [diff] [blame] | 3 | /* |
| 4 | * API for scanning a PCI bus for a given device, as well to access |
| 5 | * BAR registers. |
| 6 | * |
| 7 | * Copyright (C) 2013, Red Hat Inc, Michael S. Tsirkin <mst@redhat.com> |
| 8 | * |
| 9 | * This work is licensed under the terms of the GNU LGPL, version 2. |
| 10 | */ |
Michael S. Tsirkin | 4932b58 | 2013-04-03 11:52:33 +0300 | [diff] [blame] | 11 | #include "libcflat.h" |
| 12 | |
| 13 | typedef uint16_t pcidevaddr_t; |
| 14 | enum { |
Alexander Gordeev | ebb58e7 | 2016-11-07 11:14:33 +0100 | [diff] [blame] | 15 | PCIDEVADDR_INVALID = 0xffff, |
Michael S. Tsirkin | 4932b58 | 2013-04-03 11:52:33 +0300 | [diff] [blame] | 16 | }; |
Alexander Gordeev | ebb58e7 | 2016-11-07 11:14:33 +0100 | [diff] [blame] | 17 | |
Peter Xu | e954ce2 | 2016-12-12 11:08:15 +0800 | [diff] [blame] | 18 | #define PCI_BAR_NUM 6 |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 19 | #define PCI_DEVFN_MAX 256 |
| 20 | |
Alexander Gordeev | 68cf12d | 2017-03-27 16:32:14 +0200 | [diff] [blame] | 21 | #define ASSERT_BAR_NUM(bar_num) \ |
| 22 | do { assert(bar_num >= 0 && bar_num < PCI_BAR_NUM); } while (0) |
| 23 | |
Peter Xu | 92d2c19 | 2016-12-12 11:08:18 +0800 | [diff] [blame] | 24 | #define PCI_BDF_GET_DEVFN(x) ((x) & 0xff) |
| 25 | #define PCI_BDF_GET_BUS(x) (((x) >> 8) & 0xff) |
| 26 | |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 27 | struct pci_dev { |
| 28 | uint16_t bdf; |
Peter Xu | 903b051 | 2016-12-12 11:08:19 +0800 | [diff] [blame] | 29 | uint16_t msi_offset; |
Peter Xu | e954ce2 | 2016-12-12 11:08:15 +0800 | [diff] [blame] | 30 | phys_addr_t resource[PCI_BAR_NUM]; |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 31 | }; |
| 32 | |
| 33 | extern void pci_dev_init(struct pci_dev *dev, pcidevaddr_t bdf); |
Peter Xu | 66082ed | 2016-12-12 11:08:16 +0800 | [diff] [blame] | 34 | extern void pci_cmd_set_clr(struct pci_dev *dev, uint16_t set, uint16_t clr); |
Andrew Jones | cdccea7 | 2017-01-16 16:32:13 +0100 | [diff] [blame] | 35 | typedef void (*pci_cap_handler_t)(struct pci_dev *dev, int cap_offset, int cap_id); |
| 36 | extern void pci_cap_walk(struct pci_dev *dev, pci_cap_handler_t handler); |
Peter Xu | 66082ed | 2016-12-12 11:08:16 +0800 | [diff] [blame] | 37 | extern void pci_enable_defaults(struct pci_dev *dev); |
Peter Xu | 903b051 | 2016-12-12 11:08:19 +0800 | [diff] [blame] | 38 | extern bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, |
| 39 | uint32_t msi_data); |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 40 | |
Peter Xu | 92d2c19 | 2016-12-12 11:08:18 +0800 | [diff] [blame] | 41 | typedef phys_addr_t iova_t; |
| 42 | |
Alexander Gordeev | 33d78b0 | 2016-11-07 11:14:42 +0100 | [diff] [blame] | 43 | extern bool pci_probe(void); |
Alexander Gordeev | e461152 | 2016-11-07 11:14:41 +0100 | [diff] [blame] | 44 | extern void pci_print(void); |
Alexander Gordeev | e1cad5c | 2016-11-07 11:14:40 +0100 | [diff] [blame] | 45 | extern bool pci_dev_exists(pcidevaddr_t dev); |
Alexander Gordeev | fa80a74 | 2016-11-07 11:14:35 +0100 | [diff] [blame] | 46 | extern pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id); |
Alexander Gordeev | 2455ef2 | 2016-11-07 11:14:38 +0100 | [diff] [blame] | 47 | |
| 48 | /* |
| 49 | * @bar_num in all BAR access functions below is the index of the 32-bit |
| 50 | * register starting from the PCI_BASE_ADDRESS_0 offset. |
| 51 | * |
| 52 | * In cases where the BAR size is 64-bit, a caller should still provide |
| 53 | * @bar_num in terms of 32-bit words. For example, if a device has a 64-bit |
| 54 | * BAR#0 and a 32-bit BAR#1, then caller should provide 2 to address BAR#1, |
| 55 | * not 1. |
| 56 | * |
| 57 | * It is expected the caller is aware of the device BAR layout and never |
| 58 | * tries to address the middle of a 64-bit register. |
| 59 | */ |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 60 | extern phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num); |
| 61 | extern void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr); |
| 62 | extern phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num); |
| 63 | extern uint32_t pci_bar_get(struct pci_dev *dev, int bar_num); |
Alexander Gordeev | 33d78b0 | 2016-11-07 11:14:42 +0100 | [diff] [blame] | 64 | extern uint32_t pci_bar_mask(uint32_t bar); |
Peter Xu | 4d6cefa | 2016-12-12 11:08:14 +0800 | [diff] [blame] | 65 | extern bool pci_bar_is64(struct pci_dev *dev, int bar_num); |
| 66 | extern bool pci_bar_is_memory(struct pci_dev *dev, int bar_num); |
| 67 | extern bool pci_bar_is_valid(struct pci_dev *dev, int bar_num); |
| 68 | extern void pci_bar_print(struct pci_dev *dev, int bar_num); |
Alexander Gordeev | cb02602 | 2017-02-28 19:08:30 +0100 | [diff] [blame] | 69 | extern void pci_dev_print_id(struct pci_dev *dev); |
| 70 | extern void pci_dev_print(struct pci_dev *dev); |
Peter Xu | 352096c | 2016-12-30 16:55:53 +0800 | [diff] [blame] | 71 | extern uint8_t pci_intx_line(struct pci_dev *dev); |
Peter Xu | 19daf1c | 2016-12-30 16:55:54 +0800 | [diff] [blame] | 72 | void pci_msi_set_enable(struct pci_dev *dev, bool enabled); |
Michael S. Tsirkin | 4932b58 | 2013-04-03 11:52:33 +0300 | [diff] [blame] | 73 | |
Peter Xu | 7d4c532 | 2016-12-12 11:08:07 +0800 | [diff] [blame] | 74 | extern int pci_testdev(void); |
Alexander Gordeev | e4125c0 | 2016-11-07 11:14:43 +0100 | [diff] [blame] | 75 | |
Andrew Jones | 289ebf8 | 2016-01-18 19:01:03 +0100 | [diff] [blame] | 76 | /* |
| 77 | * pci-testdev is a driver for the pci-testdev qemu pci device. The |
| 78 | * device enables testing mmio and portio exits, and measuring their |
| 79 | * speed. |
| 80 | */ |
| 81 | #define PCI_VENDOR_ID_REDHAT 0x1b36 |
| 82 | #define PCI_DEVICE_ID_REDHAT_TEST 0x0005 |
| 83 | |
Alexander Gordeev | e4125c0 | 2016-11-07 11:14:43 +0100 | [diff] [blame] | 84 | /* |
| 85 | * pci-testdev supports at least three types of tests (via mmio and |
| 86 | * portio BARs): no-eventfd, wildcard-eventfd and datamatch-eventfd |
| 87 | */ |
Peter Xu | e954ce2 | 2016-12-12 11:08:15 +0800 | [diff] [blame] | 88 | #define PCI_TESTDEV_BAR_MEM 0 |
| 89 | #define PCI_TESTDEV_BAR_IO 1 |
Andrew Jones | 289ebf8 | 2016-01-18 19:01:03 +0100 | [diff] [blame] | 90 | #define PCI_TESTDEV_NUM_BARS 2 |
Alexander Gordeev | e4125c0 | 2016-11-07 11:14:43 +0100 | [diff] [blame] | 91 | #define PCI_TESTDEV_NUM_TESTS 3 |
Andrew Jones | 289ebf8 | 2016-01-18 19:01:03 +0100 | [diff] [blame] | 92 | |
| 93 | struct pci_test_dev_hdr { |
| 94 | uint8_t test; |
| 95 | uint8_t width; |
| 96 | uint8_t pad0[2]; |
| 97 | uint32_t offset; |
| 98 | uint32_t data; |
| 99 | uint32_t count; |
| 100 | uint8_t name[]; |
| 101 | }; |
| 102 | |
Alexander Gordeev | e461152 | 2016-11-07 11:14:41 +0100 | [diff] [blame] | 103 | #define PCI_HEADER_TYPE_MASK 0x7f |
| 104 | |
Cornelia Huck | 80e8b3d | 2021-06-10 15:59:36 +0200 | [diff] [blame] | 105 | #endif /* _PCI_H_ */ |