conf_space.h (4065B)
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() */ 15typedef void *(*conf_field_init) (struct pci_dev *dev, int offset); 16typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data); 17typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data); 18 19typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value, 20 void *data); 21typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value, 22 void *data); 23typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value, 24 void *data); 25typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value, 26 void *data); 27typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value, 28 void *data); 29typedef 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 */ 36struct 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 61struct 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 (0) 69#define INTERRUPT_TYPE_INTX (1<<0) 70#define INTERRUPT_TYPE_MSI (1<<1) 71#define INTERRUPT_TYPE_MSIX (1<<2) 72 73extern 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 */ 80int xen_pcibk_config_add_field_offset(struct pci_dev *dev, 81 const struct config_field *field, 82 unsigned int offset); 83 84static 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 90static 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 102static 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 */ 116int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value, 117 void *data); 118int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value, 119 void *data); 120int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value, 121 void *data); 122int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value, 123 void *data); 124int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value, 125 void *data); 126int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value, 127 void *data); 128 129int xen_pcibk_config_capability_init(void); 130 131int xen_pcibk_config_header_add_fields(struct pci_dev *dev); 132int xen_pcibk_config_capability_add_fields(struct pci_dev *dev); 133 134int xen_pcibk_get_interrupt_type(struct pci_dev *dev); 135 136#endif /* __XEN_PCIBACK_CONF_SPACE_H__ */