xref: /linux/drivers/xen/xen-pciback/conf_space.h (revision b24413180f5600bcb3bb70fbed5cf186b60864bd)
1*b2441318SGreg 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 
688014bcc8SBen Hutchings extern bool xen_pcibk_permissive;
69af6fc858SJan Beulich 
7030edc14bSKonrad Rzeszutek Wilk #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
7130edc14bSKonrad Rzeszutek Wilk 
7230edc14bSKonrad Rzeszutek Wilk /* Add fields to a device - the add_fields macro expects to get a pointer to
7330edc14bSKonrad Rzeszutek Wilk  * the first entry in an array (of which the ending is marked by size==0)
7430edc14bSKonrad Rzeszutek Wilk  */
75a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
7630edc14bSKonrad Rzeszutek Wilk 				    const struct config_field *field,
7730edc14bSKonrad Rzeszutek Wilk 				    unsigned int offset);
7830edc14bSKonrad Rzeszutek Wilk 
79a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_field(struct pci_dev *dev,
8030edc14bSKonrad Rzeszutek Wilk 					   const struct config_field *field)
8130edc14bSKonrad Rzeszutek Wilk {
82a92336a1SKonrad Rzeszutek Wilk 	return xen_pcibk_config_add_field_offset(dev, field, 0);
8330edc14bSKonrad Rzeszutek Wilk }
8430edc14bSKonrad Rzeszutek Wilk 
85a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_fields(struct pci_dev *dev,
8630edc14bSKonrad Rzeszutek Wilk 					    const struct config_field *field)
8730edc14bSKonrad Rzeszutek Wilk {
8830edc14bSKonrad Rzeszutek Wilk 	int i, err = 0;
8930edc14bSKonrad Rzeszutek Wilk 	for (i = 0; field[i].size != 0; i++) {
90a92336a1SKonrad Rzeszutek Wilk 		err = xen_pcibk_config_add_field(dev, &field[i]);
9130edc14bSKonrad Rzeszutek Wilk 		if (err)
9230edc14bSKonrad Rzeszutek Wilk 			break;
9330edc14bSKonrad Rzeszutek Wilk 	}
9430edc14bSKonrad Rzeszutek Wilk 	return err;
9530edc14bSKonrad Rzeszutek Wilk }
9630edc14bSKonrad Rzeszutek Wilk 
97a92336a1SKonrad Rzeszutek Wilk static inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev,
9830edc14bSKonrad Rzeszutek Wilk 					const struct config_field *field,
9930edc14bSKonrad Rzeszutek Wilk 					unsigned int offset)
10030edc14bSKonrad Rzeszutek Wilk {
10130edc14bSKonrad Rzeszutek Wilk 	int i, err = 0;
10230edc14bSKonrad Rzeszutek Wilk 	for (i = 0; field[i].size != 0; i++) {
103a92336a1SKonrad Rzeszutek Wilk 		err = xen_pcibk_config_add_field_offset(dev, &field[i], offset);
10430edc14bSKonrad Rzeszutek Wilk 		if (err)
10530edc14bSKonrad Rzeszutek Wilk 			break;
10630edc14bSKonrad Rzeszutek Wilk 	}
10730edc14bSKonrad Rzeszutek Wilk 	return err;
10830edc14bSKonrad Rzeszutek Wilk }
10930edc14bSKonrad Rzeszutek Wilk 
11030edc14bSKonrad Rzeszutek Wilk /* Read/Write the real configuration space */
111a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value,
11230edc14bSKonrad Rzeszutek Wilk 			       void *data);
113a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value,
11430edc14bSKonrad Rzeszutek Wilk 			       void *data);
115a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value,
11630edc14bSKonrad Rzeszutek Wilk 				void *data);
117a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value,
11830edc14bSKonrad Rzeszutek Wilk 				 void *data);
119a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value,
12030edc14bSKonrad Rzeszutek Wilk 				void *data);
121a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value,
12230edc14bSKonrad Rzeszutek Wilk 				 void *data);
12330edc14bSKonrad Rzeszutek Wilk 
124a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_capability_init(void);
12530edc14bSKonrad Rzeszutek Wilk 
126a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_header_add_fields(struct pci_dev *dev);
127a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_capability_add_fields(struct pci_dev *dev);
12830edc14bSKonrad Rzeszutek Wilk 
12930edc14bSKonrad Rzeszutek Wilk #endif				/* __XEN_PCIBACK_CONF_SPACE_H__ */
130