linux/drivers/xen/xen-pciback/conf_space.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * PCI Backend - Common data structures for overriding the configuration space
   4 *
   5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
   6 */
   7
   8#ifndef __XEN_PCIBACK_CONF_SPACE_H__
   9#define __XEN_PCIBACK_CONF_SPACE_H__
  10
  11#include <linux/list.h>
  12#include <linux/err.h>
  13
  14/* conf_field_init can return an errno in a ptr with ERR_PTR() */
  15typedef void *(*conf_field_init) (struct pci_dev *dev, int offset);
  16typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data);
  17typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data);
  18
  19typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value,
  20                                 void *data);
  21typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value,
  22                                void *data);
  23typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value,
  24                                void *data);
  25typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value,
  26                                void *data);
  27typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value,
  28                               void *data);
  29typedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value,
  30                               void *data);
  31
  32/* These are the fields within the configuration space which we
  33 * are interested in intercepting reads/writes to and changing their
  34 * values.
  35 */
  36struct config_field {
  37        unsigned int offset;
  38        unsigned int size;
  39        unsigned int mask;
  40        conf_field_init init;
  41        conf_field_reset reset;
  42        conf_field_free release;
  43        void (*clean) (struct config_field *field);
  44        union {
  45                struct {
  46                        conf_dword_write write;
  47                        conf_dword_read read;
  48                } dw;
  49                struct {
  50                        conf_word_write write;
  51                        conf_word_read read;
  52                } w;
  53                struct {
  54                        conf_byte_write write;
  55                        conf_byte_read read;
  56                } b;
  57        } u;
  58        struct list_head list;
  59};
  60
  61struct config_field_entry {
  62        struct list_head list;
  63        const struct config_field *field;
  64        unsigned int base_offset;
  65        void *data;
  66};
  67
  68#define INTERRUPT_TYPE_NONE (0)
  69#define INTERRUPT_TYPE_INTX (1<<0)
  70#define INTERRUPT_TYPE_MSI  (1<<1)
  71#define INTERRUPT_TYPE_MSIX (1<<2)
  72
  73extern bool xen_pcibk_permissive;
  74
  75#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
  76
  77/* Add fields to a device - the add_fields macro expects to get a pointer to
  78 * the first entry in an array (of which the ending is marked by size==0)
  79 */
  80int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
  81                                    const struct config_field *field,
  82                                    unsigned int offset);
  83
  84static inline int xen_pcibk_config_add_field(struct pci_dev *dev,
  85                                           const struct config_field *field)
  86{
  87        return xen_pcibk_config_add_field_offset(dev, field, 0);
  88}
  89
  90static inline int xen_pcibk_config_add_fields(struct pci_dev *dev,
  91                                            const struct config_field *field)
  92{
  93        int i, err = 0;
  94        for (i = 0; field[i].size != 0; i++) {
  95                err = xen_pcibk_config_add_field(dev, &field[i]);
  96                if (err)
  97                        break;
  98        }
  99        return err;
 100}
 101
 102static inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev,
 103                                        const struct config_field *field,
 104                                        unsigned int offset)
 105{
 106        int i, err = 0;
 107        for (i = 0; field[i].size != 0; i++) {
 108                err = xen_pcibk_config_add_field_offset(dev, &field[i], offset);
 109                if (err)
 110                        break;
 111        }
 112        return err;
 113}
 114
 115/* Read/Write the real configuration space */
 116int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value,
 117                               void *data);
 118int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value,
 119                               void *data);
 120int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value,
 121                                void *data);
 122int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value,
 123                                 void *data);
 124int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value,
 125                                void *data);
 126int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value,
 127                                 void *data);
 128
 129int xen_pcibk_config_capability_init(void);
 130
 131int xen_pcibk_config_header_add_fields(struct pci_dev *dev);
 132int xen_pcibk_config_capability_add_fields(struct pci_dev *dev);
 133
 134int xen_pcibk_get_interrupt_type(struct pci_dev *dev);
 135
 136#endif                          /* __XEN_PCIBACK_CONF_SPACE_H__ */
 137