1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * PCI Backend - Common data structures for overriding the configuration space 4 * 5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 6 */ 7 8 #ifndef __XEN_PCIBACK_CONF_SPACE_H__ 9 #define __XEN_PCIBACK_CONF_SPACE_H__ 10 11 #include <linux/list.h> 12 #include <linux/err.h> 13 14 /* conf_field_init can return an errno in a ptr with ERR_PTR() */ 15 typedef void *(*conf_field_init) (struct pci_dev *dev, int offset); 16 typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data); 17 typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data); 18 19 typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value, 20 void *data); 21 typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value, 22 void *data); 23 typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value, 24 void *data); 25 typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value, 26 void *data); 27 typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value, 28 void *data); 29 typedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value, 30 void *data); 31 32 /* These are the fields within the configuration space which we 33 * are interested in intercepting reads/writes to and changing their 34 * values. 35 */ 36 struct config_field { 37 unsigned int offset; 38 unsigned int size; 39 unsigned int mask; 40 conf_field_init init; 41 conf_field_reset reset; 42 conf_field_free release; 43 void (*clean) (struct config_field *field); 44 union { 45 struct { 46 conf_dword_write write; 47 conf_dword_read read; 48 } dw; 49 struct { 50 conf_word_write write; 51 conf_word_read read; 52 } w; 53 struct { 54 conf_byte_write write; 55 conf_byte_read read; 56 } b; 57 } u; 58 struct list_head list; 59 }; 60 61 struct config_field_entry { 62 struct list_head list; 63 const struct config_field *field; 64 unsigned int base_offset; 65 void *data; 66 }; 67 68 #define INTERRUPT_TYPE_NONE (1<<0) 69 #define INTERRUPT_TYPE_INTX (1<<1) 70 #define INTERRUPT_TYPE_MSI (1<<2) 71 #define INTERRUPT_TYPE_MSIX (1<<3) 72 73 extern bool xen_pcibk_permissive; 74 75 #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) 76 77 /* Add fields to a device - the add_fields macro expects to get a pointer to 78 * the first entry in an array (of which the ending is marked by size==0) 79 */ 80 int xen_pcibk_config_add_field_offset(struct pci_dev *dev, 81 const struct config_field *field, 82 unsigned int offset); 83 84 static inline int xen_pcibk_config_add_field(struct pci_dev *dev, 85 const struct config_field *field) 86 { 87 return xen_pcibk_config_add_field_offset(dev, field, 0); 88 } 89 90 static inline int xen_pcibk_config_add_fields(struct pci_dev *dev, 91 const struct config_field *field) 92 { 93 int i, err = 0; 94 for (i = 0; field[i].size != 0; i++) { 95 err = xen_pcibk_config_add_field(dev, &field[i]); 96 if (err) 97 break; 98 } 99 return err; 100 } 101 102 static inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev, 103 const struct config_field *field, 104 unsigned int offset) 105 { 106 int i, err = 0; 107 for (i = 0; field[i].size != 0; i++) { 108 err = xen_pcibk_config_add_field_offset(dev, &field[i], offset); 109 if (err) 110 break; 111 } 112 return err; 113 } 114 115 /* Read/Write the real configuration space */ 116 int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value, 117 void *data); 118 int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value, 119 void *data); 120 int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value, 121 void *data); 122 int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value, 123 void *data); 124 int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value, 125 void *data); 126 int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value, 127 void *data); 128 129 int xen_pcibk_config_capability_init(void); 130 131 int xen_pcibk_config_header_add_fields(struct pci_dev *dev); 132 int xen_pcibk_config_capability_add_fields(struct pci_dev *dev); 133 134 int xen_pcibk_get_interrupt_type(struct pci_dev *dev); 135 136 #endif /* __XEN_PCIBACK_CONF_SPACE_H__ */ 137