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