130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/*
230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * PCI Backend - Common data structures for overriding the configuration space
330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk *
430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */
630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#ifndef __XEN_PCIBACK_CONF_SPACE_H__
830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#define __XEN_PCIBACK_CONF_SPACE_H__
930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
1030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/list.h>
1130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/err.h>
1230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
1330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* conf_field_init can return an errno in a ptr with ERR_PTR() */
1430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef void *(*conf_field_init) (struct pci_dev *dev, int offset);
1530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data);
1630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data);
1730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
1830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value,
1930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				 void *data);
2030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value,
2130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				void *data);
2230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value,
2330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				void *data);
2430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value,
2530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				void *data);
2630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value,
2730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			       void *data);
2830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilktypedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value,
2930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			       void *data);
3030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
3130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* These are the fields within the configuration space which we
3230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * are interested in intercepting reads/writes to and changing their
3330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * values.
3430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */
3530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkstruct config_field {
3630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	unsigned int offset;
3730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	unsigned int size;
3830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	unsigned int mask;
3930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	conf_field_init init;
4030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	conf_field_reset reset;
4130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	conf_field_free release;
4230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	void (*clean) (struct config_field *field);
4330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	union {
4430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		struct {
4530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_dword_write write;
4630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_dword_read read;
4730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		} dw;
4830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		struct {
4930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_word_write write;
5030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_word_read read;
5130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		} w;
5230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		struct {
5330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_byte_write write;
5430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			conf_byte_read read;
5530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		} b;
5630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	} u;
5730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	struct list_head list;
5830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk};
5930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
6030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkstruct config_field_entry {
6130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	struct list_head list;
6230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	const struct config_field *field;
6330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	unsigned int base_offset;
6430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	void *data;
6530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk};
6630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
6730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
6830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
6930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* Add fields to a device - the add_fields macro expects to get a pointer to
7030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * the first entry in an array (of which the ending is marked by size==0)
7130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */
72a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_config_add_field_offset(struct pci_dev *dev,
7330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				    const struct config_field *field,
7430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk				    unsigned int offset);
7530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
76a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic inline int xen_pcibk_config_add_field(struct pci_dev *dev,
7730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk					   const struct config_field *field)
7830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{
79a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk	return xen_pcibk_config_add_field_offset(dev, field, 0);
8030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}
8130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
82a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic inline int xen_pcibk_config_add_fields(struct pci_dev *dev,
8330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk					    const struct config_field *field)
8430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{
8530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	int i, err = 0;
8630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	for (i = 0; field[i].size != 0; i++) {
87a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk		err = xen_pcibk_config_add_field(dev, &field[i]);
8830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		if (err)
8930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			break;
9030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	}
9130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	return err;
9230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}
9330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
94a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev,
9530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk					const struct config_field *field,
9630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk					unsigned int offset)
9730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{
9830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	int i, err = 0;
9930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	for (i = 0; field[i].size != 0; i++) {
100a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk		err = xen_pcibk_config_add_field_offset(dev, &field[i], offset);
10130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk		if (err)
10230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			break;
10330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	}
10430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk	return err;
10530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}
10630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
10730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* Read/Write the real configuration space */
108a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value,
10930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk			       void *data);
110a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value,
111a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk			       void *data);
112a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value,
113a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk				void *data);
114a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value,
115a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk				 void *data);
116a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value,
117a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk				void *data);
118a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value,
119a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk				 void *data);
12030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
121a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_config_capability_init(void);
12230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
123a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_config_header_add_fields(struct pci_dev *dev);
124a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_config_capability_add_fields(struct pci_dev *dev);
12530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk
12630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#endif				/* __XEN_PCIBACK_CONF_SPACE_H__ */
127