130edc14bSKonrad Rzeszutek Wilk /* 230edc14bSKonrad Rzeszutek Wilk * PCI Backend - Handles the virtual fields in the configuration space headers. 330edc14bSKonrad Rzeszutek Wilk * 430edc14bSKonrad Rzeszutek Wilk * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 530edc14bSKonrad Rzeszutek Wilk */ 630edc14bSKonrad Rzeszutek Wilk 730edc14bSKonrad Rzeszutek Wilk #include <linux/kernel.h> 830edc14bSKonrad Rzeszutek Wilk #include <linux/pci.h> 930edc14bSKonrad Rzeszutek Wilk #include "pciback.h" 1030edc14bSKonrad Rzeszutek Wilk #include "conf_space.h" 1130edc14bSKonrad Rzeszutek Wilk 1230edc14bSKonrad Rzeszutek Wilk struct pci_bar_info { 1330edc14bSKonrad Rzeszutek Wilk u32 val; 1430edc14bSKonrad Rzeszutek Wilk u32 len_val; 1530edc14bSKonrad Rzeszutek Wilk int which; 1630edc14bSKonrad Rzeszutek Wilk }; 1730edc14bSKonrad Rzeszutek Wilk 18*a92336a1SKonrad Rzeszutek Wilk #define DRV_NAME "xen-pciback" 1930edc14bSKonrad Rzeszutek Wilk #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) 2030edc14bSKonrad Rzeszutek Wilk #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) 2130edc14bSKonrad Rzeszutek Wilk 22fd5b221bSZhao, Yu static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) 23fd5b221bSZhao, Yu { 24fd5b221bSZhao, Yu int i; 25fd5b221bSZhao, Yu int ret; 26fd5b221bSZhao, Yu 27*a92336a1SKonrad Rzeszutek Wilk ret = xen_pcibk_read_config_word(dev, offset, value, data); 28fd5b221bSZhao, Yu if (!atomic_read(&dev->enable_cnt)) 29fd5b221bSZhao, Yu return ret; 30fd5b221bSZhao, Yu 31fd5b221bSZhao, Yu for (i = 0; i < PCI_ROM_RESOURCE; i++) { 32fd5b221bSZhao, Yu if (dev->resource[i].flags & IORESOURCE_IO) 33fd5b221bSZhao, Yu *value |= PCI_COMMAND_IO; 34fd5b221bSZhao, Yu if (dev->resource[i].flags & IORESOURCE_MEM) 35fd5b221bSZhao, Yu *value |= PCI_COMMAND_MEMORY; 36fd5b221bSZhao, Yu } 37fd5b221bSZhao, Yu 38fd5b221bSZhao, Yu return ret; 39fd5b221bSZhao, Yu } 40fd5b221bSZhao, Yu 4130edc14bSKonrad Rzeszutek Wilk static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) 4230edc14bSKonrad Rzeszutek Wilk { 43*a92336a1SKonrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 4430edc14bSKonrad Rzeszutek Wilk int err; 4530edc14bSKonrad Rzeszutek Wilk 460513fe9eSKonrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 4730edc14bSKonrad Rzeszutek Wilk if (!pci_is_enabled(dev) && is_enable_cmd(value)) { 4830edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 49*a92336a1SKonrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: enable\n", 5030edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 5130edc14bSKonrad Rzeszutek Wilk err = pci_enable_device(dev); 5230edc14bSKonrad Rzeszutek Wilk if (err) 5330edc14bSKonrad Rzeszutek Wilk return err; 540513fe9eSKonrad Rzeszutek Wilk if (dev_data) 550513fe9eSKonrad Rzeszutek Wilk dev_data->enable_intx = 1; 5630edc14bSKonrad Rzeszutek Wilk } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { 5730edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 58*a92336a1SKonrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: disable\n", 5930edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 6030edc14bSKonrad Rzeszutek Wilk pci_disable_device(dev); 610513fe9eSKonrad Rzeszutek Wilk if (dev_data) 620513fe9eSKonrad Rzeszutek Wilk dev_data->enable_intx = 0; 6330edc14bSKonrad Rzeszutek Wilk } 6430edc14bSKonrad Rzeszutek Wilk 6530edc14bSKonrad Rzeszutek Wilk if (!dev->is_busmaster && is_master_cmd(value)) { 6630edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 67*a92336a1SKonrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n", 6830edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 6930edc14bSKonrad Rzeszutek Wilk pci_set_master(dev); 7030edc14bSKonrad Rzeszutek Wilk } 7130edc14bSKonrad Rzeszutek Wilk 7230edc14bSKonrad Rzeszutek Wilk if (value & PCI_COMMAND_INVALIDATE) { 7330edc14bSKonrad Rzeszutek Wilk if (unlikely(verbose_request)) 7430edc14bSKonrad Rzeszutek Wilk printk(KERN_DEBUG 75*a92336a1SKonrad Rzeszutek Wilk DRV_NAME ": %s: enable memory-write-invalidate\n", 7630edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 7730edc14bSKonrad Rzeszutek Wilk err = pci_set_mwi(dev); 7830edc14bSKonrad Rzeszutek Wilk if (err) { 7930edc14bSKonrad Rzeszutek Wilk printk(KERN_WARNING 80*a92336a1SKonrad Rzeszutek Wilk DRV_NAME ": %s: cannot enable " 8130edc14bSKonrad Rzeszutek Wilk "memory-write-invalidate (%d)\n", 8230edc14bSKonrad Rzeszutek Wilk pci_name(dev), err); 8330edc14bSKonrad Rzeszutek Wilk value &= ~PCI_COMMAND_INVALIDATE; 8430edc14bSKonrad Rzeszutek Wilk } 8530edc14bSKonrad Rzeszutek Wilk } 8630edc14bSKonrad Rzeszutek Wilk 8730edc14bSKonrad Rzeszutek Wilk return pci_write_config_word(dev, offset, value); 8830edc14bSKonrad Rzeszutek Wilk } 8930edc14bSKonrad Rzeszutek Wilk 9030edc14bSKonrad Rzeszutek Wilk static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data) 9130edc14bSKonrad Rzeszutek Wilk { 9230edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 9330edc14bSKonrad Rzeszutek Wilk 9430edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 95*a92336a1SKonrad Rzeszutek Wilk printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n", 9630edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 9730edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 9830edc14bSKonrad Rzeszutek Wilk } 9930edc14bSKonrad Rzeszutek Wilk 10030edc14bSKonrad Rzeszutek Wilk /* A write to obtain the length must happen as a 32-bit write. 10130edc14bSKonrad Rzeszutek Wilk * This does not (yet) support writing individual bytes 10230edc14bSKonrad Rzeszutek Wilk */ 10330edc14bSKonrad Rzeszutek Wilk if (value == ~PCI_ROM_ADDRESS_ENABLE) 10430edc14bSKonrad Rzeszutek Wilk bar->which = 1; 10530edc14bSKonrad Rzeszutek Wilk else { 10630edc14bSKonrad Rzeszutek Wilk u32 tmpval; 10730edc14bSKonrad Rzeszutek Wilk pci_read_config_dword(dev, offset, &tmpval); 10830edc14bSKonrad Rzeszutek Wilk if (tmpval != bar->val && value == bar->val) { 10930edc14bSKonrad Rzeszutek Wilk /* Allow restoration of bar value. */ 11030edc14bSKonrad Rzeszutek Wilk pci_write_config_dword(dev, offset, bar->val); 11130edc14bSKonrad Rzeszutek Wilk } 11230edc14bSKonrad Rzeszutek Wilk bar->which = 0; 11330edc14bSKonrad Rzeszutek Wilk } 11430edc14bSKonrad Rzeszutek Wilk 11530edc14bSKonrad Rzeszutek Wilk /* Do we need to support enabling/disabling the rom address here? */ 11630edc14bSKonrad Rzeszutek Wilk 11730edc14bSKonrad Rzeszutek Wilk return 0; 11830edc14bSKonrad Rzeszutek Wilk } 11930edc14bSKonrad Rzeszutek Wilk 12030edc14bSKonrad Rzeszutek Wilk /* For the BARs, only allow writes which write ~0 or 12130edc14bSKonrad Rzeszutek Wilk * the correct resource information 12230edc14bSKonrad Rzeszutek Wilk * (Needed for when the driver probes the resource usage) 12330edc14bSKonrad Rzeszutek Wilk */ 12430edc14bSKonrad Rzeszutek Wilk static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data) 12530edc14bSKonrad Rzeszutek Wilk { 12630edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 12730edc14bSKonrad Rzeszutek Wilk 12830edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 129*a92336a1SKonrad Rzeszutek Wilk printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n", 13030edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 13130edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 13230edc14bSKonrad Rzeszutek Wilk } 13330edc14bSKonrad Rzeszutek Wilk 13430edc14bSKonrad Rzeszutek Wilk /* A write to obtain the length must happen as a 32-bit write. 13530edc14bSKonrad Rzeszutek Wilk * This does not (yet) support writing individual bytes 13630edc14bSKonrad Rzeszutek Wilk */ 13730edc14bSKonrad Rzeszutek Wilk if (value == ~0) 13830edc14bSKonrad Rzeszutek Wilk bar->which = 1; 13930edc14bSKonrad Rzeszutek Wilk else { 14030edc14bSKonrad Rzeszutek Wilk u32 tmpval; 14130edc14bSKonrad Rzeszutek Wilk pci_read_config_dword(dev, offset, &tmpval); 14230edc14bSKonrad Rzeszutek Wilk if (tmpval != bar->val && value == bar->val) { 14330edc14bSKonrad Rzeszutek Wilk /* Allow restoration of bar value. */ 14430edc14bSKonrad Rzeszutek Wilk pci_write_config_dword(dev, offset, bar->val); 14530edc14bSKonrad Rzeszutek Wilk } 14630edc14bSKonrad Rzeszutek Wilk bar->which = 0; 14730edc14bSKonrad Rzeszutek Wilk } 14830edc14bSKonrad Rzeszutek Wilk 14930edc14bSKonrad Rzeszutek Wilk return 0; 15030edc14bSKonrad Rzeszutek Wilk } 15130edc14bSKonrad Rzeszutek Wilk 15230edc14bSKonrad Rzeszutek Wilk static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data) 15330edc14bSKonrad Rzeszutek Wilk { 15430edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 15530edc14bSKonrad Rzeszutek Wilk 15630edc14bSKonrad Rzeszutek Wilk if (unlikely(!bar)) { 157*a92336a1SKonrad Rzeszutek Wilk printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n", 15830edc14bSKonrad Rzeszutek Wilk pci_name(dev)); 15930edc14bSKonrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 16030edc14bSKonrad Rzeszutek Wilk } 16130edc14bSKonrad Rzeszutek Wilk 16230edc14bSKonrad Rzeszutek Wilk *value = bar->which ? bar->len_val : bar->val; 16330edc14bSKonrad Rzeszutek Wilk 16430edc14bSKonrad Rzeszutek Wilk return 0; 16530edc14bSKonrad Rzeszutek Wilk } 16630edc14bSKonrad Rzeszutek Wilk 16730edc14bSKonrad Rzeszutek Wilk static inline void read_dev_bar(struct pci_dev *dev, 16830edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar_info, int offset, 16930edc14bSKonrad Rzeszutek Wilk u32 len_mask) 17030edc14bSKonrad Rzeszutek Wilk { 171fd5b221bSZhao, Yu int pos; 172fd5b221bSZhao, Yu struct resource *res = dev->resource; 173fd5b221bSZhao, Yu 174fd5b221bSZhao, Yu if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1) 175fd5b221bSZhao, Yu pos = PCI_ROM_RESOURCE; 176fd5b221bSZhao, Yu else { 177fd5b221bSZhao, Yu pos = (offset - PCI_BASE_ADDRESS_0) / 4; 178fd5b221bSZhao, Yu if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE | 179fd5b221bSZhao, Yu PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == 180fd5b221bSZhao, Yu (PCI_BASE_ADDRESS_SPACE_MEMORY | 181fd5b221bSZhao, Yu PCI_BASE_ADDRESS_MEM_TYPE_64))) { 182fd5b221bSZhao, Yu bar_info->val = res[pos - 1].start >> 32; 183fd5b221bSZhao, Yu bar_info->len_val = res[pos - 1].end >> 32; 184fd5b221bSZhao, Yu return; 185fd5b221bSZhao, Yu } 186fd5b221bSZhao, Yu } 187fd5b221bSZhao, Yu 188fd5b221bSZhao, Yu bar_info->val = res[pos].start | 189fd5b221bSZhao, Yu (res[pos].flags & PCI_REGION_FLAG_MASK); 190fd5b221bSZhao, Yu bar_info->len_val = res[pos].end - res[pos].start + 1; 19130edc14bSKonrad Rzeszutek Wilk } 19230edc14bSKonrad Rzeszutek Wilk 19330edc14bSKonrad Rzeszutek Wilk static void *bar_init(struct pci_dev *dev, int offset) 19430edc14bSKonrad Rzeszutek Wilk { 19530edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL); 19630edc14bSKonrad Rzeszutek Wilk 19730edc14bSKonrad Rzeszutek Wilk if (!bar) 19830edc14bSKonrad Rzeszutek Wilk return ERR_PTR(-ENOMEM); 19930edc14bSKonrad Rzeszutek Wilk 20030edc14bSKonrad Rzeszutek Wilk read_dev_bar(dev, bar, offset, ~0); 20130edc14bSKonrad Rzeszutek Wilk bar->which = 0; 20230edc14bSKonrad Rzeszutek Wilk 20330edc14bSKonrad Rzeszutek Wilk return bar; 20430edc14bSKonrad Rzeszutek Wilk } 20530edc14bSKonrad Rzeszutek Wilk 20630edc14bSKonrad Rzeszutek Wilk static void *rom_init(struct pci_dev *dev, int offset) 20730edc14bSKonrad Rzeszutek Wilk { 20830edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL); 20930edc14bSKonrad Rzeszutek Wilk 21030edc14bSKonrad Rzeszutek Wilk if (!bar) 21130edc14bSKonrad Rzeszutek Wilk return ERR_PTR(-ENOMEM); 21230edc14bSKonrad Rzeszutek Wilk 21330edc14bSKonrad Rzeszutek Wilk read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE); 21430edc14bSKonrad Rzeszutek Wilk bar->which = 0; 21530edc14bSKonrad Rzeszutek Wilk 21630edc14bSKonrad Rzeszutek Wilk return bar; 21730edc14bSKonrad Rzeszutek Wilk } 21830edc14bSKonrad Rzeszutek Wilk 21930edc14bSKonrad Rzeszutek Wilk static void bar_reset(struct pci_dev *dev, int offset, void *data) 22030edc14bSKonrad Rzeszutek Wilk { 22130edc14bSKonrad Rzeszutek Wilk struct pci_bar_info *bar = data; 22230edc14bSKonrad Rzeszutek Wilk 22330edc14bSKonrad Rzeszutek Wilk bar->which = 0; 22430edc14bSKonrad Rzeszutek Wilk } 22530edc14bSKonrad Rzeszutek Wilk 22630edc14bSKonrad Rzeszutek Wilk static void bar_release(struct pci_dev *dev, int offset, void *data) 22730edc14bSKonrad Rzeszutek Wilk { 22830edc14bSKonrad Rzeszutek Wilk kfree(data); 22930edc14bSKonrad Rzeszutek Wilk } 23030edc14bSKonrad Rzeszutek Wilk 231*a92336a1SKonrad Rzeszutek Wilk static int xen_pcibk_read_vendor(struct pci_dev *dev, int offset, 232fd5b221bSZhao, Yu u16 *value, void *data) 233fd5b221bSZhao, Yu { 234fd5b221bSZhao, Yu *value = dev->vendor; 235fd5b221bSZhao, Yu 236fd5b221bSZhao, Yu return 0; 237fd5b221bSZhao, Yu } 238fd5b221bSZhao, Yu 239*a92336a1SKonrad Rzeszutek Wilk static int xen_pcibk_read_device(struct pci_dev *dev, int offset, 240fd5b221bSZhao, Yu u16 *value, void *data) 241fd5b221bSZhao, Yu { 242fd5b221bSZhao, Yu *value = dev->device; 243fd5b221bSZhao, Yu 244fd5b221bSZhao, Yu return 0; 245fd5b221bSZhao, Yu } 246fd5b221bSZhao, Yu 24730edc14bSKonrad Rzeszutek Wilk static int interrupt_read(struct pci_dev *dev, int offset, u8 * value, 24830edc14bSKonrad Rzeszutek Wilk void *data) 24930edc14bSKonrad Rzeszutek Wilk { 25030edc14bSKonrad Rzeszutek Wilk *value = (u8) dev->irq; 25130edc14bSKonrad Rzeszutek Wilk 25230edc14bSKonrad Rzeszutek Wilk return 0; 25330edc14bSKonrad Rzeszutek Wilk } 25430edc14bSKonrad Rzeszutek Wilk 25530edc14bSKonrad Rzeszutek Wilk static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data) 25630edc14bSKonrad Rzeszutek Wilk { 25730edc14bSKonrad Rzeszutek Wilk u8 cur_value; 25830edc14bSKonrad Rzeszutek Wilk int err; 25930edc14bSKonrad Rzeszutek Wilk 26030edc14bSKonrad Rzeszutek Wilk err = pci_read_config_byte(dev, offset, &cur_value); 26130edc14bSKonrad Rzeszutek Wilk if (err) 26230edc14bSKonrad Rzeszutek Wilk goto out; 26330edc14bSKonrad Rzeszutek Wilk 26430edc14bSKonrad Rzeszutek Wilk if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START) 26530edc14bSKonrad Rzeszutek Wilk || value == PCI_BIST_START) 26630edc14bSKonrad Rzeszutek Wilk err = pci_write_config_byte(dev, offset, value); 26730edc14bSKonrad Rzeszutek Wilk 26830edc14bSKonrad Rzeszutek Wilk out: 26930edc14bSKonrad Rzeszutek Wilk return err; 27030edc14bSKonrad Rzeszutek Wilk } 27130edc14bSKonrad Rzeszutek Wilk 27230edc14bSKonrad Rzeszutek Wilk static const struct config_field header_common[] = { 27330edc14bSKonrad Rzeszutek Wilk { 274fd5b221bSZhao, Yu .offset = PCI_VENDOR_ID, 275fd5b221bSZhao, Yu .size = 2, 276*a92336a1SKonrad Rzeszutek Wilk .u.w.read = xen_pcibk_read_vendor, 277fd5b221bSZhao, Yu }, 278fd5b221bSZhao, Yu { 279fd5b221bSZhao, Yu .offset = PCI_DEVICE_ID, 280fd5b221bSZhao, Yu .size = 2, 281*a92336a1SKonrad Rzeszutek Wilk .u.w.read = xen_pcibk_read_device, 282fd5b221bSZhao, Yu }, 283fd5b221bSZhao, Yu { 28430edc14bSKonrad Rzeszutek Wilk .offset = PCI_COMMAND, 28530edc14bSKonrad Rzeszutek Wilk .size = 2, 286fd5b221bSZhao, Yu .u.w.read = command_read, 28730edc14bSKonrad Rzeszutek Wilk .u.w.write = command_write, 28830edc14bSKonrad Rzeszutek Wilk }, 28930edc14bSKonrad Rzeszutek Wilk { 29030edc14bSKonrad Rzeszutek Wilk .offset = PCI_INTERRUPT_LINE, 29130edc14bSKonrad Rzeszutek Wilk .size = 1, 29230edc14bSKonrad Rzeszutek Wilk .u.b.read = interrupt_read, 29330edc14bSKonrad Rzeszutek Wilk }, 29430edc14bSKonrad Rzeszutek Wilk { 29530edc14bSKonrad Rzeszutek Wilk .offset = PCI_INTERRUPT_PIN, 29630edc14bSKonrad Rzeszutek Wilk .size = 1, 297*a92336a1SKonrad Rzeszutek Wilk .u.b.read = xen_pcibk_read_config_byte, 29830edc14bSKonrad Rzeszutek Wilk }, 29930edc14bSKonrad Rzeszutek Wilk { 30030edc14bSKonrad Rzeszutek Wilk /* Any side effects of letting driver domain control cache line? */ 30130edc14bSKonrad Rzeszutek Wilk .offset = PCI_CACHE_LINE_SIZE, 30230edc14bSKonrad Rzeszutek Wilk .size = 1, 303*a92336a1SKonrad Rzeszutek Wilk .u.b.read = xen_pcibk_read_config_byte, 304*a92336a1SKonrad Rzeszutek Wilk .u.b.write = xen_pcibk_write_config_byte, 30530edc14bSKonrad Rzeszutek Wilk }, 30630edc14bSKonrad Rzeszutek Wilk { 30730edc14bSKonrad Rzeszutek Wilk .offset = PCI_LATENCY_TIMER, 30830edc14bSKonrad Rzeszutek Wilk .size = 1, 309*a92336a1SKonrad Rzeszutek Wilk .u.b.read = xen_pcibk_read_config_byte, 31030edc14bSKonrad Rzeszutek Wilk }, 31130edc14bSKonrad Rzeszutek Wilk { 31230edc14bSKonrad Rzeszutek Wilk .offset = PCI_BIST, 31330edc14bSKonrad Rzeszutek Wilk .size = 1, 314*a92336a1SKonrad Rzeszutek Wilk .u.b.read = xen_pcibk_read_config_byte, 31530edc14bSKonrad Rzeszutek Wilk .u.b.write = bist_write, 31630edc14bSKonrad Rzeszutek Wilk }, 31730edc14bSKonrad Rzeszutek Wilk {} 31830edc14bSKonrad Rzeszutek Wilk }; 31930edc14bSKonrad Rzeszutek Wilk 32030edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_BAR(reg_offset) \ 32130edc14bSKonrad Rzeszutek Wilk { \ 32230edc14bSKonrad Rzeszutek Wilk .offset = reg_offset, \ 32330edc14bSKonrad Rzeszutek Wilk .size = 4, \ 32430edc14bSKonrad Rzeszutek Wilk .init = bar_init, \ 32530edc14bSKonrad Rzeszutek Wilk .reset = bar_reset, \ 32630edc14bSKonrad Rzeszutek Wilk .release = bar_release, \ 32730edc14bSKonrad Rzeszutek Wilk .u.dw.read = bar_read, \ 32830edc14bSKonrad Rzeszutek Wilk .u.dw.write = bar_write, \ 32930edc14bSKonrad Rzeszutek Wilk } 33030edc14bSKonrad Rzeszutek Wilk 33130edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_ROM(reg_offset) \ 33230edc14bSKonrad Rzeszutek Wilk { \ 33330edc14bSKonrad Rzeszutek Wilk .offset = reg_offset, \ 33430edc14bSKonrad Rzeszutek Wilk .size = 4, \ 33530edc14bSKonrad Rzeszutek Wilk .init = rom_init, \ 33630edc14bSKonrad Rzeszutek Wilk .reset = bar_reset, \ 33730edc14bSKonrad Rzeszutek Wilk .release = bar_release, \ 33830edc14bSKonrad Rzeszutek Wilk .u.dw.read = bar_read, \ 33930edc14bSKonrad Rzeszutek Wilk .u.dw.write = rom_write, \ 34030edc14bSKonrad Rzeszutek Wilk } 34130edc14bSKonrad Rzeszutek Wilk 34230edc14bSKonrad Rzeszutek Wilk static const struct config_field header_0[] = { 34330edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_0), 34430edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_1), 34530edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_2), 34630edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_3), 34730edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_4), 34830edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_5), 34930edc14bSKonrad Rzeszutek Wilk CFG_FIELD_ROM(PCI_ROM_ADDRESS), 35030edc14bSKonrad Rzeszutek Wilk {} 35130edc14bSKonrad Rzeszutek Wilk }; 35230edc14bSKonrad Rzeszutek Wilk 35330edc14bSKonrad Rzeszutek Wilk static const struct config_field header_1[] = { 35430edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_0), 35530edc14bSKonrad Rzeszutek Wilk CFG_FIELD_BAR(PCI_BASE_ADDRESS_1), 35630edc14bSKonrad Rzeszutek Wilk CFG_FIELD_ROM(PCI_ROM_ADDRESS1), 35730edc14bSKonrad Rzeszutek Wilk {} 35830edc14bSKonrad Rzeszutek Wilk }; 35930edc14bSKonrad Rzeszutek Wilk 360*a92336a1SKonrad Rzeszutek Wilk int xen_pcibk_config_header_add_fields(struct pci_dev *dev) 36130edc14bSKonrad Rzeszutek Wilk { 36230edc14bSKonrad Rzeszutek Wilk int err; 36330edc14bSKonrad Rzeszutek Wilk 364*a92336a1SKonrad Rzeszutek Wilk err = xen_pcibk_config_add_fields(dev, header_common); 36530edc14bSKonrad Rzeszutek Wilk if (err) 36630edc14bSKonrad Rzeszutek Wilk goto out; 36730edc14bSKonrad Rzeszutek Wilk 36830edc14bSKonrad Rzeszutek Wilk switch (dev->hdr_type) { 36930edc14bSKonrad Rzeszutek Wilk case PCI_HEADER_TYPE_NORMAL: 370*a92336a1SKonrad Rzeszutek Wilk err = xen_pcibk_config_add_fields(dev, header_0); 37130edc14bSKonrad Rzeszutek Wilk break; 37230edc14bSKonrad Rzeszutek Wilk 37330edc14bSKonrad Rzeszutek Wilk case PCI_HEADER_TYPE_BRIDGE: 374*a92336a1SKonrad Rzeszutek Wilk err = xen_pcibk_config_add_fields(dev, header_1); 37530edc14bSKonrad Rzeszutek Wilk break; 37630edc14bSKonrad Rzeszutek Wilk 37730edc14bSKonrad Rzeszutek Wilk default: 37830edc14bSKonrad Rzeszutek Wilk err = -EINVAL; 379*a92336a1SKonrad Rzeszutek Wilk printk(KERN_ERR DRV_NAME ": %s: Unsupported header type %d!\n", 38030edc14bSKonrad Rzeszutek Wilk pci_name(dev), dev->hdr_type); 38130edc14bSKonrad Rzeszutek Wilk break; 38230edc14bSKonrad Rzeszutek Wilk } 38330edc14bSKonrad Rzeszutek Wilk 38430edc14bSKonrad Rzeszutek Wilk out: 38530edc14bSKonrad Rzeszutek Wilk return err; 38630edc14bSKonrad Rzeszutek Wilk } 387