1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 230edc14bSKonrad Rzeszutek Wilk /* 330edc14bSKonrad Rzeszutek Wilk * PCI Backend - Common data structures for overriding the configuration space 430edc14bSKonrad Rzeszutek Wilk * 530edc14bSKonrad Rzeszutek Wilk * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 630edc14bSKonrad Rzeszutek Wilk */ 730edc14bSKonrad Rzeszutek Wilk 830edc14bSKonrad Rzeszutek Wilk #ifndef __XEN_PCIBACK_CONF_SPACE_H__ 930edc14bSKonrad Rzeszutek Wilk #define __XEN_PCIBACK_CONF_SPACE_H__ 1030edc14bSKonrad Rzeszutek Wilk 1130edc14bSKonrad Rzeszutek Wilk #include <linux/list.h> 1230edc14bSKonrad Rzeszutek Wilk #include <linux/err.h> 1330edc14bSKonrad Rzeszutek Wilk 1430edc14bSKonrad Rzeszutek Wilk /* conf_field_init can return an errno in a ptr with ERR_PTR() */ 1530edc14bSKonrad Rzeszutek Wilk typedef void *(*conf_field_init) (struct pci_dev *dev, int offset); 1630edc14bSKonrad Rzeszutek Wilk typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data); 1730edc14bSKonrad Rzeszutek Wilk typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data); 1830edc14bSKonrad Rzeszutek Wilk 1930edc14bSKonrad Rzeszutek Wilk typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value, 2030edc14bSKonrad Rzeszutek Wilk void *data); 2130edc14bSKonrad Rzeszutek Wilk typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value, 2230edc14bSKonrad Rzeszutek Wilk void *data); 2330edc14bSKonrad Rzeszutek Wilk typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value, 2430edc14bSKonrad Rzeszutek Wilk void *data); 2530edc14bSKonrad Rzeszutek Wilk typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value, 2630edc14bSKonrad Rzeszutek Wilk void *data); 2730edc14bSKonrad Rzeszutek Wilk typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value, 2830edc14bSKonrad Rzeszutek Wilk void *data); 2930edc14bSKonrad Rzeszutek Wilk typedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value, 3030edc14bSKonrad Rzeszutek Wilk void *data); 3130edc14bSKonrad Rzeszutek Wilk 3230edc14bSKonrad Rzeszutek Wilk /* These are the fields within the configuration space which we 3330edc14bSKonrad Rzeszutek Wilk * are interested in intercepting reads/writes to and changing their 3430edc14bSKonrad Rzeszutek Wilk * values. 3530edc14bSKonrad Rzeszutek Wilk */ 3630edc14bSKonrad Rzeszutek Wilk struct config_field { 3730edc14bSKonrad Rzeszutek Wilk unsigned int offset; 3830edc14bSKonrad Rzeszutek Wilk unsigned int size; 3930edc14bSKonrad Rzeszutek Wilk unsigned int mask; 4030edc14bSKonrad Rzeszutek Wilk conf_field_init init; 4130edc14bSKonrad Rzeszutek Wilk conf_field_reset reset; 4230edc14bSKonrad Rzeszutek Wilk conf_field_free release; 4330edc14bSKonrad Rzeszutek Wilk void (*clean) (struct config_field *field); 4430edc14bSKonrad Rzeszutek Wilk union { 4530edc14bSKonrad Rzeszutek Wilk struct { 4630edc14bSKonrad Rzeszutek Wilk conf_dword_write write; 4730edc14bSKonrad Rzeszutek Wilk conf_dword_read read; 4830edc14bSKonrad Rzeszutek Wilk } dw; 4930edc14bSKonrad Rzeszutek Wilk struct { 5030edc14bSKonrad Rzeszutek Wilk conf_word_write write; 5130edc14bSKonrad Rzeszutek Wilk conf_word_read read; 5230edc14bSKonrad Rzeszutek Wilk } w; 5330edc14bSKonrad Rzeszutek Wilk struct { 5430edc14bSKonrad Rzeszutek Wilk conf_byte_write write; 5530edc14bSKonrad Rzeszutek Wilk conf_byte_read read; 5630edc14bSKonrad Rzeszutek Wilk } b; 5730edc14bSKonrad Rzeszutek Wilk } u; 5830edc14bSKonrad Rzeszutek Wilk struct list_head list; 5930edc14bSKonrad Rzeszutek Wilk }; 6030edc14bSKonrad Rzeszutek Wilk 6130edc14bSKonrad Rzeszutek Wilk struct config_field_entry { 6230edc14bSKonrad Rzeszutek Wilk struct list_head list; 6330edc14bSKonrad Rzeszutek Wilk const struct config_field *field; 6430edc14bSKonrad Rzeszutek Wilk unsigned int base_offset; 6530edc14bSKonrad Rzeszutek Wilk void *data; 6630edc14bSKonrad Rzeszutek Wilk }; 6730edc14bSKonrad Rzeszutek Wilk 68*476878e4SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_NONE (1<<0) 69*476878e4SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_INTX (1<<1) 70*476878e4SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_MSI (1<<2) 71*476878e4SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_MSIX (1<<3) 72*476878e4SMarek Marczykowski-Górecki 738014bcc8SBen Hutchings extern bool xen_pcibk_permissive; 74af6fc858SJan Beulich 7530edc14bSKonrad Rzeszutek Wilk #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) 7630edc14bSKonrad Rzeszutek Wilk 7730edc14bSKonrad Rzeszutek Wilk /* Add fields to a device - the add_fields macro expects to get a pointer to 7830edc14bSKonrad Rzeszutek Wilk * the first entry in an array (of which the ending is marked by size==0) 7930edc14bSKonrad Rzeszutek Wilk */ 80a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_add_field_offset(struct pci_dev *dev, 8130edc14bSKonrad Rzeszutek Wilk const struct config_field *field, 8230edc14bSKonrad Rzeszutek Wilk unsigned int offset); 8330edc14bSKonrad Rzeszutek Wilk 84a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_field(struct pci_dev *dev, 8530edc14bSKonrad Rzeszutek Wilk const struct config_field *field) 8630edc14bSKonrad Rzeszutek Wilk { 87a92336a1SKonrad Rzeszutek Wilk return xen_pcibk_config_add_field_offset(dev, field, 0); 8830edc14bSKonrad Rzeszutek Wilk } 8930edc14bSKonrad Rzeszutek Wilk 90a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_fields(struct pci_dev *dev, 9130edc14bSKonrad Rzeszutek Wilk const struct config_field *field) 9230edc14bSKonrad Rzeszutek Wilk { 9330edc14bSKonrad Rzeszutek Wilk int i, err = 0; 9430edc14bSKonrad Rzeszutek Wilk for (i = 0; field[i].size != 0; i++) { 95a92336a1SKonrad Rzeszutek Wilk err = xen_pcibk_config_add_field(dev, &field[i]); 9630edc14bSKonrad Rzeszutek Wilk if (err) 9730edc14bSKonrad Rzeszutek Wilk break; 9830edc14bSKonrad Rzeszutek Wilk } 9930edc14bSKonrad Rzeszutek Wilk return err; 10030edc14bSKonrad Rzeszutek Wilk } 10130edc14bSKonrad Rzeszutek Wilk 102a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev, 10330edc14bSKonrad Rzeszutek Wilk const struct config_field *field, 10430edc14bSKonrad Rzeszutek Wilk unsigned int offset) 10530edc14bSKonrad Rzeszutek Wilk { 10630edc14bSKonrad Rzeszutek Wilk int i, err = 0; 10730edc14bSKonrad Rzeszutek Wilk for (i = 0; field[i].size != 0; i++) { 108a92336a1SKonrad Rzeszutek Wilk err = xen_pcibk_config_add_field_offset(dev, &field[i], offset); 10930edc14bSKonrad Rzeszutek Wilk if (err) 11030edc14bSKonrad Rzeszutek Wilk break; 11130edc14bSKonrad Rzeszutek Wilk } 11230edc14bSKonrad Rzeszutek Wilk return err; 11330edc14bSKonrad Rzeszutek Wilk } 11430edc14bSKonrad Rzeszutek Wilk 11530edc14bSKonrad Rzeszutek Wilk /* Read/Write the real configuration space */ 116a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value, 11730edc14bSKonrad Rzeszutek Wilk void *data); 118a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value, 11930edc14bSKonrad Rzeszutek Wilk void *data); 120a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value, 12130edc14bSKonrad Rzeszutek Wilk void *data); 122a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value, 12330edc14bSKonrad Rzeszutek Wilk void *data); 124a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value, 12530edc14bSKonrad Rzeszutek Wilk void *data); 126a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value, 12730edc14bSKonrad Rzeszutek Wilk void *data); 12830edc14bSKonrad Rzeszutek Wilk 129a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_capability_init(void); 13030edc14bSKonrad Rzeszutek Wilk 131a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_header_add_fields(struct pci_dev *dev); 132a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_capability_add_fields(struct pci_dev *dev); 13330edc14bSKonrad Rzeszutek Wilk 134*476878e4SMarek Marczykowski-Górecki int xen_pcibk_get_interrupt_type(struct pci_dev *dev); 135*476878e4SMarek Marczykowski-Górecki 13630edc14bSKonrad Rzeszutek Wilk #endif /* __XEN_PCIBACK_CONF_SPACE_H__ */ 137