160742802SPekka Enberg #ifndef KVM__PCI_H 260742802SPekka Enberg #define KVM__PCI_H 360742802SPekka Enberg 43fdf659dSSasha Levin #include <linux/types.h> 51de74957SSasha Levin #include <linux/kvm.h> 620c64ecaSPekka Enberg #include <linux/pci_regs.h> 71de74957SSasha Levin #include <linux/msi.h> 8aa73be70SMatt Evans #include <endian.h> 976f9c841SCyrill Gorcunov 10*d0297a59SMatt Evans #include "kvm/kvm.h" 11*d0297a59SMatt Evans 129d755a36SMatt Evans #define PCI_MAX_DEVICES 256 134402a581SPekka Enberg /* 144402a581SPekka Enberg * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1. 154402a581SPekka Enberg * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for 164402a581SPekka Enberg * details. 174402a581SPekka Enberg */ 18305b72ceSCyrill Gorcunov #define PCI_CONFIG_ADDRESS 0xcf8 19305b72ceSCyrill Gorcunov #define PCI_CONFIG_DATA 0xcfc 202b9e4709SCyrill Gorcunov #define PCI_CONFIG_BUS_FORWARD 0xcfa 2195d13a52SSasha Levin #define PCI_IO_SIZE 0x100 22305b72ceSCyrill Gorcunov 23aa73be70SMatt Evans union pci_config_address { 24aa73be70SMatt Evans struct { 25aa73be70SMatt Evans #if __BYTE_ORDER == __LITTLE_ENDIAN 26*d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 274402a581SPekka Enberg unsigned register_number : 6; /* 7 .. 2 */ 284402a581SPekka Enberg unsigned function_number : 3; /* 10 .. 8 */ 294402a581SPekka Enberg unsigned device_number : 5; /* 15 .. 11 */ 304402a581SPekka Enberg unsigned bus_number : 8; /* 23 .. 16 */ 314402a581SPekka Enberg unsigned reserved : 7; /* 30 .. 24 */ 324402a581SPekka Enberg unsigned enable_bit : 1; /* 31 */ 33aa73be70SMatt Evans #else 34aa73be70SMatt Evans unsigned enable_bit : 1; /* 31 */ 35aa73be70SMatt Evans unsigned reserved : 7; /* 30 .. 24 */ 36aa73be70SMatt Evans unsigned bus_number : 8; /* 23 .. 16 */ 37aa73be70SMatt Evans unsigned device_number : 5; /* 15 .. 11 */ 38aa73be70SMatt Evans unsigned function_number : 3; /* 10 .. 8 */ 39aa73be70SMatt Evans unsigned register_number : 6; /* 7 .. 2 */ 40*d0297a59SMatt Evans unsigned reg_offset : 2; /* 1 .. 0 */ 41aa73be70SMatt Evans #endif 42aa73be70SMatt Evans }; 43aa73be70SMatt Evans u32 w; 444402a581SPekka Enberg }; 454402a581SPekka Enberg 46bc485053SSasha Levin struct msix_table { 471de74957SSasha Levin struct msi_msg msg; 48bc485053SSasha Levin u32 ctrl; 49bc485053SSasha Levin }; 50bc485053SSasha Levin 51bc485053SSasha Levin struct msix_cap { 52bc485053SSasha Levin u8 cap; 53bc485053SSasha Levin u8 next; 5406f48103SSasha Levin u16 ctrl; 55bc485053SSasha Levin u32 table_offset; 5606f48103SSasha Levin u32 pba_offset; 57bc485053SSasha Levin }; 58bc485053SSasha Levin 5976f9c841SCyrill Gorcunov struct pci_device_header { 603fdf659dSSasha Levin u16 vendor_id; 613fdf659dSSasha Levin u16 device_id; 623fdf659dSSasha Levin u16 command; 633fdf659dSSasha Levin u16 status; 64aa73be70SMatt Evans u8 revision_id; 65aa73be70SMatt Evans u8 class[3]; 663fdf659dSSasha Levin u8 cacheline_size; 673fdf659dSSasha Levin u8 latency_timer; 683fdf659dSSasha Levin u8 header_type; 693fdf659dSSasha Levin u8 bist; 703fdf659dSSasha Levin u32 bar[6]; 713fdf659dSSasha Levin u32 card_bus; 723fdf659dSSasha Levin u16 subsys_vendor_id; 733fdf659dSSasha Levin u16 subsys_id; 743fdf659dSSasha Levin u32 exp_rom_bar; 75aa73be70SMatt Evans u8 capabilities; 76aa73be70SMatt Evans u8 reserved1[3]; 773fdf659dSSasha Levin u32 reserved2; 783fdf659dSSasha Levin u8 irq_line; 793fdf659dSSasha Levin u8 irq_pin; 803fdf659dSSasha Levin u8 min_gnt; 813fdf659dSSasha Levin u8 max_lat; 82bc485053SSasha Levin struct msix_cap msix; 83c64f7ff0SSasha Levin u8 empty[136]; /* Rest of PCI config space */ 84c64f7ff0SSasha Levin u32 bar_size[6]; 85aa73be70SMatt Evans } __attribute__((packed)); 8676f9c841SCyrill Gorcunov 8760742802SPekka Enberg void pci__init(void); 883fdf659dSSasha Levin void pci__register(struct pci_device_header *dev, u8 dev_num); 89*d0297a59SMatt Evans struct pci_device_header *pci__find_dev(u8 dev_num); 9095d13a52SSasha Levin u32 pci_get_io_space_block(u32 size); 91*d0297a59SMatt Evans void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size); 92*d0297a59SMatt Evans void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size); 9360742802SPekka Enberg 9460742802SPekka Enberg #endif /* KVM__PCI_H */ 95