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*69086bd6SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_NONE (0)
69*69086bd6SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_INTX (1<<0)
70*69086bd6SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_MSI (1<<1)
71*69086bd6SMarek Marczykowski-Górecki #define INTERRUPT_TYPE_MSIX (1<<2)
72476878e4SMarek 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
xen_pcibk_config_add_field(struct pci_dev * dev,const struct config_field * field)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
xen_pcibk_config_add_fields(struct pci_dev * dev,const struct config_field * field)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
xen_pcibk_config_add_fields_offset(struct pci_dev * dev,const struct config_field * field,unsigned int offset)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
134476878e4SMarek Marczykowski-Górecki int xen_pcibk_get_interrupt_type(struct pci_dev *dev);
135476878e4SMarek Marczykowski-Górecki
13630edc14bSKonrad Rzeszutek Wilk #endif /* __XEN_PCIBACK_CONF_SPACE_H__ */
137